mirror of
https://github.com/garethgeorge/backrest.git
synced 2025-12-17 19:15:38 +00:00
feat: implement repo, edit, and supporting RPCs
This commit is contained in:
@@ -10,7 +10,9 @@ import (
|
|||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
"github.com/garethgeorge/resticui/internal/api"
|
"github.com/garethgeorge/resticui/internal/api"
|
||||||
"github.com/garethgeorge/resticui/static"
|
"github.com/garethgeorge/resticui/internal/config"
|
||||||
|
"github.com/garethgeorge/resticui/internal/orchestrator"
|
||||||
|
static "github.com/garethgeorge/resticui/webui"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
|
|
||||||
_ "embed"
|
_ "embed"
|
||||||
@@ -21,6 +23,10 @@ func main() {
|
|||||||
ctx, cancel := context.WithCancel(ctx)
|
ctx, cancel := context.WithCancel(ctx)
|
||||||
go onterm(cancel)
|
go onterm(cancel)
|
||||||
|
|
||||||
|
if _, err := config.Default.Get(); err != nil {
|
||||||
|
zap.S().Fatalf("Error loading config: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
var wg sync.WaitGroup
|
var wg sync.WaitGroup
|
||||||
|
|
||||||
// Configure the HTTP mux
|
// Configure the HTTP mux
|
||||||
@@ -32,11 +38,13 @@ func main() {
|
|||||||
Handler: mux,
|
Handler: mux,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
orchestrator := orchestrator.NewOrchestrator(config.Default)
|
||||||
|
|
||||||
// Serve the API
|
// Serve the API
|
||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
go func() {
|
go func() {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
err := api.ServeAPI(ctx, mux)
|
err := api.ServeAPI(ctx, orchestrator, mux)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
zap.S().Fatal("Error serving API", zap.Error(err))
|
zap.S().Fatal("Error serving API", zap.Error(err))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,7 +25,10 @@ type Config struct {
|
|||||||
sizeCache protoimpl.SizeCache
|
sizeCache protoimpl.SizeCache
|
||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
|
|
||||||
Version int32 `protobuf:"varint,1,opt,name=version,proto3" json:"version,omitempty"`
|
// modification number, used for read-modify-write consistency in the UI. Incremented on every write.
|
||||||
|
Modno int32 `protobuf:"varint,1,opt,name=modno,proto3" json:"modno,omitempty"`
|
||||||
|
// override the hostname tagged on backups. If provided it will be used in addition to tags to group backups.
|
||||||
|
HostOverride string `protobuf:"bytes,2,opt,name=host_override,proto3" json:"host_override,omitempty"`
|
||||||
Repos []*Repo `protobuf:"bytes,3,rep,name=repos,proto3" json:"repos,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"`
|
Plans []*Plan `protobuf:"bytes,4,rep,name=plans,proto3" json:"plans,omitempty"`
|
||||||
}
|
}
|
||||||
@@ -62,13 +65,20 @@ func (*Config) Descriptor() ([]byte, []int) {
|
|||||||
return file_v1_config_proto_rawDescGZIP(), []int{0}
|
return file_v1_config_proto_rawDescGZIP(), []int{0}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *Config) GetVersion() int32 {
|
func (x *Config) GetModno() int32 {
|
||||||
if x != nil {
|
if x != nil {
|
||||||
return x.Version
|
return x.Modno
|
||||||
}
|
}
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (x *Config) GetHostOverride() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.HostOverride
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
func (x *Config) GetRepos() []*Repo {
|
func (x *Config) GetRepos() []*Repo {
|
||||||
if x != nil {
|
if x != nil {
|
||||||
return x.Repos
|
return x.Repos
|
||||||
@@ -83,61 +93,6 @@ func (x *Config) GetPlans() []*Plan {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type User struct {
|
|
||||||
state protoimpl.MessageState
|
|
||||||
sizeCache protoimpl.SizeCache
|
|
||||||
unknownFields protoimpl.UnknownFields
|
|
||||||
|
|
||||||
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
|
|
||||||
Password string `protobuf:"bytes,2,opt,name=password,proto3" json:"password,omitempty"` // plaintext password
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *User) Reset() {
|
|
||||||
*x = User{}
|
|
||||||
if protoimpl.UnsafeEnabled {
|
|
||||||
mi := &file_v1_config_proto_msgTypes[1]
|
|
||||||
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[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 User.ProtoReflect.Descriptor instead.
|
|
||||||
func (*User) Descriptor() ([]byte, []int) {
|
|
||||||
return file_v1_config_proto_rawDescGZIP(), []int{1}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *User) GetName() string {
|
|
||||||
if x != nil {
|
|
||||||
return x.Name
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *User) GetPassword() string {
|
|
||||||
if x != nil {
|
|
||||||
return x.Password
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
type Repo struct {
|
type Repo struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState
|
||||||
sizeCache protoimpl.SizeCache
|
sizeCache protoimpl.SizeCache
|
||||||
@@ -153,7 +108,7 @@ type Repo struct {
|
|||||||
func (x *Repo) Reset() {
|
func (x *Repo) Reset() {
|
||||||
*x = Repo{}
|
*x = Repo{}
|
||||||
if protoimpl.UnsafeEnabled {
|
if protoimpl.UnsafeEnabled {
|
||||||
mi := &file_v1_config_proto_msgTypes[2]
|
mi := &file_v1_config_proto_msgTypes[1]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
@@ -166,7 +121,7 @@ func (x *Repo) String() string {
|
|||||||
func (*Repo) ProtoMessage() {}
|
func (*Repo) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *Repo) ProtoReflect() protoreflect.Message {
|
func (x *Repo) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_v1_config_proto_msgTypes[2]
|
mi := &file_v1_config_proto_msgTypes[1]
|
||||||
if protoimpl.UnsafeEnabled && x != nil {
|
if protoimpl.UnsafeEnabled && x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
@@ -179,7 +134,7 @@ func (x *Repo) ProtoReflect() protoreflect.Message {
|
|||||||
|
|
||||||
// Deprecated: Use Repo.ProtoReflect.Descriptor instead.
|
// Deprecated: Use Repo.ProtoReflect.Descriptor instead.
|
||||||
func (*Repo) Descriptor() ([]byte, []int) {
|
func (*Repo) Descriptor() ([]byte, []int) {
|
||||||
return file_v1_config_proto_rawDescGZIP(), []int{2}
|
return file_v1_config_proto_rawDescGZIP(), []int{1}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *Repo) GetId() string {
|
func (x *Repo) GetId() string {
|
||||||
@@ -233,7 +188,7 @@ type Plan struct {
|
|||||||
func (x *Plan) Reset() {
|
func (x *Plan) Reset() {
|
||||||
*x = Plan{}
|
*x = Plan{}
|
||||||
if protoimpl.UnsafeEnabled {
|
if protoimpl.UnsafeEnabled {
|
||||||
mi := &file_v1_config_proto_msgTypes[3]
|
mi := &file_v1_config_proto_msgTypes[2]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
@@ -246,7 +201,7 @@ func (x *Plan) String() string {
|
|||||||
func (*Plan) ProtoMessage() {}
|
func (*Plan) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *Plan) ProtoReflect() protoreflect.Message {
|
func (x *Plan) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_v1_config_proto_msgTypes[3]
|
mi := &file_v1_config_proto_msgTypes[2]
|
||||||
if protoimpl.UnsafeEnabled && x != nil {
|
if protoimpl.UnsafeEnabled && x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
@@ -259,7 +214,7 @@ func (x *Plan) ProtoReflect() protoreflect.Message {
|
|||||||
|
|
||||||
// Deprecated: Use Plan.ProtoReflect.Descriptor instead.
|
// Deprecated: Use Plan.ProtoReflect.Descriptor instead.
|
||||||
func (*Plan) Descriptor() ([]byte, []int) {
|
func (*Plan) Descriptor() ([]byte, []int) {
|
||||||
return file_v1_config_proto_rawDescGZIP(), []int{3}
|
return file_v1_config_proto_rawDescGZIP(), []int{2}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *Plan) GetId() string {
|
func (x *Plan) GetId() string {
|
||||||
@@ -323,7 +278,7 @@ type RetentionPolicy struct {
|
|||||||
func (x *RetentionPolicy) Reset() {
|
func (x *RetentionPolicy) Reset() {
|
||||||
*x = RetentionPolicy{}
|
*x = RetentionPolicy{}
|
||||||
if protoimpl.UnsafeEnabled {
|
if protoimpl.UnsafeEnabled {
|
||||||
mi := &file_v1_config_proto_msgTypes[4]
|
mi := &file_v1_config_proto_msgTypes[3]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
@@ -336,7 +291,7 @@ func (x *RetentionPolicy) String() string {
|
|||||||
func (*RetentionPolicy) ProtoMessage() {}
|
func (*RetentionPolicy) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *RetentionPolicy) ProtoReflect() protoreflect.Message {
|
func (x *RetentionPolicy) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_v1_config_proto_msgTypes[4]
|
mi := &file_v1_config_proto_msgTypes[3]
|
||||||
if protoimpl.UnsafeEnabled && x != nil {
|
if protoimpl.UnsafeEnabled && x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
@@ -349,7 +304,7 @@ func (x *RetentionPolicy) ProtoReflect() protoreflect.Message {
|
|||||||
|
|
||||||
// Deprecated: Use RetentionPolicy.ProtoReflect.Descriptor instead.
|
// Deprecated: Use RetentionPolicy.ProtoReflect.Descriptor instead.
|
||||||
func (*RetentionPolicy) Descriptor() ([]byte, []int) {
|
func (*RetentionPolicy) Descriptor() ([]byte, []int) {
|
||||||
return file_v1_config_proto_rawDescGZIP(), []int{4}
|
return file_v1_config_proto_rawDescGZIP(), []int{3}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *RetentionPolicy) GetMaxUnusedLimit() string {
|
func (x *RetentionPolicy) GetMaxUnusedLimit() string {
|
||||||
@@ -412,57 +367,55 @@ var File_v1_config_proto protoreflect.FileDescriptor
|
|||||||
|
|
||||||
var file_v1_config_proto_rawDesc = []byte{
|
var file_v1_config_proto_rawDesc = []byte{
|
||||||
0x0a, 0x0f, 0x76, 0x31, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74,
|
0x0a, 0x0f, 0x76, 0x31, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74,
|
||||||
0x6f, 0x12, 0x02, 0x76, 0x31, 0x22, 0x62, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12,
|
0x6f, 0x12, 0x02, 0x76, 0x31, 0x22, 0x84, 0x01, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
|
||||||
0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05,
|
0x12, 0x14, 0x0a, 0x05, 0x6d, 0x6f, 0x64, 0x6e, 0x6f, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52,
|
||||||
0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1e, 0x0a, 0x05, 0x72, 0x65, 0x70,
|
0x05, 0x6d, 0x6f, 0x64, 0x6e, 0x6f, 0x12, 0x24, 0x0a, 0x0d, 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x6f,
|
||||||
0x6f, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x08, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65,
|
0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x68,
|
||||||
0x70, 0x6f, 0x52, 0x05, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x12, 0x1e, 0x0a, 0x05, 0x70, 0x6c, 0x61,
|
0x6f, 0x73, 0x74, 0x5f, 0x6f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x12, 0x1e, 0x0a, 0x05,
|
||||||
0x6e, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x08, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6c,
|
0x72, 0x65, 0x70, 0x6f, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x08, 0x2e, 0x76, 0x31,
|
||||||
0x61, 0x6e, 0x52, 0x05, 0x70, 0x6c, 0x61, 0x6e, 0x73, 0x22, 0x36, 0x0a, 0x04, 0x55, 0x73, 0x65,
|
0x2e, 0x52, 0x65, 0x70, 0x6f, 0x52, 0x05, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x12, 0x1e, 0x0a, 0x05,
|
||||||
0x72, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
|
0x70, 0x6c, 0x61, 0x6e, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x08, 0x2e, 0x76, 0x31,
|
||||||
0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72,
|
0x2e, 0x50, 0x6c, 0x61, 0x6e, 0x52, 0x05, 0x70, 0x6c, 0x61, 0x6e, 0x73, 0x22, 0x6c, 0x0a, 0x04,
|
||||||
0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72,
|
0x52, 0x65, 0x70, 0x6f, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
|
||||||
0x64, 0x22, 0x6c, 0x0a, 0x04, 0x52, 0x65, 0x70, 0x6f, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18,
|
0x52, 0x02, 0x69, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, 0x69, 0x18, 0x02, 0x20, 0x01, 0x28,
|
||||||
0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, 0x69,
|
0x09, 0x52, 0x03, 0x75, 0x72, 0x69, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f,
|
||||||
0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x69, 0x12, 0x1a, 0x0a, 0x08, 0x70,
|
0x72, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f,
|
||||||
0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70,
|
0x72, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x65, 0x6e, 0x76, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52,
|
||||||
0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x65, 0x6e, 0x76, 0x18, 0x04,
|
0x03, 0x65, 0x6e, 0x76, 0x12, 0x14, 0x0a, 0x05, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x18, 0x05, 0x20,
|
||||||
0x20, 0x03, 0x28, 0x09, 0x52, 0x03, 0x65, 0x6e, 0x76, 0x12, 0x14, 0x0a, 0x05, 0x66, 0x6c, 0x61,
|
0x03, 0x28, 0x09, 0x52, 0x05, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x22, 0xa3, 0x01, 0x0a, 0x04, 0x50,
|
||||||
0x67, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x22,
|
0x6c, 0x61, 0x6e, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
|
||||||
0xa3, 0x01, 0x0a, 0x04, 0x50, 0x6c, 0x61, 0x6e, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01,
|
0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x72, 0x65, 0x70, 0x6f, 0x18, 0x02, 0x20, 0x01, 0x28,
|
||||||
0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x72, 0x65, 0x70, 0x6f,
|
0x09, 0x52, 0x04, 0x72, 0x65, 0x70, 0x6f, 0x12, 0x14, 0x0a, 0x05, 0x70, 0x61, 0x74, 0x68, 0x73,
|
||||||
0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x72, 0x65, 0x70, 0x6f, 0x12, 0x14, 0x0a, 0x05,
|
0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x70, 0x61, 0x74, 0x68, 0x73, 0x12, 0x1a, 0x0a,
|
||||||
0x70, 0x61, 0x74, 0x68, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x70, 0x61, 0x74,
|
0x08, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52,
|
||||||
0x68, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x73, 0x18, 0x05,
|
0x08, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x72, 0x6f,
|
||||||
0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x73, 0x12, 0x12,
|
0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x63, 0x72, 0x6f, 0x6e, 0x12, 0x31, 0x0a,
|
||||||
0x0a, 0x04, 0x63, 0x72, 0x6f, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x63, 0x72,
|
0x09, 0x72, 0x65, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b,
|
||||||
0x6f, 0x6e, 0x12, 0x31, 0x0a, 0x09, 0x72, 0x65, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x18,
|
0x32, 0x13, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x50,
|
||||||
0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x74, 0x65, 0x6e,
|
0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x09, 0x72, 0x65, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e,
|
||||||
0x74, 0x69, 0x6f, 0x6e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x09, 0x72, 0x65, 0x74, 0x65,
|
0x22, 0xb2, 0x02, 0x0a, 0x0f, 0x52, 0x65, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x6f,
|
||||||
0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0xb2, 0x02, 0x0a, 0x0f, 0x52, 0x65, 0x74, 0x65, 0x6e, 0x74,
|
0x6c, 0x69, 0x63, 0x79, 0x12, 0x28, 0x0a, 0x10, 0x6d, 0x61, 0x78, 0x5f, 0x75, 0x6e, 0x75, 0x73,
|
||||||
0x69, 0x6f, 0x6e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x28, 0x0a, 0x10, 0x6d, 0x61, 0x78,
|
0x65, 0x64, 0x5f, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e,
|
||||||
0x5f, 0x75, 0x6e, 0x75, 0x73, 0x65, 0x64, 0x5f, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, 0x01, 0x20,
|
0x6d, 0x61, 0x78, 0x55, 0x6e, 0x75, 0x73, 0x65, 0x64, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x1e,
|
||||||
0x01, 0x28, 0x09, 0x52, 0x0e, 0x6d, 0x61, 0x78, 0x55, 0x6e, 0x75, 0x73, 0x65, 0x64, 0x4c, 0x69,
|
0x0a, 0x0b, 0x6b, 0x65, 0x65, 0x70, 0x5f, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x6e, 0x18, 0x02, 0x20,
|
||||||
0x6d, 0x69, 0x74, 0x12, 0x1e, 0x0a, 0x0b, 0x6b, 0x65, 0x65, 0x70, 0x5f, 0x6c, 0x61, 0x73, 0x74,
|
0x01, 0x28, 0x05, 0x52, 0x09, 0x6b, 0x65, 0x65, 0x70, 0x4c, 0x61, 0x73, 0x74, 0x4e, 0x12, 0x1f,
|
||||||
0x5f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x6b, 0x65, 0x65, 0x70, 0x4c, 0x61,
|
0x0a, 0x0b, 0x6b, 0x65, 0x65, 0x70, 0x5f, 0x68, 0x6f, 0x75, 0x72, 0x6c, 0x79, 0x18, 0x03, 0x20,
|
||||||
0x73, 0x74, 0x4e, 0x12, 0x1f, 0x0a, 0x0b, 0x6b, 0x65, 0x65, 0x70, 0x5f, 0x68, 0x6f, 0x75, 0x72,
|
0x01, 0x28, 0x05, 0x52, 0x0a, 0x6b, 0x65, 0x65, 0x70, 0x48, 0x6f, 0x75, 0x72, 0x6c, 0x79, 0x12,
|
||||||
0x6c, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x6b, 0x65, 0x65, 0x70, 0x48, 0x6f,
|
0x1d, 0x0a, 0x0a, 0x6b, 0x65, 0x65, 0x70, 0x5f, 0x64, 0x61, 0x69, 0x6c, 0x79, 0x18, 0x04, 0x20,
|
||||||
0x75, 0x72, 0x6c, 0x79, 0x12, 0x1d, 0x0a, 0x0a, 0x6b, 0x65, 0x65, 0x70, 0x5f, 0x64, 0x61, 0x69,
|
0x01, 0x28, 0x05, 0x52, 0x09, 0x6b, 0x65, 0x65, 0x70, 0x44, 0x61, 0x69, 0x6c, 0x79, 0x12, 0x1f,
|
||||||
0x6c, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x6b, 0x65, 0x65, 0x70, 0x44, 0x61,
|
0x0a, 0x0b, 0x6b, 0x65, 0x65, 0x70, 0x5f, 0x77, 0x65, 0x65, 0x6b, 0x6c, 0x79, 0x18, 0x05, 0x20,
|
||||||
0x69, 0x6c, 0x79, 0x12, 0x1f, 0x0a, 0x0b, 0x6b, 0x65, 0x65, 0x70, 0x5f, 0x77, 0x65, 0x65, 0x6b,
|
0x01, 0x28, 0x05, 0x52, 0x0a, 0x6b, 0x65, 0x65, 0x70, 0x57, 0x65, 0x65, 0x6b, 0x6c, 0x79, 0x12,
|
||||||
0x6c, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x6b, 0x65, 0x65, 0x70, 0x57, 0x65,
|
0x21, 0x0a, 0x0c, 0x6b, 0x65, 0x65, 0x70, 0x5f, 0x6d, 0x6f, 0x6e, 0x74, 0x68, 0x6c, 0x79, 0x18,
|
||||||
0x65, 0x6b, 0x6c, 0x79, 0x12, 0x21, 0x0a, 0x0c, 0x6b, 0x65, 0x65, 0x70, 0x5f, 0x6d, 0x6f, 0x6e,
|
0x06, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b, 0x6b, 0x65, 0x65, 0x70, 0x4d, 0x6f, 0x6e, 0x74, 0x68,
|
||||||
0x74, 0x68, 0x6c, 0x79, 0x18, 0x06, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b, 0x6b, 0x65, 0x65, 0x70,
|
0x6c, 0x79, 0x12, 0x1f, 0x0a, 0x0b, 0x6b, 0x65, 0x65, 0x70, 0x5f, 0x79, 0x65, 0x61, 0x72, 0x6c,
|
||||||
0x4d, 0x6f, 0x6e, 0x74, 0x68, 0x6c, 0x79, 0x12, 0x1f, 0x0a, 0x0b, 0x6b, 0x65, 0x65, 0x70, 0x5f,
|
0x79, 0x18, 0x07, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x6b, 0x65, 0x65, 0x70, 0x59, 0x65, 0x61,
|
||||||
0x79, 0x65, 0x61, 0x72, 0x6c, 0x79, 0x18, 0x07, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x6b, 0x65,
|
0x72, 0x6c, 0x79, 0x12, 0x30, 0x0a, 0x14, 0x6b, 0x65, 0x65, 0x70, 0x5f, 0x77, 0x69, 0x74, 0x68,
|
||||||
0x65, 0x70, 0x59, 0x65, 0x61, 0x72, 0x6c, 0x79, 0x12, 0x30, 0x0a, 0x14, 0x6b, 0x65, 0x65, 0x70,
|
0x69, 0x6e, 0x5f, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x08, 0x20, 0x01, 0x28,
|
||||||
0x5f, 0x77, 0x69, 0x74, 0x68, 0x69, 0x6e, 0x5f, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e,
|
0x09, 0x52, 0x12, 0x6b, 0x65, 0x65, 0x70, 0x57, 0x69, 0x74, 0x68, 0x69, 0x6e, 0x44, 0x75, 0x72,
|
||||||
0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x12, 0x6b, 0x65, 0x65, 0x70, 0x57, 0x69, 0x74, 0x68,
|
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x2e, 0x5a, 0x2c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e,
|
||||||
0x69, 0x6e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x2e, 0x5a, 0x2c, 0x67, 0x69,
|
0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x61, 0x72, 0x65, 0x74, 0x68, 0x67, 0x65, 0x6f, 0x72, 0x67, 0x65,
|
||||||
0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x61, 0x72, 0x65, 0x74, 0x68, 0x67,
|
0x2f, 0x72, 0x65, 0x73, 0x74, 0x69, 0x63, 0x75, 0x69, 0x2f, 0x67, 0x6f, 0x2f, 0x70, 0x72, 0x6f,
|
||||||
0x65, 0x6f, 0x72, 0x67, 0x65, 0x2f, 0x72, 0x65, 0x73, 0x74, 0x69, 0x63, 0x75, 0x69, 0x2f, 0x67,
|
0x74, 0x6f, 0x2f, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||||
0x6f, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74,
|
|
||||||
0x6f, 0x33,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -477,18 +430,17 @@ func file_v1_config_proto_rawDescGZIP() []byte {
|
|||||||
return file_v1_config_proto_rawDescData
|
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, 4)
|
||||||
var file_v1_config_proto_goTypes = []interface{}{
|
var file_v1_config_proto_goTypes = []interface{}{
|
||||||
(*Config)(nil), // 0: v1.Config
|
(*Config)(nil), // 0: v1.Config
|
||||||
(*User)(nil), // 1: v1.User
|
(*Repo)(nil), // 1: v1.Repo
|
||||||
(*Repo)(nil), // 2: v1.Repo
|
(*Plan)(nil), // 2: v1.Plan
|
||||||
(*Plan)(nil), // 3: v1.Plan
|
(*RetentionPolicy)(nil), // 3: v1.RetentionPolicy
|
||||||
(*RetentionPolicy)(nil), // 4: v1.RetentionPolicy
|
|
||||||
}
|
}
|
||||||
var file_v1_config_proto_depIdxs = []int32{
|
var file_v1_config_proto_depIdxs = []int32{
|
||||||
2, // 0: v1.Config.repos:type_name -> v1.Repo
|
1, // 0: v1.Config.repos:type_name -> v1.Repo
|
||||||
3, // 1: v1.Config.plans:type_name -> v1.Plan
|
2, // 1: v1.Config.plans:type_name -> v1.Plan
|
||||||
4, // 2: v1.Plan.retention:type_name -> v1.RetentionPolicy
|
3, // 2: v1.Plan.retention:type_name -> v1.RetentionPolicy
|
||||||
3, // [3:3] is the sub-list for method output_type
|
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 method input_type
|
||||||
3, // [3:3] is the sub-list for extension type_name
|
3, // [3:3] is the sub-list for extension type_name
|
||||||
@@ -515,18 +467,6 @@ func file_v1_config_proto_init() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
file_v1_config_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
|
file_v1_config_proto_msgTypes[1].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[2].Exporter = func(v interface{}, i int) interface{} {
|
|
||||||
switch v := v.(*Repo); i {
|
switch v := v.(*Repo); i {
|
||||||
case 0:
|
case 0:
|
||||||
return &v.state
|
return &v.state
|
||||||
@@ -538,7 +478,7 @@ func file_v1_config_proto_init() {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
file_v1_config_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
|
file_v1_config_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
|
||||||
switch v := v.(*Plan); i {
|
switch v := v.(*Plan); i {
|
||||||
case 0:
|
case 0:
|
||||||
return &v.state
|
return &v.state
|
||||||
@@ -550,7 +490,7 @@ func file_v1_config_proto_init() {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
file_v1_config_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
|
file_v1_config_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
|
||||||
switch v := v.(*RetentionPolicy); i {
|
switch v := v.(*RetentionPolicy); i {
|
||||||
case 0:
|
case 0:
|
||||||
return &v.state
|
return &v.state
|
||||||
@@ -569,7 +509,7 @@ func file_v1_config_proto_init() {
|
|||||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||||
RawDescriptor: file_v1_config_proto_rawDesc,
|
RawDescriptor: file_v1_config_proto_rawDesc,
|
||||||
NumEnums: 0,
|
NumEnums: 0,
|
||||||
NumMessages: 5,
|
NumMessages: 4,
|
||||||
NumExtensions: 0,
|
NumExtensions: 0,
|
||||||
NumServices: 0,
|
NumServices: 0,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -155,7 +155,7 @@ type Event_Log struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Event_BackupStatusChange struct {
|
type Event_BackupStatusChange struct {
|
||||||
BackupStatusChange *BackupStatusEvent `protobuf:"bytes,4,opt,name=backup_status_change,json=backup_status,proto3,oneof"`
|
BackupStatusChange *BackupStatusEvent `protobuf:"bytes,4,opt,name=backup_status_change,json=backupStatusChange,proto3,oneof"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (*Event_Log) isEvent_Event() {}
|
func (*Event_Log) isEvent_Event() {}
|
||||||
@@ -276,33 +276,33 @@ var File_v1_events_proto protoreflect.FileDescriptor
|
|||||||
|
|
||||||
var file_v1_events_proto_rawDesc = []byte{
|
var file_v1_events_proto_rawDesc = []byte{
|
||||||
0x0a, 0x0f, 0x76, 0x31, 0x2f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74,
|
0x0a, 0x0f, 0x76, 0x31, 0x2f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74,
|
||||||
0x6f, 0x12, 0x02, 0x76, 0x31, 0x22, 0x96, 0x01, 0x0a, 0x05, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12,
|
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,
|
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,
|
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,
|
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,
|
0x4c, 0x6f, 0x67, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x03, 0x6c, 0x6f, 0x67, 0x12,
|
||||||
0x44, 0x0a, 0x14, 0x62, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73,
|
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,
|
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, 0x31, 0x2e, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x45,
|
||||||
0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x0d, 0x62, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x5f, 0x73,
|
0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x12, 0x62, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x53, 0x74,
|
||||||
0x74, 0x61, 0x74, 0x75, 0x73, 0x42, 0x07, 0x0a, 0x05, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x22, 0x24,
|
0x61, 0x74, 0x75, 0x73, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x42, 0x07, 0x0a, 0x05, 0x65, 0x76,
|
||||||
0x0a, 0x08, 0x4c, 0x6f, 0x67, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65,
|
0x65, 0x6e, 0x74, 0x22, 0x24, 0x0a, 0x08, 0x4c, 0x6f, 0x67, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12,
|
||||||
0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73,
|
0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
|
||||||
0x73, 0x61, 0x67, 0x65, 0x22, 0x65, 0x0a, 0x11, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x53, 0x74,
|
0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x65, 0x0a, 0x11, 0x42, 0x61, 0x63,
|
||||||
0x61, 0x74, 0x75, 0x73, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x6c, 0x61,
|
0x6b, 0x75, 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x12,
|
||||||
0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x6c, 0x61, 0x6e, 0x12, 0x22, 0x0a,
|
0x0a, 0x04, 0x70, 0x6c, 0x61, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x6c,
|
||||||
0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x0a, 0x2e,
|
0x61, 0x6e, 0x12, 0x22, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x02, 0x20, 0x01,
|
||||||
0x76, 0x31, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75,
|
0x28, 0x0e, 0x32, 0x0a, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06,
|
||||||
0x73, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x65, 0x72, 0x63, 0x65, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01,
|
0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x65, 0x72, 0x63, 0x65, 0x6e,
|
||||||
0x28, 0x0d, 0x52, 0x07, 0x70, 0x65, 0x72, 0x63, 0x65, 0x6e, 0x74, 0x2a, 0x3f, 0x0a, 0x06, 0x53,
|
0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x70, 0x65, 0x72, 0x63, 0x65, 0x6e, 0x74,
|
||||||
0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e,
|
0x2a, 0x3f, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e,
|
||||||
0x10, 0x00, 0x12, 0x0f, 0x0a, 0x0b, 0x49, 0x4e, 0x5f, 0x50, 0x52, 0x4f, 0x47, 0x52, 0x45, 0x53,
|
0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x0f, 0x0a, 0x0b, 0x49, 0x4e, 0x5f, 0x50, 0x52,
|
||||||
0x53, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x53, 0x55, 0x43, 0x43, 0x45, 0x53, 0x53, 0x10, 0x02,
|
0x4f, 0x47, 0x52, 0x45, 0x53, 0x53, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x53, 0x55, 0x43, 0x43,
|
||||||
0x12, 0x0a, 0x0a, 0x06, 0x46, 0x41, 0x49, 0x4c, 0x45, 0x44, 0x10, 0x03, 0x42, 0x2e, 0x5a, 0x2c,
|
0x45, 0x53, 0x53, 0x10, 0x02, 0x12, 0x0a, 0x0a, 0x06, 0x46, 0x41, 0x49, 0x4c, 0x45, 0x44, 0x10,
|
||||||
0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x61, 0x72, 0x65, 0x74,
|
0x03, 0x42, 0x2e, 0x5a, 0x2c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f,
|
||||||
0x68, 0x67, 0x65, 0x6f, 0x72, 0x67, 0x65, 0x2f, 0x72, 0x65, 0x73, 0x74, 0x69, 0x63, 0x75, 0x69,
|
0x67, 0x61, 0x72, 0x65, 0x74, 0x68, 0x67, 0x65, 0x6f, 0x72, 0x67, 0x65, 0x2f, 0x72, 0x65, 0x73,
|
||||||
0x2f, 0x67, 0x6f, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72,
|
0x74, 0x69, 0x63, 0x75, 0x69, 0x2f, 0x67, 0x6f, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x76,
|
||||||
0x6f, 0x74, 0x6f, 0x33,
|
0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ type ResticSnapshot struct {
|
|||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
|
|
||||||
Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
|
Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
|
||||||
UnixTimeMs int64 `protobuf:"varint,2,opt,name=unix_time_ms,json=time,proto3" json:"unix_time_ms,omitempty"`
|
UnixTimeMs int64 `protobuf:"varint,2,opt,name=unix_time_ms,json=unixTimeMs,proto3" json:"unix_time_ms,omitempty"`
|
||||||
Hostname string `protobuf:"bytes,3,opt,name=hostname,proto3" json:"hostname,omitempty"`
|
Hostname string `protobuf:"bytes,3,opt,name=hostname,proto3" json:"hostname,omitempty"`
|
||||||
Username string `protobuf:"bytes,4,opt,name=username,proto3" json:"username,omitempty"`
|
Username string `protobuf:"bytes,4,opt,name=username,proto3" json:"username,omitempty"`
|
||||||
Tree string `protobuf:"bytes,5,opt,name=tree,proto3" json:"tree,omitempty"` // tree hash
|
Tree string `protobuf:"bytes,5,opt,name=tree,proto3" json:"tree,omitempty"` // tree hash
|
||||||
@@ -123,6 +123,53 @@ func (x *ResticSnapshot) GetTags() []string {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ResticSnapshotList struct {
|
||||||
|
state protoimpl.MessageState
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
|
||||||
|
Snapshots []*ResticSnapshot `protobuf:"bytes,1,rep,name=snapshots,proto3" json:"snapshots,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ResticSnapshotList) Reset() {
|
||||||
|
*x = ResticSnapshotList{}
|
||||||
|
if protoimpl.UnsafeEnabled {
|
||||||
|
mi := &file_v1_restic_proto_msgTypes[1]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ResticSnapshotList) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*ResticSnapshotList) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *ResticSnapshotList) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_v1_restic_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 ResticSnapshotList.ProtoReflect.Descriptor instead.
|
||||||
|
func (*ResticSnapshotList) Descriptor() ([]byte, []int) {
|
||||||
|
return file_v1_restic_proto_rawDescGZIP(), []int{1}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ResticSnapshotList) GetSnapshots() []*ResticSnapshot {
|
||||||
|
if x != nil {
|
||||||
|
return x.Snapshots
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
type BackupProgressEntry struct {
|
type BackupProgressEntry struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState
|
||||||
sizeCache protoimpl.SizeCache
|
sizeCache protoimpl.SizeCache
|
||||||
@@ -138,7 +185,7 @@ type BackupProgressEntry struct {
|
|||||||
func (x *BackupProgressEntry) Reset() {
|
func (x *BackupProgressEntry) Reset() {
|
||||||
*x = BackupProgressEntry{}
|
*x = BackupProgressEntry{}
|
||||||
if protoimpl.UnsafeEnabled {
|
if protoimpl.UnsafeEnabled {
|
||||||
mi := &file_v1_restic_proto_msgTypes[1]
|
mi := &file_v1_restic_proto_msgTypes[2]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
@@ -151,7 +198,7 @@ func (x *BackupProgressEntry) String() string {
|
|||||||
func (*BackupProgressEntry) ProtoMessage() {}
|
func (*BackupProgressEntry) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *BackupProgressEntry) ProtoReflect() protoreflect.Message {
|
func (x *BackupProgressEntry) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_v1_restic_proto_msgTypes[1]
|
mi := &file_v1_restic_proto_msgTypes[2]
|
||||||
if protoimpl.UnsafeEnabled && x != nil {
|
if protoimpl.UnsafeEnabled && x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
@@ -164,7 +211,7 @@ func (x *BackupProgressEntry) ProtoReflect() protoreflect.Message {
|
|||||||
|
|
||||||
// Deprecated: Use BackupProgressEntry.ProtoReflect.Descriptor instead.
|
// Deprecated: Use BackupProgressEntry.ProtoReflect.Descriptor instead.
|
||||||
func (*BackupProgressEntry) Descriptor() ([]byte, []int) {
|
func (*BackupProgressEntry) Descriptor() ([]byte, []int) {
|
||||||
return file_v1_restic_proto_rawDescGZIP(), []int{1}
|
return file_v1_restic_proto_rawDescGZIP(), []int{2}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *BackupProgressEntry) GetEntry() isBackupProgressEntry_Entry {
|
func (m *BackupProgressEntry) GetEntry() isBackupProgressEntry_Entry {
|
||||||
@@ -209,17 +256,17 @@ type BackupProgressStatusEntry struct {
|
|||||||
sizeCache protoimpl.SizeCache
|
sizeCache protoimpl.SizeCache
|
||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
|
|
||||||
PercentDone float64 `protobuf:"fixed64,1,opt,name=percent_done,json=percent,proto3" json:"percent_done,omitempty"` // 0.0 - 1.0
|
PercentDone float64 `protobuf:"fixed64,1,opt,name=percent_done,json=percentDone,proto3" json:"percent_done,omitempty"` // 0.0 - 1.0
|
||||||
TotalFiles int64 `protobuf:"varint,2,opt,name=total_files,proto3" json:"total_files,omitempty"`
|
TotalFiles int64 `protobuf:"varint,2,opt,name=total_files,json=totalFiles,proto3" json:"total_files,omitempty"`
|
||||||
TotalBytes int64 `protobuf:"varint,3,opt,name=total_bytes,proto3" json:"total_bytes,omitempty"`
|
TotalBytes int64 `protobuf:"varint,3,opt,name=total_bytes,json=totalBytes,proto3" json:"total_bytes,omitempty"`
|
||||||
FilesDone int64 `protobuf:"varint,4,opt,name=files_done,proto3" json:"files_done,omitempty"`
|
FilesDone int64 `protobuf:"varint,4,opt,name=files_done,json=filesDone,proto3" json:"files_done,omitempty"`
|
||||||
BytesDone int64 `protobuf:"varint,5,opt,name=bytes_done,proto3" json:"bytes_done,omitempty"`
|
BytesDone int64 `protobuf:"varint,5,opt,name=bytes_done,json=bytesDone,proto3" json:"bytes_done,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *BackupProgressStatusEntry) Reset() {
|
func (x *BackupProgressStatusEntry) Reset() {
|
||||||
*x = BackupProgressStatusEntry{}
|
*x = BackupProgressStatusEntry{}
|
||||||
if protoimpl.UnsafeEnabled {
|
if protoimpl.UnsafeEnabled {
|
||||||
mi := &file_v1_restic_proto_msgTypes[2]
|
mi := &file_v1_restic_proto_msgTypes[3]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
@@ -232,7 +279,7 @@ func (x *BackupProgressStatusEntry) String() string {
|
|||||||
func (*BackupProgressStatusEntry) ProtoMessage() {}
|
func (*BackupProgressStatusEntry) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *BackupProgressStatusEntry) ProtoReflect() protoreflect.Message {
|
func (x *BackupProgressStatusEntry) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_v1_restic_proto_msgTypes[2]
|
mi := &file_v1_restic_proto_msgTypes[3]
|
||||||
if protoimpl.UnsafeEnabled && x != nil {
|
if protoimpl.UnsafeEnabled && x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
@@ -245,7 +292,7 @@ func (x *BackupProgressStatusEntry) ProtoReflect() protoreflect.Message {
|
|||||||
|
|
||||||
// Deprecated: Use BackupProgressStatusEntry.ProtoReflect.Descriptor instead.
|
// Deprecated: Use BackupProgressStatusEntry.ProtoReflect.Descriptor instead.
|
||||||
func (*BackupProgressStatusEntry) Descriptor() ([]byte, []int) {
|
func (*BackupProgressStatusEntry) Descriptor() ([]byte, []int) {
|
||||||
return file_v1_restic_proto_rawDescGZIP(), []int{2}
|
return file_v1_restic_proto_rawDescGZIP(), []int{3}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *BackupProgressStatusEntry) GetPercentDone() float64 {
|
func (x *BackupProgressStatusEntry) GetPercentDone() float64 {
|
||||||
@@ -288,25 +335,25 @@ type BackupProgressSummary struct {
|
|||||||
sizeCache protoimpl.SizeCache
|
sizeCache protoimpl.SizeCache
|
||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
|
|
||||||
FilesNew int64 `protobuf:"varint,1,opt,name=files_new,proto3" json:"files_new,omitempty"`
|
FilesNew int64 `protobuf:"varint,1,opt,name=files_new,json=filesNew,proto3" json:"files_new,omitempty"`
|
||||||
FilesChanged int64 `protobuf:"varint,2,opt,name=files_changed,proto3" json:"files_changed,omitempty"`
|
FilesChanged int64 `protobuf:"varint,2,opt,name=files_changed,json=filesChanged,proto3" json:"files_changed,omitempty"`
|
||||||
FilesUnmodified int64 `protobuf:"varint,3,opt,name=files_unmodified,proto3" json:"files_unmodified,omitempty"`
|
FilesUnmodified int64 `protobuf:"varint,3,opt,name=files_unmodified,json=filesUnmodified,proto3" json:"files_unmodified,omitempty"`
|
||||||
DirsNew int64 `protobuf:"varint,4,opt,name=dirs_new,proto3" json:"dirs_new,omitempty"`
|
DirsNew int64 `protobuf:"varint,4,opt,name=dirs_new,json=dirsNew,proto3" json:"dirs_new,omitempty"`
|
||||||
DirsChanged int64 `protobuf:"varint,5,opt,name=dirs_changed,proto3" json:"dirs_changed,omitempty"`
|
DirsChanged int64 `protobuf:"varint,5,opt,name=dirs_changed,json=dirsChanged,proto3" json:"dirs_changed,omitempty"`
|
||||||
DirsUnmodified int64 `protobuf:"varint,6,opt,name=dirs_unmodified,proto3" json:"dirs_unmodified,omitempty"`
|
DirsUnmodified int64 `protobuf:"varint,6,opt,name=dirs_unmodified,json=dirsUnmodified,proto3" json:"dirs_unmodified,omitempty"`
|
||||||
DataBlobs int64 `protobuf:"varint,7,opt,name=data_blobs,proto3" json:"data_blobs,omitempty"`
|
DataBlobs int64 `protobuf:"varint,7,opt,name=data_blobs,json=dataBlobs,proto3" json:"data_blobs,omitempty"`
|
||||||
TreeBlobs int64 `protobuf:"varint,8,opt,name=tree_blobs,proto3" json:"tree_blobs,omitempty"`
|
TreeBlobs int64 `protobuf:"varint,8,opt,name=tree_blobs,json=treeBlobs,proto3" json:"tree_blobs,omitempty"`
|
||||||
DataAdded int64 `protobuf:"varint,9,opt,name=data_added,proto3" json:"data_added,omitempty"`
|
DataAdded int64 `protobuf:"varint,9,opt,name=data_added,json=dataAdded,proto3" json:"data_added,omitempty"`
|
||||||
TotalFilesProcessed int64 `protobuf:"varint,10,opt,name=total_files_processed,proto3" json:"total_files_processed,omitempty"`
|
TotalFilesProcessed int64 `protobuf:"varint,10,opt,name=total_files_processed,json=totalFilesProcessed,proto3" json:"total_files_processed,omitempty"`
|
||||||
TotalBytesProcessed int64 `protobuf:"varint,11,opt,name=total_bytes_processed,proto3" json:"total_bytes_processed,omitempty"`
|
TotalBytesProcessed int64 `protobuf:"varint,11,opt,name=total_bytes_processed,json=totalBytesProcessed,proto3" json:"total_bytes_processed,omitempty"`
|
||||||
TotalDuration int64 `protobuf:"varint,12,opt,name=total_duration,proto3" json:"total_duration,omitempty"`
|
TotalDuration int64 `protobuf:"varint,12,opt,name=total_duration,json=totalDuration,proto3" json:"total_duration,omitempty"`
|
||||||
SnapshotId string `protobuf:"bytes,13,opt,name=snapshot_id,proto3" json:"snapshot_id,omitempty"`
|
SnapshotId string `protobuf:"bytes,13,opt,name=snapshot_id,json=snapshotId,proto3" json:"snapshot_id,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *BackupProgressSummary) Reset() {
|
func (x *BackupProgressSummary) Reset() {
|
||||||
*x = BackupProgressSummary{}
|
*x = BackupProgressSummary{}
|
||||||
if protoimpl.UnsafeEnabled {
|
if protoimpl.UnsafeEnabled {
|
||||||
mi := &file_v1_restic_proto_msgTypes[3]
|
mi := &file_v1_restic_proto_msgTypes[4]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
@@ -319,7 +366,7 @@ func (x *BackupProgressSummary) String() string {
|
|||||||
func (*BackupProgressSummary) ProtoMessage() {}
|
func (*BackupProgressSummary) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *BackupProgressSummary) ProtoReflect() protoreflect.Message {
|
func (x *BackupProgressSummary) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_v1_restic_proto_msgTypes[3]
|
mi := &file_v1_restic_proto_msgTypes[4]
|
||||||
if protoimpl.UnsafeEnabled && x != nil {
|
if protoimpl.UnsafeEnabled && x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
@@ -332,7 +379,7 @@ func (x *BackupProgressSummary) ProtoReflect() protoreflect.Message {
|
|||||||
|
|
||||||
// Deprecated: Use BackupProgressSummary.ProtoReflect.Descriptor instead.
|
// Deprecated: Use BackupProgressSummary.ProtoReflect.Descriptor instead.
|
||||||
func (*BackupProgressSummary) Descriptor() ([]byte, []int) {
|
func (*BackupProgressSummary) Descriptor() ([]byte, []int) {
|
||||||
return file_v1_restic_proto_rawDescGZIP(), []int{3}
|
return file_v1_restic_proto_rawDescGZIP(), []int{4}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *BackupProgressSummary) GetFilesNew() int64 {
|
func (x *BackupProgressSummary) GetFilesNew() int64 {
|
||||||
@@ -430,77 +477,81 @@ var File_v1_restic_proto protoreflect.FileDescriptor
|
|||||||
|
|
||||||
var file_v1_restic_proto_rawDesc = []byte{
|
var file_v1_restic_proto_rawDesc = []byte{
|
||||||
0x0a, 0x0f, 0x76, 0x31, 0x2f, 0x72, 0x65, 0x73, 0x74, 0x69, 0x63, 0x2e, 0x70, 0x72, 0x6f, 0x74,
|
0x0a, 0x0f, 0x76, 0x31, 0x2f, 0x72, 0x65, 0x73, 0x74, 0x69, 0x63, 0x2e, 0x70, 0x72, 0x6f, 0x74,
|
||||||
0x6f, 0x12, 0x02, 0x76, 0x31, 0x22, 0xca, 0x01, 0x0a, 0x0e, 0x52, 0x65, 0x73, 0x74, 0x69, 0x63,
|
0x6f, 0x12, 0x02, 0x76, 0x31, 0x22, 0xd0, 0x01, 0x0a, 0x0e, 0x52, 0x65, 0x73, 0x74, 0x69, 0x63,
|
||||||
0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01,
|
0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01,
|
||||||
0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1a, 0x0a, 0x0c, 0x75, 0x6e, 0x69, 0x78,
|
0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x20, 0x0a, 0x0c, 0x75, 0x6e, 0x69, 0x78,
|
||||||
0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x6d, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x04,
|
0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x6d, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a,
|
||||||
0x74, 0x69, 0x6d, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x68, 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65,
|
0x75, 0x6e, 0x69, 0x78, 0x54, 0x69, 0x6d, 0x65, 0x4d, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x68, 0x6f,
|
||||||
0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x68, 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65,
|
0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x68, 0x6f,
|
||||||
0x12, 0x1a, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01,
|
0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61,
|
||||||
0x28, 0x09, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04,
|
0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61,
|
||||||
0x74, 0x72, 0x65, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x72, 0x65, 0x65,
|
0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x72, 0x65, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09,
|
||||||
0x12, 0x16, 0x0a, 0x06, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09,
|
0x52, 0x04, 0x74, 0x72, 0x65, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74,
|
||||||
0x52, 0x06, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x70, 0x61, 0x74, 0x68,
|
0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x12, 0x14,
|
||||||
0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x70, 0x61, 0x74, 0x68, 0x73, 0x12, 0x12,
|
0x0a, 0x05, 0x70, 0x61, 0x74, 0x68, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x70,
|
||||||
0x0a, 0x04, 0x74, 0x61, 0x67, 0x73, 0x18, 0x08, 0x20, 0x03, 0x28, 0x09, 0x52, 0x04, 0x74, 0x61,
|
0x61, 0x74, 0x68, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x61, 0x67, 0x73, 0x18, 0x08, 0x20, 0x03,
|
||||||
0x67, 0x73, 0x22, 0x8e, 0x01, 0x0a, 0x13, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x50, 0x72, 0x6f,
|
0x28, 0x09, 0x52, 0x04, 0x74, 0x61, 0x67, 0x73, 0x22, 0x46, 0x0a, 0x12, 0x52, 0x65, 0x73, 0x74,
|
||||||
0x67, 0x72, 0x65, 0x73, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x37, 0x0a, 0x06, 0x73, 0x74,
|
0x69, 0x63, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x30,
|
||||||
0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x76, 0x31, 0x2e,
|
0x0a, 0x09, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28,
|
||||||
0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x53, 0x74,
|
0x0b, 0x32, 0x12, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x74, 0x69, 0x63, 0x53, 0x6e, 0x61,
|
||||||
0x61, 0x74, 0x75, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x48, 0x00, 0x52, 0x06, 0x73, 0x74, 0x61,
|
0x70, 0x73, 0x68, 0x6f, 0x74, 0x52, 0x09, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x73,
|
||||||
0x74, 0x75, 0x73, 0x12, 0x35, 0x0a, 0x07, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x18, 0x02,
|
0x22, 0x8e, 0x01, 0x0a, 0x13, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x50, 0x72, 0x6f, 0x67, 0x72,
|
||||||
0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70,
|
0x65, 0x73, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x37, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74,
|
||||||
0x50, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x48,
|
0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x61,
|
||||||
0x00, 0x52, 0x07, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x42, 0x07, 0x0a, 0x05, 0x65, 0x6e,
|
0x63, 0x6b, 0x75, 0x70, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x53, 0x74, 0x61, 0x74,
|
||||||
0x74, 0x72, 0x79, 0x22, 0xbe, 0x01, 0x0a, 0x19, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x50, 0x72,
|
0x75, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x48, 0x00, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75,
|
||||||
0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x45, 0x6e, 0x74, 0x72,
|
0x73, 0x12, 0x35, 0x0a, 0x07, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x18, 0x02, 0x20, 0x01,
|
||||||
0x79, 0x12, 0x1d, 0x0a, 0x0c, 0x70, 0x65, 0x72, 0x63, 0x65, 0x6e, 0x74, 0x5f, 0x64, 0x6f, 0x6e,
|
0x28, 0x0b, 0x32, 0x19, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x50, 0x72,
|
||||||
0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x01, 0x52, 0x07, 0x70, 0x65, 0x72, 0x63, 0x65, 0x6e, 0x74,
|
0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x48, 0x00, 0x52,
|
||||||
0x12, 0x20, 0x0a, 0x0b, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x18,
|
0x07, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x42, 0x07, 0x0a, 0x05, 0x65, 0x6e, 0x74, 0x72,
|
||||||
0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x66, 0x69, 0x6c,
|
0x79, 0x22, 0xbe, 0x01, 0x0a, 0x19, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x50, 0x72, 0x6f, 0x67,
|
||||||
0x65, 0x73, 0x12, 0x20, 0x0a, 0x0b, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x62, 0x79, 0x74, 0x65,
|
0x72, 0x65, 0x73, 0x73, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12,
|
||||||
0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x62,
|
0x21, 0x0a, 0x0c, 0x70, 0x65, 0x72, 0x63, 0x65, 0x6e, 0x74, 0x5f, 0x64, 0x6f, 0x6e, 0x65, 0x18,
|
||||||
0x79, 0x74, 0x65, 0x73, 0x12, 0x1e, 0x0a, 0x0a, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x5f, 0x64, 0x6f,
|
0x01, 0x20, 0x01, 0x28, 0x01, 0x52, 0x0b, 0x70, 0x65, 0x72, 0x63, 0x65, 0x6e, 0x74, 0x44, 0x6f,
|
||||||
0x6e, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x5f,
|
0x6e, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x66, 0x69, 0x6c, 0x65,
|
||||||
0x64, 0x6f, 0x6e, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x62, 0x79, 0x74, 0x65, 0x73, 0x5f, 0x64, 0x6f,
|
0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x46, 0x69,
|
||||||
0x6e, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x62, 0x79, 0x74, 0x65, 0x73, 0x5f,
|
0x6c, 0x65, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x62, 0x79, 0x74,
|
||||||
0x64, 0x6f, 0x6e, 0x65, 0x22, 0x87, 0x04, 0x0a, 0x15, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x50,
|
0x65, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x42,
|
||||||
0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x12, 0x1c,
|
0x79, 0x74, 0x65, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x5f, 0x64, 0x6f,
|
||||||
0x0a, 0x09, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x5f, 0x6e, 0x65, 0x77, 0x18, 0x01, 0x20, 0x01, 0x28,
|
0x6e, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x44,
|
||||||
0x03, 0x52, 0x09, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x5f, 0x6e, 0x65, 0x77, 0x12, 0x24, 0x0a, 0x0d,
|
0x6f, 0x6e, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x62, 0x79, 0x74, 0x65, 0x73, 0x5f, 0x64, 0x6f, 0x6e,
|
||||||
0x66, 0x69, 0x6c, 0x65, 0x73, 0x5f, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x18, 0x02, 0x20,
|
0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x62, 0x79, 0x74, 0x65, 0x73, 0x44, 0x6f,
|
||||||
0x01, 0x28, 0x03, 0x52, 0x0d, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x5f, 0x63, 0x68, 0x61, 0x6e, 0x67,
|
0x6e, 0x65, 0x22, 0xf8, 0x03, 0x0a, 0x15, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x50, 0x72, 0x6f,
|
||||||
0x65, 0x64, 0x12, 0x2a, 0x0a, 0x10, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x5f, 0x75, 0x6e, 0x6d, 0x6f,
|
0x67, 0x72, 0x65, 0x73, 0x73, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x12, 0x1b, 0x0a, 0x09,
|
||||||
0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x10, 0x66, 0x69,
|
0x66, 0x69, 0x6c, 0x65, 0x73, 0x5f, 0x6e, 0x65, 0x77, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52,
|
||||||
0x6c, 0x65, 0x73, 0x5f, 0x75, 0x6e, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x12, 0x1a,
|
0x08, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x4e, 0x65, 0x77, 0x12, 0x23, 0x0a, 0x0d, 0x66, 0x69, 0x6c,
|
||||||
0x0a, 0x08, 0x64, 0x69, 0x72, 0x73, 0x5f, 0x6e, 0x65, 0x77, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03,
|
0x65, 0x73, 0x5f, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03,
|
||||||
0x52, 0x08, 0x64, 0x69, 0x72, 0x73, 0x5f, 0x6e, 0x65, 0x77, 0x12, 0x22, 0x0a, 0x0c, 0x64, 0x69,
|
0x52, 0x0c, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x12, 0x29,
|
||||||
0x72, 0x73, 0x5f, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03,
|
0x0a, 0x10, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x5f, 0x75, 0x6e, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69,
|
||||||
0x52, 0x0c, 0x64, 0x69, 0x72, 0x73, 0x5f, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x12, 0x28,
|
0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x55,
|
||||||
0x0a, 0x0f, 0x64, 0x69, 0x72, 0x73, 0x5f, 0x75, 0x6e, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65,
|
0x6e, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x64, 0x69, 0x72,
|
||||||
0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, 0x64, 0x69, 0x72, 0x73, 0x5f, 0x75, 0x6e,
|
0x73, 0x5f, 0x6e, 0x65, 0x77, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x64, 0x69, 0x72,
|
||||||
0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x12, 0x1e, 0x0a, 0x0a, 0x64, 0x61, 0x74, 0x61,
|
0x73, 0x4e, 0x65, 0x77, 0x12, 0x21, 0x0a, 0x0c, 0x64, 0x69, 0x72, 0x73, 0x5f, 0x63, 0x68, 0x61,
|
||||||
0x5f, 0x62, 0x6c, 0x6f, 0x62, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x64, 0x61,
|
0x6e, 0x67, 0x65, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x64, 0x69, 0x72, 0x73,
|
||||||
0x74, 0x61, 0x5f, 0x62, 0x6c, 0x6f, 0x62, 0x73, 0x12, 0x1e, 0x0a, 0x0a, 0x74, 0x72, 0x65, 0x65,
|
0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x12, 0x27, 0x0a, 0x0f, 0x64, 0x69, 0x72, 0x73, 0x5f,
|
||||||
0x5f, 0x62, 0x6c, 0x6f, 0x62, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x74, 0x72,
|
0x75, 0x6e, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03,
|
||||||
0x65, 0x65, 0x5f, 0x62, 0x6c, 0x6f, 0x62, 0x73, 0x12, 0x1e, 0x0a, 0x0a, 0x64, 0x61, 0x74, 0x61,
|
0x52, 0x0e, 0x64, 0x69, 0x72, 0x73, 0x55, 0x6e, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64,
|
||||||
0x5f, 0x61, 0x64, 0x64, 0x65, 0x64, 0x18, 0x09, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x64, 0x61,
|
0x12, 0x1d, 0x0a, 0x0a, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x62, 0x6c, 0x6f, 0x62, 0x73, 0x18, 0x07,
|
||||||
0x74, 0x61, 0x5f, 0x61, 0x64, 0x64, 0x65, 0x64, 0x12, 0x34, 0x0a, 0x15, 0x74, 0x6f, 0x74, 0x61,
|
0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x64, 0x61, 0x74, 0x61, 0x42, 0x6c, 0x6f, 0x62, 0x73, 0x12,
|
||||||
0x6c, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x5f, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x65,
|
0x1d, 0x0a, 0x0a, 0x74, 0x72, 0x65, 0x65, 0x5f, 0x62, 0x6c, 0x6f, 0x62, 0x73, 0x18, 0x08, 0x20,
|
||||||
0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x03, 0x52, 0x15, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x66,
|
0x01, 0x28, 0x03, 0x52, 0x09, 0x74, 0x72, 0x65, 0x65, 0x42, 0x6c, 0x6f, 0x62, 0x73, 0x12, 0x1d,
|
||||||
0x69, 0x6c, 0x65, 0x73, 0x5f, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x65, 0x64, 0x12, 0x34,
|
0x0a, 0x0a, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x61, 0x64, 0x64, 0x65, 0x64, 0x18, 0x09, 0x20, 0x01,
|
||||||
0x0a, 0x15, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x5f, 0x70, 0x72,
|
0x28, 0x03, 0x52, 0x09, 0x64, 0x61, 0x74, 0x61, 0x41, 0x64, 0x64, 0x65, 0x64, 0x12, 0x32, 0x0a,
|
||||||
0x6f, 0x63, 0x65, 0x73, 0x73, 0x65, 0x64, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x03, 0x52, 0x15, 0x74,
|
0x15, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x5f, 0x70, 0x72, 0x6f,
|
||||||
0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x5f, 0x70, 0x72, 0x6f, 0x63, 0x65,
|
0x63, 0x65, 0x73, 0x73, 0x65, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x03, 0x52, 0x13, 0x74, 0x6f,
|
||||||
0x73, 0x73, 0x65, 0x64, 0x12, 0x26, 0x0a, 0x0e, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x64, 0x75,
|
0x74, 0x61, 0x6c, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x65,
|
||||||
0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x74, 0x6f,
|
0x64, 0x12, 0x32, 0x0a, 0x15, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73,
|
||||||
0x74, 0x61, 0x6c, 0x5f, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x20, 0x0a, 0x0b,
|
0x5f, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x65, 0x64, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x03,
|
||||||
|
0x52, 0x13, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x42, 0x79, 0x74, 0x65, 0x73, 0x50, 0x72, 0x6f, 0x63,
|
||||||
|
0x65, 0x73, 0x73, 0x65, 0x64, 0x12, 0x25, 0x0a, 0x0e, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x64,
|
||||||
|
0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, 0x74,
|
||||||
|
0x6f, 0x74, 0x61, 0x6c, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1f, 0x0a, 0x0b,
|
||||||
0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x0d, 0x20, 0x01, 0x28,
|
0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x0d, 0x20, 0x01, 0x28,
|
||||||
0x09, 0x52, 0x0b, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x5f, 0x69, 0x64, 0x42, 0x2e,
|
0x09, 0x52, 0x0a, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x49, 0x64, 0x42, 0x2e, 0x5a,
|
||||||
0x5a, 0x2c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x61, 0x72,
|
0x2c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x61, 0x72, 0x65,
|
||||||
0x65, 0x74, 0x68, 0x67, 0x65, 0x6f, 0x72, 0x67, 0x65, 0x2f, 0x72, 0x65, 0x73, 0x74, 0x69, 0x63,
|
0x74, 0x68, 0x67, 0x65, 0x6f, 0x72, 0x67, 0x65, 0x2f, 0x72, 0x65, 0x73, 0x74, 0x69, 0x63, 0x75,
|
||||||
0x75, 0x69, 0x2f, 0x67, 0x6f, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x76, 0x31, 0x62, 0x06,
|
0x69, 0x2f, 0x67, 0x6f, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x76, 0x31, 0x62, 0x06, 0x70,
|
||||||
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -515,21 +566,23 @@ func file_v1_restic_proto_rawDescGZIP() []byte {
|
|||||||
return file_v1_restic_proto_rawDescData
|
return file_v1_restic_proto_rawDescData
|
||||||
}
|
}
|
||||||
|
|
||||||
var file_v1_restic_proto_msgTypes = make([]protoimpl.MessageInfo, 4)
|
var file_v1_restic_proto_msgTypes = make([]protoimpl.MessageInfo, 5)
|
||||||
var file_v1_restic_proto_goTypes = []interface{}{
|
var file_v1_restic_proto_goTypes = []interface{}{
|
||||||
(*ResticSnapshot)(nil), // 0: v1.ResticSnapshot
|
(*ResticSnapshot)(nil), // 0: v1.ResticSnapshot
|
||||||
(*BackupProgressEntry)(nil), // 1: v1.BackupProgressEntry
|
(*ResticSnapshotList)(nil), // 1: v1.ResticSnapshotList
|
||||||
(*BackupProgressStatusEntry)(nil), // 2: v1.BackupProgressStatusEntry
|
(*BackupProgressEntry)(nil), // 2: v1.BackupProgressEntry
|
||||||
(*BackupProgressSummary)(nil), // 3: v1.BackupProgressSummary
|
(*BackupProgressStatusEntry)(nil), // 3: v1.BackupProgressStatusEntry
|
||||||
|
(*BackupProgressSummary)(nil), // 4: v1.BackupProgressSummary
|
||||||
}
|
}
|
||||||
var file_v1_restic_proto_depIdxs = []int32{
|
var file_v1_restic_proto_depIdxs = []int32{
|
||||||
2, // 0: v1.BackupProgressEntry.status:type_name -> v1.BackupProgressStatusEntry
|
0, // 0: v1.ResticSnapshotList.snapshots:type_name -> v1.ResticSnapshot
|
||||||
3, // 1: v1.BackupProgressEntry.summary:type_name -> v1.BackupProgressSummary
|
3, // 1: v1.BackupProgressEntry.status:type_name -> v1.BackupProgressStatusEntry
|
||||||
2, // [2:2] is the sub-list for method output_type
|
4, // 2: v1.BackupProgressEntry.summary:type_name -> v1.BackupProgressSummary
|
||||||
2, // [2:2] is the sub-list for method input_type
|
3, // [3:3] is the sub-list for method output_type
|
||||||
2, // [2:2] is the sub-list for extension type_name
|
3, // [3:3] is the sub-list for method input_type
|
||||||
2, // [2:2] is the sub-list for extension extendee
|
3, // [3:3] is the sub-list for extension type_name
|
||||||
0, // [0:2] is the sub-list for field 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_restic_proto_init() }
|
func init() { file_v1_restic_proto_init() }
|
||||||
@@ -551,7 +604,7 @@ func file_v1_restic_proto_init() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
file_v1_restic_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
|
file_v1_restic_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
|
||||||
switch v := v.(*BackupProgressEntry); i {
|
switch v := v.(*ResticSnapshotList); i {
|
||||||
case 0:
|
case 0:
|
||||||
return &v.state
|
return &v.state
|
||||||
case 1:
|
case 1:
|
||||||
@@ -563,7 +616,7 @@ func file_v1_restic_proto_init() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
file_v1_restic_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
|
file_v1_restic_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
|
||||||
switch v := v.(*BackupProgressStatusEntry); i {
|
switch v := v.(*BackupProgressEntry); i {
|
||||||
case 0:
|
case 0:
|
||||||
return &v.state
|
return &v.state
|
||||||
case 1:
|
case 1:
|
||||||
@@ -575,6 +628,18 @@ func file_v1_restic_proto_init() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
file_v1_restic_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
|
file_v1_restic_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
|
||||||
|
switch v := v.(*BackupProgressStatusEntry); i {
|
||||||
|
case 0:
|
||||||
|
return &v.state
|
||||||
|
case 1:
|
||||||
|
return &v.sizeCache
|
||||||
|
case 2:
|
||||||
|
return &v.unknownFields
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
file_v1_restic_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
|
||||||
switch v := v.(*BackupProgressSummary); i {
|
switch v := v.(*BackupProgressSummary); i {
|
||||||
case 0:
|
case 0:
|
||||||
return &v.state
|
return &v.state
|
||||||
@@ -587,7 +652,7 @@ func file_v1_restic_proto_init() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
file_v1_restic_proto_msgTypes[1].OneofWrappers = []interface{}{
|
file_v1_restic_proto_msgTypes[2].OneofWrappers = []interface{}{
|
||||||
(*BackupProgressEntry_Status)(nil),
|
(*BackupProgressEntry_Status)(nil),
|
||||||
(*BackupProgressEntry_Summary)(nil),
|
(*BackupProgressEntry_Summary)(nil),
|
||||||
}
|
}
|
||||||
@@ -597,7 +662,7 @@ func file_v1_restic_proto_init() {
|
|||||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||||
RawDescriptor: file_v1_restic_proto_rawDesc,
|
RawDescriptor: file_v1_restic_proto_rawDesc,
|
||||||
NumEnums: 0,
|
NumEnums: 0,
|
||||||
NumMessages: 4,
|
NumMessages: 5,
|
||||||
NumExtensions: 0,
|
NumExtensions: 0,
|
||||||
NumServices: 0,
|
NumServices: 0,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import (
|
|||||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||||
emptypb "google.golang.org/protobuf/types/known/emptypb"
|
emptypb "google.golang.org/protobuf/types/known/emptypb"
|
||||||
reflect "reflect"
|
reflect "reflect"
|
||||||
|
sync "sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -22,67 +23,151 @@ const (
|
|||||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type ListSnapshotsRequest struct {
|
||||||
|
state protoimpl.MessageState
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
|
||||||
|
RepoId string `protobuf:"bytes,1,opt,name=repo_id,json=repoId,proto3" json:"repo_id,omitempty"`
|
||||||
|
PlanId string `protobuf:"bytes,2,opt,name=plan_id,json=planId,proto3" json:"plan_id,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ListSnapshotsRequest) Reset() {
|
||||||
|
*x = ListSnapshotsRequest{}
|
||||||
|
if protoimpl.UnsafeEnabled {
|
||||||
|
mi := &file_v1_service_proto_msgTypes[0]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ListSnapshotsRequest) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*ListSnapshotsRequest) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *ListSnapshotsRequest) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_v1_service_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 ListSnapshotsRequest.ProtoReflect.Descriptor instead.
|
||||||
|
func (*ListSnapshotsRequest) Descriptor() ([]byte, []int) {
|
||||||
|
return file_v1_service_proto_rawDescGZIP(), []int{0}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ListSnapshotsRequest) GetRepoId() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.RepoId
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ListSnapshotsRequest) GetPlanId() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.PlanId
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
var File_v1_service_proto protoreflect.FileDescriptor
|
var File_v1_service_proto protoreflect.FileDescriptor
|
||||||
|
|
||||||
var file_v1_service_proto_rawDesc = []byte{
|
var file_v1_service_proto_rawDesc = []byte{
|
||||||
0x0a, 0x10, 0x76, 0x31, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x70, 0x72, 0x6f,
|
0x0a, 0x10, 0x76, 0x31, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x70, 0x72, 0x6f,
|
||||||
0x74, 0x6f, 0x12, 0x02, 0x76, 0x31, 0x1a, 0x0f, 0x76, 0x31, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69,
|
0x74, 0x6f, 0x12, 0x02, 0x76, 0x31, 0x1a, 0x0f, 0x76, 0x31, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69,
|
||||||
0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x0f, 0x76, 0x31, 0x2f, 0x65, 0x76, 0x65, 0x6e,
|
0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x0f, 0x76, 0x31, 0x2f, 0x65, 0x76, 0x65, 0x6e,
|
||||||
0x74, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x11, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f,
|
0x74, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x0f, 0x76, 0x31, 0x2f, 0x72, 0x65, 0x73,
|
||||||
0x76, 0x61, 0x6c, 0x75, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1b, 0x67, 0x6f, 0x6f,
|
0x74, 0x69, 0x63, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x11, 0x74, 0x79, 0x70, 0x65, 0x73,
|
||||||
0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x65, 0x6d, 0x70,
|
0x2f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1b, 0x67, 0x6f,
|
||||||
0x74, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1c, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
|
0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x65, 0x6d,
|
||||||
0x2f, 0x61, 0x70, 0x69, 0x2f, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73,
|
0x70, 0x74, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1c, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
|
||||||
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x32, 0xeb, 0x02, 0x0a, 0x08, 0x52, 0x65, 0x73, 0x74, 0x69,
|
0x65, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e,
|
||||||
0x63, 0x55, 0x49, 0x12, 0x43, 0x0a, 0x09, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
|
0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x48, 0x0a, 0x14, 0x4c, 0x69, 0x73, 0x74, 0x53,
|
||||||
0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62,
|
0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12,
|
||||||
0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x0a, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f,
|
0x17, 0x0a, 0x07, 0x72, 0x65, 0x70, 0x6f, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
|
||||||
0x6e, 0x66, 0x69, 0x67, 0x22, 0x12, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0c, 0x12, 0x0a, 0x2f, 0x76,
|
0x52, 0x06, 0x72, 0x65, 0x70, 0x6f, 0x49, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x70, 0x6c, 0x61, 0x6e,
|
||||||
0x31, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x3a, 0x0a, 0x09, 0x53, 0x65, 0x74, 0x43,
|
0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x70, 0x6c, 0x61, 0x6e, 0x49,
|
||||||
0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x0a, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69,
|
0x64, 0x32, 0xc8, 0x03, 0x0a, 0x08, 0x52, 0x65, 0x73, 0x74, 0x69, 0x63, 0x55, 0x49, 0x12, 0x43,
|
||||||
0x67, 0x1a, 0x0a, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x22, 0x15, 0x82,
|
0x0a, 0x09, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x16, 0x2e, 0x67, 0x6f,
|
||||||
0xd3, 0xe4, 0x93, 0x02, 0x0f, 0x3a, 0x01, 0x2a, 0x22, 0x0a, 0x2f, 0x76, 0x31, 0x2f, 0x63, 0x6f,
|
0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d,
|
||||||
0x6e, 0x66, 0x69, 0x67, 0x12, 0x3b, 0x0a, 0x07, 0x41, 0x64, 0x64, 0x52, 0x65, 0x70, 0x6f, 0x12,
|
0x70, 0x74, 0x79, 0x1a, 0x0a, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x22,
|
||||||
0x08, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x70, 0x6f, 0x1a, 0x0a, 0x2e, 0x76, 0x31, 0x2e, 0x43,
|
0x12, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0c, 0x12, 0x0a, 0x2f, 0x76, 0x31, 0x2f, 0x63, 0x6f, 0x6e,
|
||||||
0x6f, 0x6e, 0x66, 0x69, 0x67, 0x22, 0x1a, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x14, 0x3a, 0x01, 0x2a,
|
0x66, 0x69, 0x67, 0x12, 0x3a, 0x0a, 0x09, 0x53, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
|
||||||
0x22, 0x0f, 0x2f, 0x76, 0x31, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2f, 0x72, 0x65, 0x70,
|
0x12, 0x0a, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x1a, 0x0a, 0x2e, 0x76,
|
||||||
0x6f, 0x12, 0x44, 0x0a, 0x09, 0x47, 0x65, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x16,
|
0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x22, 0x15, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0f,
|
||||||
0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66,
|
0x3a, 0x01, 0x2a, 0x22, 0x0a, 0x2f, 0x76, 0x31, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12,
|
||||||
0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x09, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x76, 0x65, 0x6e,
|
0x3b, 0x0a, 0x07, 0x41, 0x64, 0x64, 0x52, 0x65, 0x70, 0x6f, 0x12, 0x08, 0x2e, 0x76, 0x31, 0x2e,
|
||||||
0x74, 0x22, 0x12, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0c, 0x12, 0x0a, 0x2f, 0x76, 0x31, 0x2f, 0x65,
|
0x52, 0x65, 0x70, 0x6f, 0x1a, 0x0a, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
|
||||||
0x76, 0x65, 0x6e, 0x74, 0x73, 0x30, 0x01, 0x12, 0x5b, 0x0a, 0x10, 0x50, 0x61, 0x74, 0x68, 0x41,
|
0x22, 0x1a, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x14, 0x3a, 0x01, 0x2a, 0x22, 0x0f, 0x2f, 0x76, 0x31,
|
||||||
0x75, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x12, 0x12, 0x2e, 0x74, 0x79,
|
0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2f, 0x72, 0x65, 0x70, 0x6f, 0x12, 0x44, 0x0a, 0x09,
|
||||||
0x70, 0x65, 0x73, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a,
|
0x47, 0x65, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67,
|
||||||
0x11, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x4c, 0x69,
|
0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74,
|
||||||
0x73, 0x74, 0x22, 0x20, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1a, 0x3a, 0x01, 0x2a, 0x22, 0x15, 0x2f,
|
0x79, 0x1a, 0x09, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x22, 0x12, 0x82, 0xd3,
|
||||||
0x76, 0x31, 0x2f, 0x61, 0x75, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x2f,
|
0xe4, 0x93, 0x02, 0x0c, 0x12, 0x0a, 0x2f, 0x76, 0x31, 0x2f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73,
|
||||||
0x70, 0x61, 0x74, 0x68, 0x42, 0x2e, 0x5a, 0x2c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63,
|
0x30, 0x01, 0x12, 0x5b, 0x0a, 0x0d, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68,
|
||||||
0x6f, 0x6d, 0x2f, 0x67, 0x61, 0x72, 0x65, 0x74, 0x68, 0x67, 0x65, 0x6f, 0x72, 0x67, 0x65, 0x2f,
|
0x6f, 0x74, 0x73, 0x12, 0x18, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x6e, 0x61,
|
||||||
0x72, 0x65, 0x73, 0x74, 0x69, 0x63, 0x75, 0x69, 0x2f, 0x67, 0x6f, 0x2f, 0x70, 0x72, 0x6f, 0x74,
|
0x70, 0x73, 0x68, 0x6f, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e,
|
||||||
0x6f, 0x2f, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
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,
|
||||||
|
0x5b, 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, 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, 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_service_proto_rawDescOnce sync.Once
|
||||||
|
file_v1_service_proto_rawDescData = file_v1_service_proto_rawDesc
|
||||||
|
)
|
||||||
|
|
||||||
|
func file_v1_service_proto_rawDescGZIP() []byte {
|
||||||
|
file_v1_service_proto_rawDescOnce.Do(func() {
|
||||||
|
file_v1_service_proto_rawDescData = protoimpl.X.CompressGZIP(file_v1_service_proto_rawDescData)
|
||||||
|
})
|
||||||
|
return file_v1_service_proto_rawDescData
|
||||||
|
}
|
||||||
|
|
||||||
|
var file_v1_service_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
|
||||||
var file_v1_service_proto_goTypes = []interface{}{
|
var file_v1_service_proto_goTypes = []interface{}{
|
||||||
(*emptypb.Empty)(nil), // 0: google.protobuf.Empty
|
(*ListSnapshotsRequest)(nil), // 0: v1.ListSnapshotsRequest
|
||||||
(*Config)(nil), // 1: v1.Config
|
(*emptypb.Empty)(nil), // 1: google.protobuf.Empty
|
||||||
(*Repo)(nil), // 2: v1.Repo
|
(*Config)(nil), // 2: v1.Config
|
||||||
(*types.StringValue)(nil), // 3: types.StringValue
|
(*Repo)(nil), // 3: v1.Repo
|
||||||
(*Event)(nil), // 4: v1.Event
|
(*types.StringValue)(nil), // 4: types.StringValue
|
||||||
(*types.StringList)(nil), // 5: types.StringList
|
(*Event)(nil), // 5: v1.Event
|
||||||
|
(*ResticSnapshotList)(nil), // 6: v1.ResticSnapshotList
|
||||||
|
(*types.StringList)(nil), // 7: types.StringList
|
||||||
}
|
}
|
||||||
var file_v1_service_proto_depIdxs = []int32{
|
var file_v1_service_proto_depIdxs = []int32{
|
||||||
0, // 0: v1.ResticUI.GetConfig:input_type -> google.protobuf.Empty
|
1, // 0: v1.ResticUI.GetConfig:input_type -> google.protobuf.Empty
|
||||||
1, // 1: v1.ResticUI.SetConfig:input_type -> v1.Config
|
2, // 1: v1.ResticUI.SetConfig:input_type -> v1.Config
|
||||||
2, // 2: v1.ResticUI.AddRepo:input_type -> v1.Repo
|
3, // 2: v1.ResticUI.AddRepo:input_type -> v1.Repo
|
||||||
0, // 3: v1.ResticUI.GetEvents:input_type -> google.protobuf.Empty
|
1, // 3: v1.ResticUI.GetEvents:input_type -> google.protobuf.Empty
|
||||||
3, // 4: v1.ResticUI.PathAutocomplete:input_type -> types.StringValue
|
0, // 4: v1.ResticUI.ListSnapshots:input_type -> v1.ListSnapshotsRequest
|
||||||
1, // 5: v1.ResticUI.GetConfig:output_type -> v1.Config
|
4, // 5: v1.ResticUI.PathAutocomplete:input_type -> types.StringValue
|
||||||
1, // 6: v1.ResticUI.SetConfig:output_type -> v1.Config
|
2, // 6: v1.ResticUI.GetConfig:output_type -> v1.Config
|
||||||
1, // 7: v1.ResticUI.AddRepo:output_type -> v1.Config
|
2, // 7: v1.ResticUI.SetConfig:output_type -> v1.Config
|
||||||
4, // 8: v1.ResticUI.GetEvents:output_type -> v1.Event
|
2, // 8: v1.ResticUI.AddRepo:output_type -> v1.Config
|
||||||
5, // 9: v1.ResticUI.PathAutocomplete:output_type -> types.StringList
|
5, // 9: v1.ResticUI.GetEvents:output_type -> v1.Event
|
||||||
5, // [5:10] is the sub-list for method output_type
|
6, // 10: v1.ResticUI.ListSnapshots:output_type -> v1.ResticSnapshotList
|
||||||
0, // [0:5] is the sub-list for method input_type
|
7, // 11: v1.ResticUI.PathAutocomplete:output_type -> types.StringList
|
||||||
|
6, // [6:12] is the sub-list for method output_type
|
||||||
|
0, // [0:6] is the sub-list for method input_type
|
||||||
0, // [0:0] is the sub-list for extension type_name
|
0, // [0:0] is the sub-list for extension type_name
|
||||||
0, // [0:0] is the sub-list for extension extendee
|
0, // [0:0] is the sub-list for extension extendee
|
||||||
0, // [0:0] is the sub-list for field type_name
|
0, // [0:0] is the sub-list for field type_name
|
||||||
@@ -95,18 +180,34 @@ func file_v1_service_proto_init() {
|
|||||||
}
|
}
|
||||||
file_v1_config_proto_init()
|
file_v1_config_proto_init()
|
||||||
file_v1_events_proto_init()
|
file_v1_events_proto_init()
|
||||||
|
file_v1_restic_proto_init()
|
||||||
|
if !protoimpl.UnsafeEnabled {
|
||||||
|
file_v1_service_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
|
||||||
|
switch v := v.(*ListSnapshotsRequest); i {
|
||||||
|
case 0:
|
||||||
|
return &v.state
|
||||||
|
case 1:
|
||||||
|
return &v.sizeCache
|
||||||
|
case 2:
|
||||||
|
return &v.unknownFields
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
type x struct{}
|
type x struct{}
|
||||||
out := protoimpl.TypeBuilder{
|
out := protoimpl.TypeBuilder{
|
||||||
File: protoimpl.DescBuilder{
|
File: protoimpl.DescBuilder{
|
||||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||||
RawDescriptor: file_v1_service_proto_rawDesc,
|
RawDescriptor: file_v1_service_proto_rawDesc,
|
||||||
NumEnums: 0,
|
NumEnums: 0,
|
||||||
NumMessages: 0,
|
NumMessages: 1,
|
||||||
NumExtensions: 0,
|
NumExtensions: 0,
|
||||||
NumServices: 1,
|
NumServices: 1,
|
||||||
},
|
},
|
||||||
GoTypes: file_v1_service_proto_goTypes,
|
GoTypes: file_v1_service_proto_goTypes,
|
||||||
DependencyIndexes: file_v1_service_proto_depIdxs,
|
DependencyIndexes: file_v1_service_proto_depIdxs,
|
||||||
|
MessageInfos: file_v1_service_proto_msgTypes,
|
||||||
}.Build()
|
}.Build()
|
||||||
File_v1_service_proto = out.File
|
File_v1_service_proto = out.File
|
||||||
file_v1_service_proto_rawDesc = nil
|
file_v1_service_proto_rawDesc = nil
|
||||||
|
|||||||
@@ -136,6 +136,40 @@ func request_ResticUI_GetEvents_0(ctx context.Context, marshaler runtime.Marshal
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func request_ResticUI_ListSnapshots_0(ctx context.Context, marshaler runtime.Marshaler, client ResticUIClient, 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_ResticUI_ListSnapshots_0(ctx context.Context, marshaler runtime.Marshaler, server ResticUIServer, 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_ResticUI_PathAutocomplete_0(ctx context.Context, marshaler runtime.Marshaler, client ResticUIClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
func request_ResticUI_PathAutocomplete_0(ctx context.Context, marshaler runtime.Marshaler, client ResticUIClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||||
var protoReq types.StringValue
|
var protoReq types.StringValue
|
||||||
var metadata runtime.ServerMetadata
|
var metadata runtime.ServerMetadata
|
||||||
@@ -258,6 +292,31 @@ func RegisterResticUIHandlerServer(ctx context.Context, mux *runtime.ServeMux, s
|
|||||||
return
|
return
|
||||||
})
|
})
|
||||||
|
|
||||||
|
mux.Handle("POST", pattern_ResticUI_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.ResticUI/ListSnapshots", runtime.WithHTTPPathPattern("/v1/snapshots"))
|
||||||
|
if err != nil {
|
||||||
|
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
resp, md, err := local_request_ResticUI_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_ResticUI_ListSnapshots_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
mux.Handle("POST", pattern_ResticUI_PathAutocomplete_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
mux.Handle("POST", pattern_ResticUI_PathAutocomplete_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||||
ctx, cancel := context.WithCancel(req.Context())
|
ctx, cancel := context.WithCancel(req.Context())
|
||||||
defer cancel()
|
defer cancel()
|
||||||
@@ -412,6 +471,28 @@ func RegisterResticUIHandlerClient(ctx context.Context, mux *runtime.ServeMux, c
|
|||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
|
mux.Handle("POST", pattern_ResticUI_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.ResticUI/ListSnapshots", runtime.WithHTTPPathPattern("/v1/snapshots"))
|
||||||
|
if err != nil {
|
||||||
|
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
resp, md, err := request_ResticUI_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_ResticUI_ListSnapshots_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
mux.Handle("POST", pattern_ResticUI_PathAutocomplete_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
mux.Handle("POST", pattern_ResticUI_PathAutocomplete_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||||
ctx, cancel := context.WithCancel(req.Context())
|
ctx, cancel := context.WithCancel(req.Context())
|
||||||
defer cancel()
|
defer cancel()
|
||||||
@@ -446,6 +527,8 @@ var (
|
|||||||
|
|
||||||
pattern_ResticUI_GetEvents_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"v1", "events"}, ""))
|
pattern_ResticUI_GetEvents_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"v1", "events"}, ""))
|
||||||
|
|
||||||
|
pattern_ResticUI_ListSnapshots_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"v1", "snapshots"}, ""))
|
||||||
|
|
||||||
pattern_ResticUI_PathAutocomplete_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v1", "autocomplete", "path"}, ""))
|
pattern_ResticUI_PathAutocomplete_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v1", "autocomplete", "path"}, ""))
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -458,5 +541,7 @@ var (
|
|||||||
|
|
||||||
forward_ResticUI_GetEvents_0 = runtime.ForwardResponseStream
|
forward_ResticUI_GetEvents_0 = runtime.ForwardResponseStream
|
||||||
|
|
||||||
|
forward_ResticUI_ListSnapshots_0 = runtime.ForwardResponseMessage
|
||||||
|
|
||||||
forward_ResticUI_PathAutocomplete_0 = runtime.ForwardResponseMessage
|
forward_ResticUI_PathAutocomplete_0 = runtime.ForwardResponseMessage
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ const (
|
|||||||
ResticUI_SetConfig_FullMethodName = "/v1.ResticUI/SetConfig"
|
ResticUI_SetConfig_FullMethodName = "/v1.ResticUI/SetConfig"
|
||||||
ResticUI_AddRepo_FullMethodName = "/v1.ResticUI/AddRepo"
|
ResticUI_AddRepo_FullMethodName = "/v1.ResticUI/AddRepo"
|
||||||
ResticUI_GetEvents_FullMethodName = "/v1.ResticUI/GetEvents"
|
ResticUI_GetEvents_FullMethodName = "/v1.ResticUI/GetEvents"
|
||||||
|
ResticUI_ListSnapshots_FullMethodName = "/v1.ResticUI/ListSnapshots"
|
||||||
ResticUI_PathAutocomplete_FullMethodName = "/v1.ResticUI/PathAutocomplete"
|
ResticUI_PathAutocomplete_FullMethodName = "/v1.ResticUI/PathAutocomplete"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -36,6 +37,7 @@ type ResticUIClient interface {
|
|||||||
SetConfig(ctx context.Context, in *Config, opts ...grpc.CallOption) (*Config, error)
|
SetConfig(ctx context.Context, in *Config, opts ...grpc.CallOption) (*Config, error)
|
||||||
AddRepo(ctx context.Context, in *Repo, opts ...grpc.CallOption) (*Config, error)
|
AddRepo(ctx context.Context, in *Repo, opts ...grpc.CallOption) (*Config, error)
|
||||||
GetEvents(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (ResticUI_GetEventsClient, error)
|
GetEvents(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (ResticUI_GetEventsClient, error)
|
||||||
|
ListSnapshots(ctx context.Context, in *ListSnapshotsRequest, opts ...grpc.CallOption) (*ResticSnapshotList, error)
|
||||||
PathAutocomplete(ctx context.Context, in *types.StringValue, opts ...grpc.CallOption) (*types.StringList, error)
|
PathAutocomplete(ctx context.Context, in *types.StringValue, opts ...grpc.CallOption) (*types.StringList, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -106,6 +108,15 @@ func (x *resticUIGetEventsClient) Recv() (*Event, error) {
|
|||||||
return m, nil
|
return m, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *resticUIClient) ListSnapshots(ctx context.Context, in *ListSnapshotsRequest, opts ...grpc.CallOption) (*ResticSnapshotList, error) {
|
||||||
|
out := new(ResticSnapshotList)
|
||||||
|
err := c.cc.Invoke(ctx, ResticUI_ListSnapshots_FullMethodName, in, out, opts...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (c *resticUIClient) PathAutocomplete(ctx context.Context, in *types.StringValue, opts ...grpc.CallOption) (*types.StringList, error) {
|
func (c *resticUIClient) PathAutocomplete(ctx context.Context, in *types.StringValue, opts ...grpc.CallOption) (*types.StringList, error) {
|
||||||
out := new(types.StringList)
|
out := new(types.StringList)
|
||||||
err := c.cc.Invoke(ctx, ResticUI_PathAutocomplete_FullMethodName, in, out, opts...)
|
err := c.cc.Invoke(ctx, ResticUI_PathAutocomplete_FullMethodName, in, out, opts...)
|
||||||
@@ -123,6 +134,7 @@ type ResticUIServer interface {
|
|||||||
SetConfig(context.Context, *Config) (*Config, error)
|
SetConfig(context.Context, *Config) (*Config, error)
|
||||||
AddRepo(context.Context, *Repo) (*Config, error)
|
AddRepo(context.Context, *Repo) (*Config, error)
|
||||||
GetEvents(*emptypb.Empty, ResticUI_GetEventsServer) error
|
GetEvents(*emptypb.Empty, ResticUI_GetEventsServer) error
|
||||||
|
ListSnapshots(context.Context, *ListSnapshotsRequest) (*ResticSnapshotList, error)
|
||||||
PathAutocomplete(context.Context, *types.StringValue) (*types.StringList, error)
|
PathAutocomplete(context.Context, *types.StringValue) (*types.StringList, error)
|
||||||
mustEmbedUnimplementedResticUIServer()
|
mustEmbedUnimplementedResticUIServer()
|
||||||
}
|
}
|
||||||
@@ -143,6 +155,9 @@ func (UnimplementedResticUIServer) AddRepo(context.Context, *Repo) (*Config, err
|
|||||||
func (UnimplementedResticUIServer) GetEvents(*emptypb.Empty, ResticUI_GetEventsServer) error {
|
func (UnimplementedResticUIServer) GetEvents(*emptypb.Empty, ResticUI_GetEventsServer) error {
|
||||||
return status.Errorf(codes.Unimplemented, "method GetEvents not implemented")
|
return status.Errorf(codes.Unimplemented, "method GetEvents not implemented")
|
||||||
}
|
}
|
||||||
|
func (UnimplementedResticUIServer) ListSnapshots(context.Context, *ListSnapshotsRequest) (*ResticSnapshotList, error) {
|
||||||
|
return nil, status.Errorf(codes.Unimplemented, "method ListSnapshots not implemented")
|
||||||
|
}
|
||||||
func (UnimplementedResticUIServer) PathAutocomplete(context.Context, *types.StringValue) (*types.StringList, error) {
|
func (UnimplementedResticUIServer) PathAutocomplete(context.Context, *types.StringValue) (*types.StringList, error) {
|
||||||
return nil, status.Errorf(codes.Unimplemented, "method PathAutocomplete not implemented")
|
return nil, status.Errorf(codes.Unimplemented, "method PathAutocomplete not implemented")
|
||||||
}
|
}
|
||||||
@@ -234,6 +249,24 @@ func (x *resticUIGetEventsServer) Send(m *Event) error {
|
|||||||
return x.ServerStream.SendMsg(m)
|
return x.ServerStream.SendMsg(m)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func _ResticUI_ListSnapshots_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||||
|
in := new(ListSnapshotsRequest)
|
||||||
|
if err := dec(in); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if interceptor == nil {
|
||||||
|
return srv.(ResticUIServer).ListSnapshots(ctx, in)
|
||||||
|
}
|
||||||
|
info := &grpc.UnaryServerInfo{
|
||||||
|
Server: srv,
|
||||||
|
FullMethod: ResticUI_ListSnapshots_FullMethodName,
|
||||||
|
}
|
||||||
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
|
return srv.(ResticUIServer).ListSnapshots(ctx, req.(*ListSnapshotsRequest))
|
||||||
|
}
|
||||||
|
return interceptor(ctx, in, info, handler)
|
||||||
|
}
|
||||||
|
|
||||||
func _ResticUI_PathAutocomplete_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
func _ResticUI_PathAutocomplete_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||||
in := new(types.StringValue)
|
in := new(types.StringValue)
|
||||||
if err := dec(in); err != nil {
|
if err := dec(in); err != nil {
|
||||||
@@ -271,6 +304,10 @@ var ResticUI_ServiceDesc = grpc.ServiceDesc{
|
|||||||
MethodName: "AddRepo",
|
MethodName: "AddRepo",
|
||||||
Handler: _ResticUI_AddRepo_Handler,
|
Handler: _ResticUI_AddRepo_Handler,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
MethodName: "ListSnapshots",
|
||||||
|
Handler: _ResticUI_ListSnapshots_Handler,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
MethodName: "PathAutocomplete",
|
MethodName: "PathAutocomplete",
|
||||||
Handler: _ResticUI_PathAutocomplete_Handler,
|
Handler: _ResticUI_PathAutocomplete_Handler,
|
||||||
|
|||||||
1
go.mod
1
go.mod
@@ -5,6 +5,7 @@ go 1.21.3
|
|||||||
require (
|
require (
|
||||||
github.com/gitploy-io/cronexpr v0.2.2
|
github.com/gitploy-io/cronexpr v0.2.2
|
||||||
github.com/google/renameio v1.0.1
|
github.com/google/renameio v1.0.1
|
||||||
|
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.1
|
||||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.18.1
|
github.com/grpc-ecosystem/grpc-gateway/v2 v2.18.1
|
||||||
github.com/hashicorp/go-multierror v1.1.1
|
github.com/hashicorp/go-multierror v1.1.1
|
||||||
go.uber.org/zap v1.26.0
|
go.uber.org/zap v1.26.0
|
||||||
|
|||||||
2
go.sum
2
go.sum
@@ -28,6 +28,8 @@ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
|
|||||||
github.com/google/renameio v1.0.1 h1:Lh/jXZmvZxb0BBeSY5VKEfidcbcbenKjZFzM/q0fSeU=
|
github.com/google/renameio v1.0.1 h1:Lh/jXZmvZxb0BBeSY5VKEfidcbcbenKjZFzM/q0fSeU=
|
||||||
github.com/google/renameio v1.0.1/go.mod h1:t/HQoYBZSsWSNK35C6CO/TpPLDVWvxOHboWUAweKUpk=
|
github.com/google/renameio v1.0.1/go.mod h1:t/HQoYBZSsWSNK35C6CO/TpPLDVWvxOHboWUAweKUpk=
|
||||||
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
|
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.1 h1:HcUWd006luQPljE73d5sk+/VgYPGUReEVz2y1/qylwY=
|
||||||
|
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.1/go.mod h1:w9Y7gY31krpLmrVU5ZPG9H7l9fZuRu5/3R3S3FMtVQ4=
|
||||||
github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo=
|
github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo=
|
||||||
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
|
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
|
||||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.2 h1:dygLcbEBA+t/P7ck6a8AkXv6juQ4cK0RHBoh32jxhHM=
|
github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.2 h1:dygLcbEBA+t/P7ck6a8AkXv6juQ4cK0RHBoh32jxhHM=
|
||||||
|
|||||||
@@ -9,18 +9,68 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
v1 "github.com/garethgeorge/resticui/gen/go/v1"
|
v1 "github.com/garethgeorge/resticui/gen/go/v1"
|
||||||
|
"github.com/garethgeorge/resticui/internal/orchestrator"
|
||||||
|
"github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/logging"
|
||||||
"github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
|
"github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
|
||||||
|
"go.uber.org/zap"
|
||||||
"google.golang.org/grpc"
|
"google.golang.org/grpc"
|
||||||
"google.golang.org/grpc/credentials/insecure"
|
"google.golang.org/grpc/credentials/insecure"
|
||||||
)
|
)
|
||||||
|
|
||||||
func serveGRPC(ctx context.Context, socket string) error {
|
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.Info(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, orchestrator *orchestrator.Orchestrator, socket string) error {
|
||||||
lis, err := net.Listen("unix", socket)
|
lis, err := net.Listen("unix", socket)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to listen: %w", err)
|
return fmt.Errorf("failed to listen: %w", err)
|
||||||
}
|
}
|
||||||
grpcServer := grpc.NewServer()
|
|
||||||
v1.RegisterResticUIServer(grpcServer, NewServer())
|
logger := zap.L()
|
||||||
|
grpcServer := grpc.NewServer(
|
||||||
|
grpc.ChainUnaryInterceptor(
|
||||||
|
logging.UnaryServerInterceptor(loggingFunc(logger)),
|
||||||
|
),
|
||||||
|
grpc.ChainStreamInterceptor(
|
||||||
|
logging.StreamServerInterceptor(loggingFunc(logger)),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
v1.RegisterResticUIServer(grpcServer, NewServer(orchestrator))
|
||||||
go func() {
|
go func() {
|
||||||
<-ctx.Done()
|
<-ctx.Done()
|
||||||
grpcServer.GracefulStop()
|
grpcServer.GracefulStop()
|
||||||
@@ -32,7 +82,7 @@ func serveGRPC(ctx context.Context, socket string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func serveHTTPHandlers(ctx context.Context, mux *runtime.ServeMux) error {
|
func serveHTTPHandlers(ctx context.Context, orchestrator *orchestrator.Orchestrator, mux *runtime.ServeMux) error {
|
||||||
tmpDir, err := os.MkdirTemp("", "resticui")
|
tmpDir, err := os.MkdirTemp("", "resticui")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to create temp dir for unix domain socket: %w", err)
|
return fmt.Errorf("failed to create temp dir for unix domain socket: %w", err)
|
||||||
@@ -49,7 +99,7 @@ func serveHTTPHandlers(ctx context.Context, mux *runtime.ServeMux) error {
|
|||||||
return fmt.Errorf("failed to register gateway: %w", err)
|
return fmt.Errorf("failed to register gateway: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := serveGRPC(ctx, socket); err != nil {
|
if err := serveGRPC(ctx, orchestrator, socket); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -57,8 +107,8 @@ func serveHTTPHandlers(ctx context.Context, mux *runtime.ServeMux) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Handler returns an http.Handler serving the API, cancel the context to cleanly shut down the server.
|
// Handler returns an http.Handler serving the API, cancel the context to cleanly shut down the server.
|
||||||
func ServeAPI(ctx context.Context, mux *http.ServeMux) error {
|
func ServeAPI(ctx context.Context, orchestrator *orchestrator.Orchestrator, mux *http.ServeMux) error {
|
||||||
apiMux := runtime.NewServeMux()
|
apiMux := runtime.NewServeMux()
|
||||||
mux.Handle("/api/", http.StripPrefix("/api", apiMux))
|
mux.Handle("/api/", http.StripPrefix("/api", apiMux))
|
||||||
return serveHTTPHandlers(ctx, apiMux)
|
return serveHTTPHandlers(ctx, orchestrator, apiMux)
|
||||||
}
|
}
|
||||||
@@ -7,18 +7,20 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/garethgeorge/resticui/gen/go/types"
|
"github.com/garethgeorge/resticui/gen/go/types"
|
||||||
v1 "github.com/garethgeorge/resticui/gen/go/v1"
|
v1 "github.com/garethgeorge/resticui/gen/go/v1"
|
||||||
"github.com/garethgeorge/resticui/internal/config"
|
"github.com/garethgeorge/resticui/internal/config"
|
||||||
|
"github.com/garethgeorge/resticui/internal/orchestrator"
|
||||||
"github.com/garethgeorge/resticui/pkg/restic"
|
"github.com/garethgeorge/resticui/pkg/restic"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
|
"google.golang.org/protobuf/proto"
|
||||||
"google.golang.org/protobuf/types/known/emptypb"
|
"google.golang.org/protobuf/types/known/emptypb"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Server struct {
|
type Server struct {
|
||||||
*v1.UnimplementedResticUIServer
|
*v1.UnimplementedResticUIServer
|
||||||
|
orchestrator *orchestrator.Orchestrator
|
||||||
|
|
||||||
reqId atomic.Uint64
|
reqId atomic.Uint64
|
||||||
eventChannelsMu sync.Mutex
|
eventChannelsMu sync.Mutex
|
||||||
@@ -27,23 +29,25 @@ type Server struct {
|
|||||||
|
|
||||||
var _ v1.ResticUIServer = &Server{}
|
var _ v1.ResticUIServer = &Server{}
|
||||||
|
|
||||||
func NewServer() *Server {
|
func NewServer(orchestrator *orchestrator.Orchestrator) *Server {
|
||||||
s := &Server{
|
s := &Server{
|
||||||
eventChannels: make(map[uint64]chan *v1.Event),
|
eventChannels: make(map[uint64]chan *v1.Event),
|
||||||
|
orchestrator: orchestrator,
|
||||||
}
|
}
|
||||||
|
|
||||||
go func() {
|
// go func() {
|
||||||
for {
|
// // TODO: disable this when proper event sources are implemented.
|
||||||
time.Sleep(3 * time.Second)
|
// for {
|
||||||
s.PublishEvent(&v1.Event{
|
// time.Sleep(3 * time.Second)
|
||||||
Event: &v1.Event_Log{
|
// s.PublishEvent(&v1.Event{
|
||||||
Log: &v1.LogEvent{
|
// Event: &v1.Event_Log{
|
||||||
Message: fmt.Sprintf("event push test, it is %v", time.Now().Format(time.RFC3339)),
|
// Log: &v1.LogEvent{
|
||||||
},
|
// Message: fmt.Sprintf("event push test, it is %v", time.Now().Format(time.RFC3339)),
|
||||||
},
|
// },
|
||||||
})
|
// },
|
||||||
}
|
// })
|
||||||
}()
|
// }
|
||||||
|
// }()
|
||||||
|
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
@@ -55,8 +59,18 @@ func (s *Server) GetConfig(ctx context.Context, empty *emptypb.Empty) (*v1.Confi
|
|||||||
|
|
||||||
// SetConfig implements POST /v1/config
|
// 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, c *v1.Config) (*v1.Config, error) {
|
||||||
err := config.Default.Update(c)
|
existing, err := config.Default.Get()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to check current config: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compare and increment modno
|
||||||
|
if existing.Modno != c.Modno {
|
||||||
|
return nil, errors.New("config modno mismatch, reload and try again")
|
||||||
|
}
|
||||||
|
c.Modno += 1
|
||||||
|
|
||||||
|
if err := config.Default.Update(c); err != nil {
|
||||||
return nil, fmt.Errorf("failed to update config: %w", err)
|
return nil, fmt.Errorf("failed to update config: %w", err)
|
||||||
}
|
}
|
||||||
return config.Default.Get()
|
return config.Default.Get()
|
||||||
@@ -69,14 +83,20 @@ func (s *Server) AddRepo(ctx context.Context, repo *v1.Repo) (*v1.Config, error)
|
|||||||
return nil, fmt.Errorf("failed to get config: %w", err)
|
return nil, fmt.Errorf("failed to get config: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
c = proto.Clone(c).(*v1.Config)
|
||||||
|
c.Repos = append(c.Repos, repo)
|
||||||
|
|
||||||
|
if err := config.ValidateConfig(c); err != nil {
|
||||||
|
return nil, fmt.Errorf("validation error: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
r := restic.NewRepo(repo)
|
r := restic.NewRepo(repo)
|
||||||
// use background context such that the init op can try to complete even if the connection is closed.
|
// 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 {
|
if err := r.Init(context.Background()); err != nil {
|
||||||
return nil, fmt.Errorf("failed to init repo: %w", err)
|
return nil, fmt.Errorf("failed to init repo: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Repos = append(c.Repos, repo)
|
zap.S().Debug("Updating config")
|
||||||
|
|
||||||
if err := config.Default.Update(c); err != nil {
|
if err := config.Default.Update(c); err != nil {
|
||||||
return nil, fmt.Errorf("failed to update config: %w", err)
|
return nil, fmt.Errorf("failed to update config: %w", err)
|
||||||
}
|
}
|
||||||
@@ -84,6 +104,40 @@ func (s *Server) AddRepo(ctx context.Context, repo *v1.Repo) (*v1.Config, error)
|
|||||||
return c, nil
|
return c, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ListSnapshots implements GET /v1/snapshots/{repo.id}/{plan.id?}
|
||||||
|
func (s *Server) ListSnapshots(ctx context.Context, query *v1.ListSnapshotsRequest) (*v1.ResticSnapshotList, error) {
|
||||||
|
repo, err := s.orchestrator.GetRepo(query.RepoId)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to get repo: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var snapshots []*restic.Snapshot
|
||||||
|
if query.PlanId != "" {
|
||||||
|
var plan *v1.Plan
|
||||||
|
plan, err = s.orchestrator.GetPlan(query.PlanId)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to get plan %q: %w", query.PlanId, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
snapshots, err = repo.SnapshotsForPlan(ctx, plan)
|
||||||
|
} else {
|
||||||
|
snapshots, err = repo.Snapshots(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to list snapshots: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Transform the snapshots and return them.
|
||||||
|
var rs []*v1.ResticSnapshot
|
||||||
|
for _, snapshot := range snapshots {
|
||||||
|
rs = append(rs, snapshot.ToProto())
|
||||||
|
}
|
||||||
|
|
||||||
|
return &v1.ResticSnapshotList{
|
||||||
|
Snapshots: rs,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
// GetEvents implements GET /v1/events
|
// GetEvents implements GET /v1/events
|
||||||
func (s *Server) GetEvents(_ *emptypb.Empty, stream v1.ResticUI_GetEventsServer) error {
|
func (s *Server) GetEvents(_ *emptypb.Empty, stream v1.ResticUI_GetEventsServer) error {
|
||||||
|
|||||||
@@ -1,18 +1,23 @@
|
|||||||
package config
|
package config
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
|
"sync"
|
||||||
|
|
||||||
v1 "github.com/garethgeorge/resticui/gen/go/v1"
|
v1 "github.com/garethgeorge/resticui/gen/go/v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var ErrConfigNotFound = fmt.Errorf("config not found")
|
||||||
var configDirFlag = flag.String("config_dir", "", "The directory to store the config file")
|
var configDirFlag = flag.String("config_dir", "", "The directory to store the config file")
|
||||||
|
|
||||||
var Default ConfigStore = &YamlFileStore{
|
var Default ConfigStore = &CachingValidatingStore{
|
||||||
|
ConfigStore: &YamlFileStore{
|
||||||
Path: path.Join(configDir(*configDirFlag), "config.yaml"),
|
Path: path.Join(configDir(*configDirFlag), "config.yaml"),
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
type ConfigStore interface {
|
type ConfigStore interface {
|
||||||
@@ -43,3 +48,50 @@ func configDir(override string) string {
|
|||||||
|
|
||||||
return fmt.Sprintf("%v/.config/resticui", home)
|
return fmt.Sprintf("%v/.config/resticui", home)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type CachingValidatingStore struct {
|
||||||
|
ConfigStore
|
||||||
|
mu sync.Mutex
|
||||||
|
config *v1.Config
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *CachingValidatingStore) Get() (*v1.Config, error) {
|
||||||
|
c.mu.Lock()
|
||||||
|
defer c.mu.Unlock()
|
||||||
|
|
||||||
|
if c.config != nil {
|
||||||
|
return c.config, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
config, err := c.ConfigStore.Get()
|
||||||
|
if err != nil {
|
||||||
|
if errors.Is(err, ErrConfigNotFound) {
|
||||||
|
c.config = NewDefaultConfig()
|
||||||
|
return c.config, nil
|
||||||
|
}
|
||||||
|
return c.config, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := ValidateConfig(config); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
c.config = config
|
||||||
|
return config, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *CachingValidatingStore) Update(config *v1.Config) error {
|
||||||
|
c.mu.Lock()
|
||||||
|
defer c.mu.Unlock()
|
||||||
|
|
||||||
|
if err := ValidateConfig(config); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := c.ConfigStore.Update(config); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
c.config = config
|
||||||
|
return nil
|
||||||
|
}
|
||||||
114
internal/config/config_test.go
Normal file
114
internal/config/config_test.go
Normal file
@@ -0,0 +1,114 @@
|
|||||||
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
v1 "github.com/garethgeorge/resticui/gen/go/v1"
|
||||||
|
"google.golang.org/protobuf/proto"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
func TestConfig(t *testing.T) {
|
||||||
|
dir := t.TempDir()
|
||||||
|
|
||||||
|
testRepo := &v1.Repo{
|
||||||
|
Id: "test-repo",
|
||||||
|
Uri: "/tmp/test",
|
||||||
|
Password: "test",
|
||||||
|
}
|
||||||
|
|
||||||
|
testPlan := &v1.Plan{
|
||||||
|
Id: "test-plan",
|
||||||
|
Repo: "test-repo",
|
||||||
|
Paths: []string{"/tmp/foo"},
|
||||||
|
Cron: "* * * * *",
|
||||||
|
}
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
config *v1.Config
|
||||||
|
wantErr bool
|
||||||
|
wantErrContains string
|
||||||
|
store ConfigStore
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "default config",
|
||||||
|
config: NewDefaultConfig(),
|
||||||
|
store: &CachingValidatingStore{ConfigStore: &YamlFileStore{Path: dir + "/default-config.yaml"}},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "simple valid config",
|
||||||
|
config: &v1.Config{
|
||||||
|
Repos: []*v1.Repo{testRepo},
|
||||||
|
Plans: []*v1.Plan{testPlan},
|
||||||
|
},
|
||||||
|
store: &CachingValidatingStore{ConfigStore: &YamlFileStore{Path: dir + "/valid-config.yaml"}},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "plan references non-existent repo",
|
||||||
|
config: &v1.Config{
|
||||||
|
Plans: []*v1.Plan{testPlan},
|
||||||
|
},
|
||||||
|
store: &CachingValidatingStore{ConfigStore: &YamlFileStore{Path: dir + "/invalid-config.yaml"}},
|
||||||
|
wantErr: true,
|
||||||
|
wantErrContains: "repo \"test-repo\" not found",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "repo with duplicate id",
|
||||||
|
config: &v1.Config{
|
||||||
|
Repos: []*v1.Repo{
|
||||||
|
testRepo,
|
||||||
|
testRepo,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
store: &CachingValidatingStore{ConfigStore: &YamlFileStore{Path: dir + "/invalid-config2.yaml"}},
|
||||||
|
wantErr: true,
|
||||||
|
wantErrContains: "repo test-repo: duplicate id",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "plan with bad cron",
|
||||||
|
config: &v1.Config{
|
||||||
|
Repos: []*v1.Repo{
|
||||||
|
testRepo,
|
||||||
|
},
|
||||||
|
Plans: []*v1.Plan{
|
||||||
|
{
|
||||||
|
Id: "test-plan",
|
||||||
|
Repo: "test-repo",
|
||||||
|
Paths: []string{"/tmp/foo"},
|
||||||
|
Cron: "bad cron",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
store: &CachingValidatingStore{ConfigStore: &YamlFileStore{Path: dir + "/invalid-config3.yaml"}},
|
||||||
|
wantErr: true,
|
||||||
|
wantErrContains: "invalid cron \"bad cron\"",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range tests {
|
||||||
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
err := tc.store.Update(tc.config)
|
||||||
|
if (err != nil) != tc.wantErr {
|
||||||
|
t.Errorf("Config.Update() error = %v, wantErr %v", err, tc.wantErr)
|
||||||
|
}
|
||||||
|
|
||||||
|
if tc.wantErrContains != "" && (err == nil || !strings.Contains(err.Error(), tc.wantErrContains)) {
|
||||||
|
t.Errorf("Config.Update() error = %v, wantErrContains %v", err, tc.wantErrContains)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err == nil {
|
||||||
|
config, err := tc.store.Get()
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Config.Get() error = %v, wantErr nil", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !proto.Equal(config, tc.config) {
|
||||||
|
t.Errorf("Config.Get() = %v, want %v", config, tc.config)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -11,7 +11,7 @@ import (
|
|||||||
"github.com/hashicorp/go-multierror"
|
"github.com/hashicorp/go-multierror"
|
||||||
)
|
)
|
||||||
|
|
||||||
func validateConfig(c *v1.Config) error {
|
func ValidateConfig(c *v1.Config) error {
|
||||||
var err error
|
var err error
|
||||||
repos := make(map[string]*v1.Repo)
|
repos := make(map[string]*v1.Repo)
|
||||||
if c.Repos != nil {
|
if c.Repos != nil {
|
||||||
@@ -19,15 +19,17 @@ func validateConfig(c *v1.Config) error {
|
|||||||
if e := validateRepo(repo); e != nil {
|
if e := validateRepo(repo); e != nil {
|
||||||
err = multierror.Append(e, fmt.Errorf("repo %s: %w", repo.GetId(), err))
|
err = multierror.Append(e, fmt.Errorf("repo %s: %w", repo.GetId(), err))
|
||||||
}
|
}
|
||||||
|
if _, ok := repos[repo.GetId()]; ok {
|
||||||
|
err = multierror.Append(err, fmt.Errorf("repo %s: duplicate id", repo.GetId()))
|
||||||
|
}
|
||||||
repos[repo.GetId()] = repo
|
repos[repo.GetId()] = repo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.Plans != nil {
|
if c.Plans != nil {
|
||||||
for _, plan := range c.Plans {
|
for _, plan := range c.Plans {
|
||||||
err := validatePlan(plan, repos);
|
if e := validatePlan(plan, repos); e != nil {
|
||||||
if err != nil {
|
err = multierror.Append(err, fmt.Errorf("plan %s: %w", plan.GetId(), e))
|
||||||
err = multierror.Append(err, fmt.Errorf("plan %s: %w", plan.GetId(), err))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -73,7 +75,7 @@ func validatePlan(plan *v1.Plan, repos map[string]*v1.Repo) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if _, e := cronexpr.Parse(plan.GetCron()); err != nil {
|
if _, e := cronexpr.Parse(plan.GetCron()); e != nil {
|
||||||
err = multierror.Append(err, fmt.Errorf("invalid cron %q: %w", plan.GetCron(), e))
|
err = multierror.Append(err, fmt.Errorf("invalid cron %q: %w", plan.GetCron(), e))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,31 +17,22 @@ import (
|
|||||||
type YamlFileStore struct {
|
type YamlFileStore struct {
|
||||||
Path string
|
Path string
|
||||||
mu sync.Mutex
|
mu sync.Mutex
|
||||||
config *v1.Config
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ ConfigStore = &YamlFileStore{}
|
var _ ConfigStore = &YamlFileStore{}
|
||||||
|
|
||||||
func (f *YamlFileStore) Get() (*v1.Config, error) {
|
func (f *YamlFileStore) Get() (*v1.Config, error) {
|
||||||
f.mu.Lock()
|
f.mu.Lock()
|
||||||
|
defer f.mu.Unlock()
|
||||||
if f.config != nil {
|
|
||||||
f.mu.Unlock()
|
|
||||||
return f.config, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
data, err := os.ReadFile(f.Path)
|
data, err := os.ReadFile(f.Path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, os.ErrNotExist) {
|
if errors.Is(err, os.ErrNotExist) {
|
||||||
f.config = NewDefaultConfig()
|
return nil, ErrConfigNotFound
|
||||||
f.mu.Unlock()
|
|
||||||
f.Update(f.config)
|
|
||||||
return f.config, nil
|
|
||||||
}
|
}
|
||||||
return nil, fmt.Errorf("failed to read config file: %w", err)
|
return nil, fmt.Errorf("failed to read config file: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
defer f.mu.Unlock()
|
|
||||||
|
|
||||||
data, err = yamlToJson(data)
|
data, err = yamlToJson(data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -54,19 +45,18 @@ func (f *YamlFileStore) Get() (*v1.Config, error) {
|
|||||||
return nil, fmt.Errorf("failed to unmarshal config: %w", err)
|
return nil, fmt.Errorf("failed to unmarshal config: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := validateConfig(&config); err != nil {
|
if err := ValidateConfig(&config); err != nil {
|
||||||
return nil, fmt.Errorf("invalid config: %w", err)
|
return nil, fmt.Errorf("invalid config: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
f.config = &config
|
return &config, nil
|
||||||
return f.config, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *YamlFileStore) Update(config *v1.Config) error {
|
func (f *YamlFileStore) Update(config *v1.Config) error {
|
||||||
f.mu.Lock()
|
f.mu.Lock()
|
||||||
defer f.mu.Unlock()
|
defer f.mu.Unlock()
|
||||||
|
|
||||||
if err := validateConfig(config); err != nil {
|
if err := ValidateConfig(config); err != nil {
|
||||||
return fmt.Errorf("invalid config: %w", err)
|
return fmt.Errorf("invalid config: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -90,7 +80,6 @@ func (f *YamlFileStore) Update(config *v1.Config) error {
|
|||||||
return fmt.Errorf("failed to write config file: %w", err)
|
return fmt.Errorf("failed to write config file: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
f.config = config
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
121
internal/orchestrator/orchestrator.go
Normal file
121
internal/orchestrator/orchestrator.go
Normal file
@@ -0,0 +1,121 @@
|
|||||||
|
package orchestrator
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
v1 "github.com/garethgeorge/resticui/gen/go/v1"
|
||||||
|
"github.com/garethgeorge/resticui/internal/config"
|
||||||
|
"github.com/garethgeorge/resticui/pkg/restic"
|
||||||
|
"google.golang.org/protobuf/proto"
|
||||||
|
)
|
||||||
|
|
||||||
|
var ErrRepoNotFound = errors.New("repo not found")
|
||||||
|
var ErrRepoInitializationFailed = errors.New("repo initialization failed")
|
||||||
|
var ErrPlanNotFound = errors.New("plan not found")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Orchestrator is responsible for managing repos and backups.
|
||||||
|
type Orchestrator struct {
|
||||||
|
configProvider config.ConfigStore
|
||||||
|
repoPool *resticRepoPool
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewOrchestrator(configProvider config.ConfigStore) *Orchestrator {
|
||||||
|
return &Orchestrator{
|
||||||
|
configProvider: configProvider,
|
||||||
|
repoPool: newResticRepoPool(configProvider),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *Orchestrator) GetRepo(repoId string) (repo *RepoOrchestrator, err error) {
|
||||||
|
r, err := o.repoPool.GetRepo(repoId)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to get repo %q: %w", repoId, err)
|
||||||
|
}
|
||||||
|
return r, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *Orchestrator) GetPlan(planId string) (*v1.Plan, error) {
|
||||||
|
cfg, err := o.configProvider.Get()
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to get config: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if cfg.Plans == nil {
|
||||||
|
return nil, ErrPlanNotFound
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, p := range cfg.Plans {
|
||||||
|
if p.Id == planId {
|
||||||
|
return p, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, ErrPlanNotFound
|
||||||
|
}
|
||||||
|
|
||||||
|
// resticRepoPool caches restic repos.
|
||||||
|
type resticRepoPool struct {
|
||||||
|
mu sync.Mutex
|
||||||
|
repos map[string]*RepoOrchestrator
|
||||||
|
configProvider config.ConfigStore
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
func newResticRepoPool(configProvider config.ConfigStore) *resticRepoPool {
|
||||||
|
return &resticRepoPool{
|
||||||
|
repos: make(map[string]*RepoOrchestrator),
|
||||||
|
configProvider: configProvider,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rp *resticRepoPool) GetRepo(repoId string) (repo *RepoOrchestrator, err error) {
|
||||||
|
cfg, err := rp.configProvider.Get()
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to get config: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
rp.mu.Lock()
|
||||||
|
defer rp.mu.Unlock()
|
||||||
|
|
||||||
|
if cfg.Repos == nil {
|
||||||
|
return nil, ErrRepoNotFound
|
||||||
|
}
|
||||||
|
|
||||||
|
var repoProto *v1.Repo
|
||||||
|
for _, r := range cfg.Repos {
|
||||||
|
if r.GetId() == repoId {
|
||||||
|
repoProto = r
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if repoProto == nil {
|
||||||
|
return nil, ErrRepoNotFound
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if we already have a repo for this id, if we do return it.
|
||||||
|
repo, ok := rp.repos[repoId]
|
||||||
|
if ok && proto.Equal(repo.repoConfig, repoProto) {
|
||||||
|
return repo, nil
|
||||||
|
}
|
||||||
|
delete(rp.repos, repoId);
|
||||||
|
|
||||||
|
var opts []restic.GenericOption
|
||||||
|
if len(repoProto.GetEnv()) > 0 {
|
||||||
|
opts = append(opts, restic.WithEnv(repoProto.GetEnv()...))
|
||||||
|
}
|
||||||
|
if len(repoProto.GetFlags()) > 0 {
|
||||||
|
opts = append(opts, restic.WithFlags(repoProto.GetFlags()...))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise create a new repo.
|
||||||
|
repo = &RepoOrchestrator{
|
||||||
|
repoConfig: repoProto,
|
||||||
|
repo: restic.NewRepo(repoProto, opts...),
|
||||||
|
}
|
||||||
|
rp.repos[repoId] = repo
|
||||||
|
return repo, nil
|
||||||
|
}
|
||||||
108
internal/orchestrator/repo.go
Normal file
108
internal/orchestrator/repo.go
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
package orchestrator
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"slices"
|
||||||
|
"sort"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
v1 "github.com/garethgeorge/resticui/gen/go/v1"
|
||||||
|
"github.com/garethgeorge/resticui/pkg/restic"
|
||||||
|
)
|
||||||
|
|
||||||
|
// RepoOrchestrator is responsible for managing a single repo.
|
||||||
|
type RepoOrchestrator struct {
|
||||||
|
mu sync.Mutex
|
||||||
|
|
||||||
|
repoConfig *v1.Repo
|
||||||
|
repo *restic.Repo
|
||||||
|
|
||||||
|
snapshotsAge time.Time
|
||||||
|
snapshots []*restic.Snapshot
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *RepoOrchestrator) updateSnapshotsIfNeeded(ctx context.Context) error {
|
||||||
|
if time.Since(r.snapshotsAge) > 10 * time.Minute {
|
||||||
|
r.snapshots = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if r.snapshots != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
snapshots, err := r.repo.Snapshots(ctx, restic.WithPropagatedEnvVars(restic.EnvToPropagate...))
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to update snapshots: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
sort.SliceStable(snapshots, func(i, j int) bool {
|
||||||
|
return snapshots[i].Time > snapshots[j].Time
|
||||||
|
})
|
||||||
|
|
||||||
|
r.snapshots = snapshots
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *RepoOrchestrator) Snapshots(ctx context.Context) ([]*restic.Snapshot, error) {
|
||||||
|
r.mu.Lock()
|
||||||
|
defer r.mu.Unlock()
|
||||||
|
|
||||||
|
if err := r.updateSnapshotsIfNeeded(ctx); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return r.snapshots, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *RepoOrchestrator) SnapshotsForPlan(ctx context.Context, plan *v1.Plan) ([]*restic.Snapshot, error) {
|
||||||
|
r.mu.Lock()
|
||||||
|
defer r.mu.Unlock()
|
||||||
|
|
||||||
|
if err := r.updateSnapshotsIfNeeded(ctx); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return filterSnapshotsForPlan(r.snapshots, plan), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *RepoOrchestrator) Backup(ctx context.Context, plan *v1.Plan, progressCallback func(event *restic.BackupProgressEntry)) error {
|
||||||
|
snapshots, err := r.SnapshotsForPlan(ctx, plan)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
var opts []restic.BackupOption
|
||||||
|
opts = append(opts, restic.WithBackupPaths(plan.Paths...))
|
||||||
|
opts = append(opts, restic.WithBackupExcludes(plan.Excludes...))
|
||||||
|
opts = append(opts, restic.WithBackupTags(tagForPlan(plan)))
|
||||||
|
|
||||||
|
if len(snapshots) > 0 {
|
||||||
|
// TODO: design a test strategy to verify that the backup parent is used correctly.
|
||||||
|
opts = append(opts, restic.WithBackupParent(snapshots[len(snapshots) - 1].Id))
|
||||||
|
}
|
||||||
|
|
||||||
|
panic("not yet implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
func filterSnapshotsForPlan(snapshots []*restic.Snapshot, plan *v1.Plan) []*restic.Snapshot {
|
||||||
|
wantTag := tagForPlan(plan)
|
||||||
|
var filtered []*restic.Snapshot
|
||||||
|
for _, snapshot := range snapshots {
|
||||||
|
if snapshot.Tags == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if slices.Contains(snapshot.Tags, wantTag) {
|
||||||
|
filtered = append(filtered, snapshot)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return filtered
|
||||||
|
}
|
||||||
|
|
||||||
|
func tagForPlan(plan *v1.Plan) string {
|
||||||
|
return fmt.Sprintf("plan:%s", plan.Id)
|
||||||
|
}
|
||||||
@@ -7,6 +7,9 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"slices"
|
"slices"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
v1 "github.com/garethgeorge/resticui/gen/go/v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
type LsEntry struct {
|
type LsEntry struct {
|
||||||
@@ -33,6 +36,23 @@ type Snapshot struct {
|
|||||||
Parent string `json:"parent"`
|
Parent string `json:"parent"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Snapshot) ToProto() *v1.ResticSnapshot {
|
||||||
|
t, err := time.Parse(time.RFC3339Nano, s.Time)
|
||||||
|
if err != nil {
|
||||||
|
t = time.Unix(0, 0)
|
||||||
|
}
|
||||||
|
return &v1.ResticSnapshot{
|
||||||
|
Id: s.Id,
|
||||||
|
UnixTimeMs: t.UnixMilli(),
|
||||||
|
Tree: s.Tree,
|
||||||
|
Paths: s.Paths,
|
||||||
|
Hostname: s.Hostname,
|
||||||
|
Username: s.Username,
|
||||||
|
Tags: s.Tags,
|
||||||
|
Parent: s.Parent,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
type BackupProgressEntry struct {
|
type BackupProgressEntry struct {
|
||||||
// Common fields
|
// Common fields
|
||||||
MessageType string `json:"message_type"` // "summary" or "status"
|
MessageType string `json:"message_type"` // "summary" or "status"
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ func TestReadBackupProgressEntries(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func TestReadLs(t *testing.T) {
|
func TestReadLs(t *testing.T) {
|
||||||
testInput := `{"time":"2023-11-10T19:14:17.053824063-08:00","tree":"3e2918b261948e69602ee9504b8f475bcc7cdc4dcec0b3f34ecdb014287d07b2","paths":["/resticui"],"hostname":"pop-os","username":"dontpanic","uid":1000,"gid":1000,"id":"db155169d788e6e432e320aedbdff5a54cc439653093bb56944a67682528aa52","short_id":"db155169","struct_type":"snapshot"}
|
testInput := `{"time":"2023-11-10T19:14:17.053824063-08:00","tree":"3e2918b261948e69602ee9504b8f475bcc7cdc4dcec0b3f34ecdb014287d07b2","paths":["/resticui"],"hostname":"pop-os","username":"dontpanic","uid":1000,"gid":1000,"id":"db155169d788e6e432e320aedbdff5a54cc439653093bb56944a67682528aa52","short_id":"db155169","struct_type":"snapshot"}
|
||||||
{"name":".git","type":"dir","path":"/.git","uid":1000,"gid":1000,"mode":2147484157,"mtime":"2023-11-10T18:32:38.156599473-08:00","atime":"2023-11-10T18:32:38.156599473-08:00","ctime":"2023-11-10T18:32:38.156599473-08:00","struct_type":"node"}
|
{"name":".git","type":"dir","path":"/.git","uid":1000,"gid":1000,"mode":2147484157,"mtime":"2023-11-10T18:32:38.156599473-08:00","atime":"2023-11-10T18:32:38.156599473-08:00","ctime":"2023-11-10T18:32:38.156599473-08:00","struct_type":"node"}
|
||||||
@@ -46,3 +47,40 @@ func TestReadLs(t *testing.T) {
|
|||||||
t.Errorf("wanted 3 entries, got: %d", len(entries))
|
t.Errorf("wanted 3 entries, got: %d", len(entries))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestSnapshotToProto(t *testing.T) {
|
||||||
|
snapshot := &Snapshot{
|
||||||
|
Id: "db155169d788e6e432e320aedbdff5a54cc439653093bb56944a67682528aa52",
|
||||||
|
Time: "2023-11-10T19:14:17.053824063-08:00",
|
||||||
|
Tree: "3e2918b261948e69602ee9504b8f475bcc7cdc4dcec0b3f34ecdb014287d07b2",
|
||||||
|
Paths: []string{"/resticui"},
|
||||||
|
Hostname: "pop-os",
|
||||||
|
Username: "dontpanic",
|
||||||
|
Tags: []string{},
|
||||||
|
Parent: "",
|
||||||
|
}
|
||||||
|
|
||||||
|
proto := snapshot.ToProto()
|
||||||
|
|
||||||
|
if proto.Id != snapshot.Id {
|
||||||
|
t.Errorf("wanted id %q, got: %q", snapshot.Id, proto.Id)
|
||||||
|
}
|
||||||
|
if proto.Tree != snapshot.Tree {
|
||||||
|
t.Errorf("wanted tree %q, got: %q", snapshot.Tree, proto.Tree)
|
||||||
|
}
|
||||||
|
if proto.Hostname != snapshot.Hostname {
|
||||||
|
t.Errorf("wanted hostname %q, got: %q", snapshot.Hostname, proto.Hostname)
|
||||||
|
}
|
||||||
|
if proto.Username != snapshot.Username {
|
||||||
|
t.Errorf("wanted username %q, got: %q", snapshot.Username, proto.Username)
|
||||||
|
}
|
||||||
|
if len(proto.Tags) != len(snapshot.Tags) {
|
||||||
|
t.Errorf("wanted %d tags, got: %d", len(snapshot.Tags), len(proto.Tags))
|
||||||
|
}
|
||||||
|
if proto.Parent != snapshot.Parent {
|
||||||
|
t.Errorf("wanted parent %q, got: %q", snapshot.Parent, proto.Parent)
|
||||||
|
}
|
||||||
|
if proto.UnixTimeMs != 1699672457053 {
|
||||||
|
t.Errorf("wanted unix time %d, got: %d", 1699672457053, proto.UnixTimeMs)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -9,6 +9,7 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
v1 "github.com/garethgeorge/resticui/gen/go/v1"
|
v1 "github.com/garethgeorge/resticui/gen/go/v1"
|
||||||
@@ -25,6 +26,7 @@ type Repo struct {
|
|||||||
extraEnv []string
|
extraEnv []string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewRepo instantiates a new repository. TODO: should not accept a v1.Repo
|
||||||
func NewRepo(repo *v1.Repo, opts ...GenericOption) *Repo {
|
func NewRepo(repo *v1.Repo, opts ...GenericOption) *Repo {
|
||||||
opt := &GenericOpts{}
|
opt := &GenericOpts{}
|
||||||
for _, o := range opts {
|
for _, o := range opts {
|
||||||
@@ -63,8 +65,10 @@ func (r *Repo) init(ctx context.Context) error {
|
|||||||
cmd.Env = append(cmd.Env, r.buildEnv()...)
|
cmd.Env = append(cmd.Env, r.buildEnv()...)
|
||||||
|
|
||||||
if output, err := cmd.CombinedOutput(); err != nil {
|
if output, err := cmd.CombinedOutput(); err != nil {
|
||||||
|
if !strings.Contains(string(output), "config file already exists") {
|
||||||
return NewCmdError(cmd, output, err)
|
return NewCmdError(cmd, output, err)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
r.initialized = true
|
r.initialized = true
|
||||||
return nil
|
return nil
|
||||||
@@ -242,6 +246,12 @@ func WithBackupTags(tags ...string) BackupOption {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func WithBackupParent(parent string) BackupOption {
|
||||||
|
return func(opts *BackupOpts) {
|
||||||
|
opts.extraArgs = append(opts.extraArgs, "--parent", parent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
type GenericOpts struct {
|
type GenericOpts struct {
|
||||||
extraArgs []string
|
extraArgs []string
|
||||||
extraEnv []string
|
extraEnv []string
|
||||||
|
|||||||
@@ -140,6 +140,13 @@ func TestSnapshot(t *testing.T) {
|
|||||||
if len(snapshots) != tc.count {
|
if len(snapshots) != tc.count {
|
||||||
t.Errorf("wanted %d snapshots, got: %d", tc.count, len(snapshots))
|
t.Errorf("wanted %d snapshots, got: %d", tc.count, len(snapshots))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ensure that snapshot timestamps are set, this is critical for correct ordering in the orchestrator.
|
||||||
|
for _, snapshot := range snapshots {
|
||||||
|
if p := snapshot.ToProto(); p.UnixTimeMs == 0 {
|
||||||
|
t.Errorf("wanted snapshot time to be non-zero, got: %v", p.UnixTimeMs)
|
||||||
|
}
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,14 +5,15 @@ package v1;
|
|||||||
option go_package = "github.com/garethgeorge/resticui/go/proto/v1";
|
option go_package = "github.com/garethgeorge/resticui/go/proto/v1";
|
||||||
|
|
||||||
message Config {
|
message Config {
|
||||||
int32 version = 1;
|
// modification number, used for read-modify-write consistency in the UI. Incremented on every write.
|
||||||
repeated Repo repos = 3 [json_name="repos"];
|
int32 modno = 1 [json_name="modno"];
|
||||||
repeated Plan plans = 4 [json_name="plans"];
|
|
||||||
}
|
|
||||||
|
|
||||||
message User {
|
// override the hostname tagged on backups. If provided it will be used in addition to tags to group backups.
|
||||||
string name = 1;
|
string host_override = 2 [json_name="host_override"];
|
||||||
string password = 2; // plaintext password
|
|
||||||
|
repeated Repo repos = 3 [json_name="repos"];
|
||||||
|
|
||||||
|
repeated Plan plans = 4 [json_name="plans"];
|
||||||
}
|
}
|
||||||
|
|
||||||
message Repo {
|
message Repo {
|
||||||
|
|||||||
@@ -6,22 +6,22 @@ option go_package = "github.com/garethgeorge/resticui/go/proto/v1";
|
|||||||
|
|
||||||
message Event {
|
message Event {
|
||||||
// timestamp is the number of milliseconds since the Unix epoch.
|
// timestamp is the number of milliseconds since the Unix epoch.
|
||||||
int64 timestamp = 1 [json_name="timestamp"];
|
int64 timestamp = 1;
|
||||||
|
|
||||||
oneof event {
|
oneof event {
|
||||||
LogEvent log = 3 [json_name="log"];
|
LogEvent log = 3;
|
||||||
BackupStatusEvent backup_status_change = 4 [json_name="backup_status"];
|
BackupStatusEvent backup_status_change = 4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
message LogEvent {
|
message LogEvent {
|
||||||
string message = 1 [json_name="message"];
|
string message = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
message BackupStatusEvent {
|
message BackupStatusEvent {
|
||||||
string plan = 1 [json_name="plan"];
|
string plan = 1;
|
||||||
Status status = 2 [json_name="status"];
|
Status status = 2;
|
||||||
uint32 percent = 3 [json_name="percent"];
|
uint32 percent = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum Status {
|
enum Status {
|
||||||
|
|||||||
@@ -5,43 +5,47 @@ package v1;
|
|||||||
option go_package = "github.com/garethgeorge/resticui/go/proto/v1";
|
option go_package = "github.com/garethgeorge/resticui/go/proto/v1";
|
||||||
|
|
||||||
message ResticSnapshot {
|
message ResticSnapshot {
|
||||||
string id = 1 [json_name = "id"];
|
string id = 1;
|
||||||
int64 unix_time_ms = 2 [json_name = "time"];
|
int64 unix_time_ms = 2;
|
||||||
string hostname = 3 [json_name = "hostname"];
|
string hostname = 3;
|
||||||
string username = 4 [json_name = "username"];
|
string username = 4;
|
||||||
string tree = 5 [json_name = "tree"]; // tree hash
|
string tree = 5; // tree hash
|
||||||
string parent = 6 [json_name = "parent"]; // parent snapshot's id
|
string parent = 6; // parent snapshot's id
|
||||||
repeated string paths = 7 [json_name = "paths"];
|
repeated string paths = 7;
|
||||||
repeated string tags = 8 [json_name = "tags"];
|
repeated string tags = 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResticSnapshotList {
|
||||||
|
repeated ResticSnapshot snapshots = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
message BackupProgressEntry {
|
message BackupProgressEntry {
|
||||||
oneof entry {
|
oneof entry {
|
||||||
BackupProgressStatusEntry status = 1 [json_name = "status"];
|
BackupProgressStatusEntry status = 1;
|
||||||
BackupProgressSummary summary = 2 [json_name = "summary"];
|
BackupProgressSummary summary = 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
message BackupProgressStatusEntry {
|
message BackupProgressStatusEntry {
|
||||||
double percent_done = 1 [json_name = "percent"]; // 0.0 - 1.0
|
double percent_done = 1; // 0.0 - 1.0
|
||||||
int64 total_files = 2 [json_name = "total_files"];
|
int64 total_files = 2;
|
||||||
int64 total_bytes = 3 [json_name = "total_bytes"];
|
int64 total_bytes = 3;
|
||||||
int64 files_done = 4 [json_name = "files_done"];
|
int64 files_done = 4;
|
||||||
int64 bytes_done = 5 [json_name = "bytes_done"];
|
int64 bytes_done = 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
message BackupProgressSummary {
|
message BackupProgressSummary {
|
||||||
int64 files_new = 1 [json_name = "files_new"];
|
int64 files_new = 1;
|
||||||
int64 files_changed = 2 [json_name = "files_changed"];
|
int64 files_changed = 2;
|
||||||
int64 files_unmodified = 3 [json_name = "files_unmodified"];
|
int64 files_unmodified = 3;
|
||||||
int64 dirs_new = 4 [json_name = "dirs_new"];
|
int64 dirs_new = 4;
|
||||||
int64 dirs_changed = 5 [json_name = "dirs_changed"];
|
int64 dirs_changed = 5;
|
||||||
int64 dirs_unmodified = 6 [json_name = "dirs_unmodified"];
|
int64 dirs_unmodified = 6;
|
||||||
int64 data_blobs = 7 [json_name = "data_blobs"];
|
int64 data_blobs = 7;
|
||||||
int64 tree_blobs = 8 [json_name = "tree_blobs"];
|
int64 tree_blobs = 8;
|
||||||
int64 data_added = 9 [json_name = "data_added"];
|
int64 data_added = 9;
|
||||||
int64 total_files_processed = 10 [json_name = "total_files_processed"];
|
int64 total_files_processed = 10;
|
||||||
int64 total_bytes_processed = 11 [json_name = "total_bytes_processed"];
|
int64 total_bytes_processed = 11;
|
||||||
int64 total_duration = 12 [json_name = "total_duration"];
|
int64 total_duration = 12;
|
||||||
string snapshot_id = 13 [json_name = "snapshot_id"];
|
string snapshot_id = 13;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ option go_package = "github.com/garethgeorge/resticui/go/proto/v1";
|
|||||||
|
|
||||||
import "v1/config.proto";
|
import "v1/config.proto";
|
||||||
import "v1/events.proto";
|
import "v1/events.proto";
|
||||||
|
import "v1/restic.proto";
|
||||||
import "types/value.proto";
|
import "types/value.proto";
|
||||||
import "google/protobuf/empty.proto";
|
import "google/protobuf/empty.proto";
|
||||||
import "google/api/annotations.proto";
|
import "google/api/annotations.proto";
|
||||||
@@ -37,6 +38,13 @@ service ResticUI {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rpc ListSnapshots(ListSnapshotsRequest) returns (ResticSnapshotList) {
|
||||||
|
option (google.api.http) = {
|
||||||
|
post: "/v1/snapshots"
|
||||||
|
body: "*"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
rpc PathAutocomplete (types.StringValue) returns (types.StringList) {
|
rpc PathAutocomplete (types.StringValue) returns (types.StringList) {
|
||||||
option (google.api.http) = {
|
option (google.api.http) = {
|
||||||
post: "/v1/autocomplete/path"
|
post: "/v1/autocomplete/path"
|
||||||
@@ -44,3 +52,8 @@ service ResticUI {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message ListSnapshotsRequest {
|
||||||
|
string repo_id = 1;
|
||||||
|
string plan_id = 2;
|
||||||
|
}
|
||||||
|
|||||||
@@ -4,16 +4,12 @@
|
|||||||
* This file is a generated Typescript file for GRPC Gateway, DO NOT MODIFY
|
* This file is a generated Typescript file for GRPC Gateway, DO NOT MODIFY
|
||||||
*/
|
*/
|
||||||
export type Config = {
|
export type Config = {
|
||||||
version?: number
|
modno?: number
|
||||||
|
hostOverride?: string
|
||||||
repos?: Repo[]
|
repos?: Repo[]
|
||||||
plans?: Plan[]
|
plans?: Plan[]
|
||||||
}
|
}
|
||||||
|
|
||||||
export type User = {
|
|
||||||
name?: string
|
|
||||||
password?: string
|
|
||||||
}
|
|
||||||
|
|
||||||
export type Repo = {
|
export type Repo = {
|
||||||
id?: string
|
id?: string
|
||||||
uri?: string
|
uri?: string
|
||||||
|
|||||||
@@ -23,6 +23,10 @@ export type ResticSnapshot = {
|
|||||||
tags?: string[]
|
tags?: string[]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type ResticSnapshotList = {
|
||||||
|
snapshots?: ResticSnapshot[]
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
type BaseBackupProgressEntry = {
|
type BaseBackupProgressEntry = {
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,12 @@ import * as GoogleProtobufEmpty from "../google/protobuf/empty.pb"
|
|||||||
import * as TypesValue from "../types/value.pb"
|
import * as TypesValue from "../types/value.pb"
|
||||||
import * as V1Config from "./config.pb"
|
import * as V1Config from "./config.pb"
|
||||||
import * as V1Events from "./events.pb"
|
import * as V1Events from "./events.pb"
|
||||||
|
import * as V1Restic from "./restic.pb"
|
||||||
|
export type ListSnapshotsRequest = {
|
||||||
|
repoId?: string
|
||||||
|
planId?: string
|
||||||
|
}
|
||||||
|
|
||||||
export class ResticUI {
|
export class ResticUI {
|
||||||
static GetConfig(req: GoogleProtobufEmpty.Empty, initReq?: fm.InitReq): Promise<V1Config.Config> {
|
static GetConfig(req: GoogleProtobufEmpty.Empty, initReq?: fm.InitReq): Promise<V1Config.Config> {
|
||||||
return fm.fetchReq<GoogleProtobufEmpty.Empty, V1Config.Config>(`/v1/config?${fm.renderURLSearchParams(req, [])}`, {...initReq, method: "GET"})
|
return fm.fetchReq<GoogleProtobufEmpty.Empty, V1Config.Config>(`/v1/config?${fm.renderURLSearchParams(req, [])}`, {...initReq, method: "GET"})
|
||||||
@@ -22,6 +28,9 @@ export class ResticUI {
|
|||||||
static GetEvents(req: GoogleProtobufEmpty.Empty, entityNotifier?: fm.NotifyStreamEntityArrival<V1Events.Event>, initReq?: fm.InitReq): Promise<void> {
|
static GetEvents(req: GoogleProtobufEmpty.Empty, entityNotifier?: fm.NotifyStreamEntityArrival<V1Events.Event>, initReq?: fm.InitReq): Promise<void> {
|
||||||
return fm.fetchStreamingRequest<GoogleProtobufEmpty.Empty, V1Events.Event>(`/v1/events?${fm.renderURLSearchParams(req, [])}`, entityNotifier, {...initReq, method: "GET"})
|
return fm.fetchStreamingRequest<GoogleProtobufEmpty.Empty, V1Events.Event>(`/v1/events?${fm.renderURLSearchParams(req, [])}`, entityNotifier, {...initReq, method: "GET"})
|
||||||
}
|
}
|
||||||
|
static ListSnapshots(req: ListSnapshotsRequest, initReq?: fm.InitReq): Promise<V1Restic.ResticSnapshotList> {
|
||||||
|
return fm.fetchReq<ListSnapshotsRequest, V1Restic.ResticSnapshotList>(`/v1/snapshots`, {...initReq, method: "POST", body: JSON.stringify(req, fm.replacer)})
|
||||||
|
}
|
||||||
static PathAutocomplete(req: TypesValue.StringValue, initReq?: fm.InitReq): Promise<TypesValue.StringList> {
|
static PathAutocomplete(req: TypesValue.StringValue, initReq?: fm.InitReq): Promise<TypesValue.StringList> {
|
||||||
return fm.fetchReq<TypesValue.StringValue, TypesValue.StringList>(`/v1/autocomplete/path`, {...initReq, method: "POST", body: JSON.stringify(req, fm.replacer)})
|
return fm.fetchReq<TypesValue.StringValue, TypesValue.StringList>(`/v1/autocomplete/path`, {...initReq, method: "POST", body: JSON.stringify(req, fm.replacer)})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,9 @@ import { StringList } from "../../gen/ts/types/value.pb";
|
|||||||
|
|
||||||
let timeout: NodeJS.Timeout | undefined = undefined;
|
let timeout: NodeJS.Timeout | undefined = undefined;
|
||||||
|
|
||||||
export const URIAutocomplete = (props: React.PropsWithChildren) => {
|
export const URIAutocomplete = (
|
||||||
|
props: React.PropsWithChildren<{ disabled: boolean }>
|
||||||
|
) => {
|
||||||
const [value, setValue] = useState("");
|
const [value, setValue] = useState("");
|
||||||
const [options, setOptions] = useState<{ value: string }[]>([]);
|
const [options, setOptions] = useState<{ value: string }[]>([]);
|
||||||
const [showOptions, setShowOptions] = useState<{ value: string }[]>([]);
|
const [showOptions, setShowOptions] = useState<{ value: string }[]>([]);
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ export const addRepo = async (repo: Repo): Promise<Config> => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
export const setConfig = async (config: Config): Promise<Config> => {
|
export const updateConfig = async (config: Config): Promise<Config> => {
|
||||||
return await ResticUI.SetConfig(config, {
|
return await ResticUI.SetConfig(config, {
|
||||||
pathPrefix: "/api/",
|
pathPrefix: "/api/",
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -14,20 +14,26 @@ import { URIAutocomplete } from "../components/URIAutocomplete";
|
|||||||
import { MinusCircleOutlined, PlusOutlined } from "@ant-design/icons";
|
import { MinusCircleOutlined, PlusOutlined } from "@ant-design/icons";
|
||||||
import { useAlertApi } from "../components/Alerts";
|
import { useAlertApi } from "../components/Alerts";
|
||||||
import { ResticUI } from "../../gen/ts/v1/service.pb";
|
import { ResticUI } from "../../gen/ts/v1/service.pb";
|
||||||
|
import {
|
||||||
|
addRepo,
|
||||||
|
configState,
|
||||||
|
fetchConfig,
|
||||||
|
updateConfig,
|
||||||
|
} from "../state/config";
|
||||||
|
import { useRecoilState, useSetRecoilState } from "recoil";
|
||||||
|
|
||||||
export const AddRepoModel = ({
|
export const AddRepoModel = ({
|
||||||
template,
|
template,
|
||||||
}: {
|
}: {
|
||||||
template: Partial<Repo> | null;
|
template: Partial<Repo> | null;
|
||||||
}) => {
|
}) => {
|
||||||
|
const setConfig = useSetRecoilState(configState);
|
||||||
const [confirmLoading, setConfirmLoading] = useState(false);
|
const [confirmLoading, setConfirmLoading] = useState(false);
|
||||||
const showModal = useShowModal();
|
const showModal = useShowModal();
|
||||||
const alertsApi = useAlertApi()!;
|
const alertsApi = useAlertApi()!;
|
||||||
const [form] = Form.useForm<Repo>();
|
const [form] = Form.useForm<Repo>();
|
||||||
|
|
||||||
template = template || {};
|
const handleOk = async () => {
|
||||||
|
|
||||||
const handleOk = () => {
|
|
||||||
const errors = form
|
const errors = form
|
||||||
.getFieldsError()
|
.getFieldsError()
|
||||||
.map((e) => e.errors)
|
.map((e) => e.errors)
|
||||||
@@ -40,22 +46,43 @@ export const AddRepoModel = ({
|
|||||||
|
|
||||||
const repo = form.getFieldsValue() as Repo;
|
const repo = form.getFieldsValue() as Repo;
|
||||||
|
|
||||||
if (template === null) {
|
if (template !== null) {
|
||||||
|
// We are in the edit repo flow, update the repo in the config
|
||||||
|
try {
|
||||||
|
let config = await fetchConfig();
|
||||||
|
const idx = config.repos!.findIndex((r) => r.id === template!.id);
|
||||||
|
if (idx === -1) {
|
||||||
|
alertsApi.error("Can't update repo, not found");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
config.repos![idx] = { ...repo };
|
||||||
|
setConfig(await updateConfig(config));
|
||||||
|
showModal(null);
|
||||||
|
alertsApi.success("Updated repo " + repo.uri);
|
||||||
|
|
||||||
|
// Update the snapshots for the repo
|
||||||
|
await ResticUI.ListSnapshots(
|
||||||
|
{
|
||||||
|
repoId: repo.id,
|
||||||
|
},
|
||||||
|
{ pathPrefix: "/api" }
|
||||||
|
);
|
||||||
|
} catch (e: any) {
|
||||||
|
alertsApi.error("Error updating repo: " + e.message, 15);
|
||||||
|
} finally {
|
||||||
|
setConfirmLoading(false);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
// We are in the create repo flow, create the new repo via the service
|
// We are in the create repo flow, create the new repo via the service
|
||||||
ResticUI.AddRepo(repo, {
|
try {
|
||||||
pathPrefix: "/api",
|
setConfig(await addRepo(repo));
|
||||||
})
|
|
||||||
.then((res) => {
|
|
||||||
showModal(null);
|
showModal(null);
|
||||||
alertsApi.success("Added repo " + repo.uri);
|
alertsApi.success("Added repo " + repo.uri);
|
||||||
})
|
} catch (e: any) {
|
||||||
.catch((e) => {
|
|
||||||
alertsApi.error("Error adding repo: " + e.message, 15);
|
alertsApi.error("Error adding repo: " + e.message, 15);
|
||||||
})
|
} finally {
|
||||||
.finally(() => {
|
|
||||||
setConfirmLoading(false);
|
setConfirmLoading(false);
|
||||||
});
|
}
|
||||||
} else {
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -67,7 +94,7 @@ export const AddRepoModel = ({
|
|||||||
<>
|
<>
|
||||||
<Modal
|
<Modal
|
||||||
open={true}
|
open={true}
|
||||||
title={template ? "Add Restic Repository" : "Edit Restic Repository"}
|
title={template ? "Edit Restic Repository" : "Add Restic Repository"}
|
||||||
onOk={handleOk}
|
onOk={handleOk}
|
||||||
confirmLoading={confirmLoading}
|
confirmLoading={confirmLoading}
|
||||||
onCancel={handleCancel}
|
onCancel={handleCancel}
|
||||||
@@ -78,7 +105,7 @@ export const AddRepoModel = ({
|
|||||||
hasFeedback
|
hasFeedback
|
||||||
name="id"
|
name="id"
|
||||||
label="Repo Name"
|
label="Repo Name"
|
||||||
initialValue={template.id}
|
initialValue={template && template.id}
|
||||||
validateTrigger={["onChange", "onBlur"]}
|
validateTrigger={["onChange", "onBlur"]}
|
||||||
rules={[
|
rules={[
|
||||||
{
|
{
|
||||||
@@ -91,7 +118,7 @@ export const AddRepoModel = ({
|
|||||||
},
|
},
|
||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
<Input />
|
<Input disabled={!!template} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
|
||||||
{/* Repo.uri */}
|
{/* Repo.uri */}
|
||||||
@@ -118,8 +145,8 @@ export const AddRepoModel = ({
|
|||||||
<Form.Item<Repo>
|
<Form.Item<Repo>
|
||||||
hasFeedback
|
hasFeedback
|
||||||
name="uri"
|
name="uri"
|
||||||
label="Repo URI"
|
label="Repository URI (e.g. ./local-path or s3://bucket-name/path)"
|
||||||
initialValue={template.id}
|
initialValue={template && template.uri}
|
||||||
validateTrigger={["onChange", "onBlur"]}
|
validateTrigger={["onChange", "onBlur"]}
|
||||||
rules={[
|
rules={[
|
||||||
{
|
{
|
||||||
@@ -128,7 +155,7 @@ export const AddRepoModel = ({
|
|||||||
},
|
},
|
||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
<Input />
|
<URIAutocomplete disabled={!!template} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
|
|
||||||
@@ -137,7 +164,7 @@ export const AddRepoModel = ({
|
|||||||
hasFeedback
|
hasFeedback
|
||||||
name="password"
|
name="password"
|
||||||
label="Password"
|
label="Password"
|
||||||
initialValue={template.password}
|
initialValue={template && template.password}
|
||||||
validateTrigger={["onChange", "onBlur"]}
|
validateTrigger={["onChange", "onBlur"]}
|
||||||
rules={[
|
rules={[
|
||||||
{
|
{
|
||||||
@@ -150,7 +177,7 @@ export const AddRepoModel = ({
|
|||||||
},
|
},
|
||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
<Input />
|
<Input disabled={!!template} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
|
||||||
{/* Repo.env */}
|
{/* Repo.env */}
|
||||||
@@ -164,7 +191,7 @@ export const AddRepoModel = ({
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
]}
|
]}
|
||||||
initialValue={[]}
|
initialValue={(template && template.env) || undefined}
|
||||||
>
|
>
|
||||||
{(fields, { add, remove }, { errors }) => (
|
{(fields, { add, remove }, { errors }) => (
|
||||||
<>
|
<>
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import { configState, fetchConfig } from "../state/config";
|
|||||||
import { useRecoilState } from "recoil";
|
import { useRecoilState } from "recoil";
|
||||||
import { Config } from "../../gen/ts/v1/config.pb";
|
import { Config } from "../../gen/ts/v1/config.pb";
|
||||||
import { AlertContextProvider, useAlertApi } from "../components/Alerts";
|
import { AlertContextProvider, useAlertApi } from "../components/Alerts";
|
||||||
import { useShowModal, useShowSpinner } from "../components/ModalManager";
|
import { useShowModal } from "../components/ModalManager";
|
||||||
import { AddPlanModal } from "./AddPlanModel";
|
import { AddPlanModal } from "./AddPlanModel";
|
||||||
import { AddRepoModel } from "./AddRepoModel";
|
import { AddRepoModel } from "./AddRepoModel";
|
||||||
|
|
||||||
@@ -41,6 +41,7 @@ export const App: React.FC = () => {
|
|||||||
});
|
});
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
console.log("rerender config ", config);
|
||||||
const items = getSidenavItems(config);
|
const items = getSidenavItems(config);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -2,8 +2,7 @@ package static
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"embed"
|
"embed"
|
||||||
_ "embed"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
//go:embed *
|
//go:embed dist/*.js dist/*.css dist/*.html
|
||||||
var FS embed.FS
|
var FS embed.FS
|
||||||
Reference in New Issue
Block a user