diff --git a/client/proto/daemon.pb.go b/client/proto/daemon.pb.go index 402dd2f9a..6ae6479d8 100644 --- a/client/proto/daemon.pb.go +++ b/client/proto/daemon.pb.go @@ -3559,6 +3559,147 @@ func (x *GetEventsResponse) GetEvents() []*SystemEvent { return nil } +// Profiles +type Profile struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + Selected bool `protobuf:"varint,2,opt,name=selected,proto3" json:"selected,omitempty"` +} + +func (x *Profile) Reset() { + *x = Profile{} + if protoimpl.UnsafeEnabled { + mi := &file_daemon_proto_msgTypes[52] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Profile) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Profile) ProtoMessage() {} + +func (x *Profile) ProtoReflect() protoreflect.Message { + mi := &file_daemon_proto_msgTypes[52] + 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 Profile.ProtoReflect.Descriptor instead. +func (*Profile) Descriptor() ([]byte, []int) { + return file_daemon_proto_rawDescGZIP(), []int{52} +} + +func (x *Profile) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *Profile) GetSelected() bool { + if x != nil { + return x.Selected + } + return false +} + +type GetProfilesRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *GetProfilesRequest) Reset() { + *x = GetProfilesRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_daemon_proto_msgTypes[53] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetProfilesRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetProfilesRequest) ProtoMessage() {} + +func (x *GetProfilesRequest) ProtoReflect() protoreflect.Message { + mi := &file_daemon_proto_msgTypes[53] + 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 GetProfilesRequest.ProtoReflect.Descriptor instead. +func (*GetProfilesRequest) Descriptor() ([]byte, []int) { + return file_daemon_proto_rawDescGZIP(), []int{53} +} + +type GetProfilesResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Profiles []*Profile `protobuf:"bytes,1,rep,name=profiles,proto3" json:"profiles,omitempty"` +} + +func (x *GetProfilesResponse) Reset() { + *x = GetProfilesResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_daemon_proto_msgTypes[54] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetProfilesResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetProfilesResponse) ProtoMessage() {} + +func (x *GetProfilesResponse) ProtoReflect() protoreflect.Message { + mi := &file_daemon_proto_msgTypes[54] + 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 GetProfilesResponse.ProtoReflect.Descriptor instead. +func (*GetProfilesResponse) Descriptor() ([]byte, []int) { + return file_daemon_proto_rawDescGZIP(), []int{54} +} + +func (x *GetProfilesResponse) GetProfiles() []*Profile { + if x != nil { + return x.Profiles + } + return nil +} + type PortInfo_Range struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -3571,7 +3712,7 @@ type PortInfo_Range struct { func (x *PortInfo_Range) Reset() { *x = PortInfo_Range{} if protoimpl.UnsafeEnabled { - mi := &file_daemon_proto_msgTypes[53] + mi := &file_daemon_proto_msgTypes[56] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3584,7 +3725,7 @@ func (x *PortInfo_Range) String() string { func (*PortInfo_Range) ProtoMessage() {} func (x *PortInfo_Range) ProtoReflect() protoreflect.Message { - mi := &file_daemon_proto_msgTypes[53] + mi := &file_daemon_proto_msgTypes[56] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4118,105 +4259,119 @@ var file_daemon_proto_rawDesc = []byte{ 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2b, 0x0a, 0x06, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x06, 0x65, 0x76, - 0x65, 0x6e, 0x74, 0x73, 0x2a, 0x62, 0x0a, 0x08, 0x4c, 0x6f, 0x67, 0x4c, 0x65, 0x76, 0x65, 0x6c, - 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x09, 0x0a, - 0x05, 0x50, 0x41, 0x4e, 0x49, 0x43, 0x10, 0x01, 0x12, 0x09, 0x0a, 0x05, 0x46, 0x41, 0x54, 0x41, - 0x4c, 0x10, 0x02, 0x12, 0x09, 0x0a, 0x05, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x03, 0x12, 0x08, - 0x0a, 0x04, 0x57, 0x41, 0x52, 0x4e, 0x10, 0x04, 0x12, 0x08, 0x0a, 0x04, 0x49, 0x4e, 0x46, 0x4f, - 0x10, 0x05, 0x12, 0x09, 0x0a, 0x05, 0x44, 0x45, 0x42, 0x55, 0x47, 0x10, 0x06, 0x12, 0x09, 0x0a, - 0x05, 0x54, 0x52, 0x41, 0x43, 0x45, 0x10, 0x07, 0x32, 0xb3, 0x0b, 0x0a, 0x0d, 0x44, 0x61, 0x65, - 0x6d, 0x6f, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x36, 0x0a, 0x05, 0x4c, 0x6f, - 0x67, 0x69, 0x6e, 0x12, 0x14, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x4c, 0x6f, 0x67, - 0x69, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x15, 0x2e, 0x64, 0x61, 0x65, 0x6d, - 0x6f, 0x6e, 0x2e, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x22, 0x00, 0x12, 0x4b, 0x0a, 0x0c, 0x57, 0x61, 0x69, 0x74, 0x53, 0x53, 0x4f, 0x4c, 0x6f, 0x67, - 0x69, 0x6e, 0x12, 0x1b, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x57, 0x61, 0x69, 0x74, - 0x53, 0x53, 0x4f, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x1c, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x57, 0x61, 0x69, 0x74, 0x53, 0x53, 0x4f, - 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, - 0x2d, 0x0a, 0x02, 0x55, 0x70, 0x12, 0x11, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x55, - 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x12, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, - 0x6e, 0x2e, 0x55, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x39, - 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x15, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, - 0x6e, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x16, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x33, 0x0a, 0x04, 0x44, 0x6f, 0x77, - 0x6e, 0x12, 0x13, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x44, 0x6f, 0x77, 0x6e, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, - 0x44, 0x6f, 0x77, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x42, - 0x0a, 0x09, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x18, 0x2e, 0x64, 0x61, - 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x47, - 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x22, 0x00, 0x12, 0x4b, 0x0a, 0x0c, 0x4c, 0x69, 0x73, 0x74, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, - 0x6b, 0x73, 0x12, 0x1b, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x4c, 0x69, 0x73, 0x74, - 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x1c, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4e, 0x65, 0x74, - 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, - 0x51, 0x0a, 0x0e, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, - 0x73, 0x12, 0x1d, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x53, 0x65, 0x6c, 0x65, 0x63, - 0x74, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x1e, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, - 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x22, 0x00, 0x12, 0x53, 0x0a, 0x10, 0x44, 0x65, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x4e, 0x65, + 0x65, 0x6e, 0x74, 0x73, 0x22, 0x39, 0x0a, 0x07, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x12, + 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, + 0x61, 0x6d, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x65, 0x64, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x65, 0x64, 0x22, + 0x14, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x42, 0x0a, 0x13, 0x47, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x66, + 0x69, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2b, 0x0a, 0x08, + 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0f, + 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x52, + 0x08, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x2a, 0x62, 0x0a, 0x08, 0x4c, 0x6f, 0x67, + 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, + 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x50, 0x41, 0x4e, 0x49, 0x43, 0x10, 0x01, 0x12, 0x09, 0x0a, + 0x05, 0x46, 0x41, 0x54, 0x41, 0x4c, 0x10, 0x02, 0x12, 0x09, 0x0a, 0x05, 0x45, 0x52, 0x52, 0x4f, + 0x52, 0x10, 0x03, 0x12, 0x08, 0x0a, 0x04, 0x57, 0x41, 0x52, 0x4e, 0x10, 0x04, 0x12, 0x08, 0x0a, + 0x04, 0x49, 0x4e, 0x46, 0x4f, 0x10, 0x05, 0x12, 0x09, 0x0a, 0x05, 0x44, 0x45, 0x42, 0x55, 0x47, + 0x10, 0x06, 0x12, 0x09, 0x0a, 0x05, 0x54, 0x52, 0x41, 0x43, 0x45, 0x10, 0x07, 0x32, 0xfd, 0x0b, + 0x0a, 0x0d, 0x44, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, + 0x36, 0x0a, 0x05, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x12, 0x14, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, + 0x6e, 0x2e, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x15, + 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x4b, 0x0a, 0x0c, 0x57, 0x61, 0x69, 0x74, 0x53, + 0x53, 0x4f, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x12, 0x1b, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, + 0x2e, 0x57, 0x61, 0x69, 0x74, 0x53, 0x53, 0x4f, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x57, 0x61, + 0x69, 0x74, 0x53, 0x53, 0x4f, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x00, 0x12, 0x2d, 0x0a, 0x02, 0x55, 0x70, 0x12, 0x11, 0x2e, 0x64, 0x61, 0x65, + 0x6d, 0x6f, 0x6e, 0x2e, 0x55, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x12, 0x2e, + 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x55, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x22, 0x00, 0x12, 0x39, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x15, 0x2e, + 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x53, 0x74, + 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x33, + 0x0a, 0x04, 0x44, 0x6f, 0x77, 0x6e, 0x12, 0x13, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, + 0x44, 0x6f, 0x77, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x64, 0x61, + 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x44, 0x6f, 0x77, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x22, 0x00, 0x12, 0x42, 0x0a, 0x09, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x12, 0x18, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x64, 0x61, 0x65, + 0x6d, 0x6f, 0x6e, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x4b, 0x0a, 0x0c, 0x4c, 0x69, 0x73, 0x74, 0x4e, + 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x12, 0x1b, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, + 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x4c, 0x69, + 0x73, 0x74, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x00, 0x12, 0x51, 0x0a, 0x0e, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x12, 0x1d, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x4a, 0x0a, 0x0f, 0x46, 0x6f, 0x72, 0x77, 0x61, - 0x72, 0x64, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x12, 0x14, 0x2e, 0x64, 0x61, 0x65, - 0x6d, 0x6f, 0x6e, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x1f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x46, 0x6f, 0x72, 0x77, 0x61, 0x72, - 0x64, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x22, 0x00, 0x12, 0x48, 0x0a, 0x0b, 0x44, 0x65, 0x62, 0x75, 0x67, 0x42, 0x75, 0x6e, 0x64, - 0x6c, 0x65, 0x12, 0x1a, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x44, 0x65, 0x62, 0x75, - 0x67, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, - 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x44, 0x65, 0x62, 0x75, 0x67, 0x42, 0x75, 0x6e, - 0x64, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x48, 0x0a, - 0x0b, 0x47, 0x65, 0x74, 0x4c, 0x6f, 0x67, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x1a, 0x2e, 0x64, - 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x47, 0x65, 0x74, 0x4c, 0x6f, 0x67, 0x4c, 0x65, 0x76, 0x65, - 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, - 0x6e, 0x2e, 0x47, 0x65, 0x74, 0x4c, 0x6f, 0x67, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x48, 0x0a, 0x0b, 0x53, 0x65, 0x74, 0x4c, 0x6f, - 0x67, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x1a, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, - 0x53, 0x65, 0x74, 0x4c, 0x6f, 0x67, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x53, 0x65, 0x74, 0x4c, - 0x6f, 0x67, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, - 0x00, 0x12, 0x45, 0x0a, 0x0a, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x73, 0x12, - 0x19, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x74, 0x61, - 0x74, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x64, 0x61, 0x65, - 0x6d, 0x6f, 0x6e, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x73, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x45, 0x0a, 0x0a, 0x43, 0x6c, 0x65, 0x61, - 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x19, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, - 0x43, 0x6c, 0x65, 0x61, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x1a, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x43, 0x6c, 0x65, 0x61, 0x6e, - 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, - 0x48, 0x0a, 0x0b, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x1a, - 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x53, 0x74, - 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x64, 0x61, 0x65, - 0x6d, 0x6f, 0x6e, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x6f, 0x0a, 0x18, 0x53, 0x65, 0x74, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x53, 0x0a, 0x10, 0x44, 0x65, 0x73, 0x65, 0x6c, + 0x65, 0x63, 0x74, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x12, 0x1d, 0x2e, 0x64, 0x61, + 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x4e, 0x65, 0x74, 0x77, 0x6f, + 0x72, 0x6b, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x64, 0x61, 0x65, + 0x6d, 0x6f, 0x6e, 0x2e, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, + 0x6b, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x4a, 0x0a, 0x0f, + 0x46, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x12, + 0x14, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x46, + 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x48, 0x0a, 0x0b, 0x44, 0x65, 0x62, 0x75, + 0x67, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x12, 0x1a, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, + 0x2e, 0x44, 0x65, 0x62, 0x75, 0x67, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x44, 0x65, 0x62, + 0x75, 0x67, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0x00, 0x12, 0x48, 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x4c, 0x6f, 0x67, 0x4c, 0x65, 0x76, 0x65, + 0x6c, 0x12, 0x1a, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x47, 0x65, 0x74, 0x4c, 0x6f, + 0x67, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, + 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x47, 0x65, 0x74, 0x4c, 0x6f, 0x67, 0x4c, 0x65, 0x76, + 0x65, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x48, 0x0a, 0x0b, + 0x53, 0x65, 0x74, 0x4c, 0x6f, 0x67, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x1a, 0x2e, 0x64, 0x61, + 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x53, 0x65, 0x74, 0x4c, 0x6f, 0x67, 0x4c, 0x65, 0x76, 0x65, 0x6c, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, + 0x2e, 0x53, 0x65, 0x74, 0x4c, 0x6f, 0x67, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x45, 0x0a, 0x0a, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x74, + 0x61, 0x74, 0x65, 0x73, 0x12, 0x19, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x4c, 0x69, + 0x73, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x1a, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x74, 0x61, + 0x74, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x45, 0x0a, + 0x0a, 0x43, 0x6c, 0x65, 0x61, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x19, 0x2e, 0x64, 0x61, + 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x43, 0x6c, 0x65, 0x61, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, + 0x43, 0x6c, 0x65, 0x61, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x00, 0x12, 0x48, 0x0a, 0x0b, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x53, 0x74, + 0x61, 0x74, 0x65, 0x12, 0x1a, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x44, 0x65, 0x6c, + 0x65, 0x74, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x1b, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x53, + 0x74, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x6f, + 0x0a, 0x18, 0x53, 0x65, 0x74, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x4d, 0x61, 0x70, 0x50, + 0x65, 0x72, 0x73, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x63, 0x65, 0x12, 0x27, 0x2e, 0x64, 0x61, 0x65, + 0x6d, 0x6f, 0x6e, 0x2e, 0x53, 0x65, 0x74, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x4d, 0x61, + 0x70, 0x50, 0x65, 0x72, 0x73, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x53, 0x65, 0x74, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x4d, 0x61, 0x70, 0x50, 0x65, 0x72, 0x73, 0x69, 0x73, - 0x74, 0x65, 0x6e, 0x63, 0x65, 0x12, 0x27, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x53, - 0x65, 0x74, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x4d, 0x61, 0x70, 0x50, 0x65, 0x72, 0x73, - 0x69, 0x73, 0x74, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, - 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x53, 0x65, 0x74, 0x4e, 0x65, 0x74, 0x77, 0x6f, - 0x72, 0x6b, 0x4d, 0x61, 0x70, 0x50, 0x65, 0x72, 0x73, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x63, 0x65, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x48, 0x0a, 0x0b, 0x54, 0x72, - 0x61, 0x63, 0x65, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x12, 0x1a, 0x2e, 0x64, 0x61, 0x65, 0x6d, - 0x6f, 0x6e, 0x2e, 0x54, 0x72, 0x61, 0x63, 0x65, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x54, - 0x72, 0x61, 0x63, 0x65, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0x00, 0x12, 0x44, 0x0a, 0x0f, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, - 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x18, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, - 0x2e, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x13, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x53, 0x79, 0x73, 0x74, 0x65, - 0x6d, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x22, 0x00, 0x30, 0x01, 0x12, 0x42, 0x0a, 0x09, 0x47, 0x65, - 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x18, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, - 0x2e, 0x47, 0x65, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x19, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x47, 0x65, 0x74, 0x45, 0x76, - 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x08, - 0x5a, 0x06, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x74, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, + 0x48, 0x0a, 0x0b, 0x54, 0x72, 0x61, 0x63, 0x65, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x12, 0x1a, + 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x54, 0x72, 0x61, 0x63, 0x65, 0x50, 0x61, 0x63, + 0x6b, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x64, 0x61, 0x65, + 0x6d, 0x6f, 0x6e, 0x2e, 0x54, 0x72, 0x61, 0x63, 0x65, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x44, 0x0a, 0x0f, 0x53, 0x75, 0x62, + 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x18, 0x2e, 0x64, + 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, + 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x22, 0x00, 0x30, 0x01, 0x12, + 0x42, 0x0a, 0x09, 0x47, 0x65, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x18, 0x2e, 0x64, + 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x47, 0x65, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, + 0x47, 0x65, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x22, 0x00, 0x12, 0x48, 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, + 0x65, 0x73, 0x12, 0x1a, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x47, 0x65, 0x74, 0x50, + 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, + 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x66, 0x69, + 0x6c, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x08, 0x5a, + 0x06, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -4232,7 +4387,7 @@ func file_daemon_proto_rawDescGZIP() []byte { } var file_daemon_proto_enumTypes = make([]protoimpl.EnumInfo, 3) -var file_daemon_proto_msgTypes = make([]protoimpl.MessageInfo, 55) +var file_daemon_proto_msgTypes = make([]protoimpl.MessageInfo, 58) var file_daemon_proto_goTypes = []interface{}{ (LogLevel)(0), // 0: daemon.LogLevel (SystemEvent_Severity)(0), // 1: daemon.SystemEvent.Severity @@ -4289,18 +4444,21 @@ var file_daemon_proto_goTypes = []interface{}{ (*SystemEvent)(nil), // 52: daemon.SystemEvent (*GetEventsRequest)(nil), // 53: daemon.GetEventsRequest (*GetEventsResponse)(nil), // 54: daemon.GetEventsResponse - nil, // 55: daemon.Network.ResolvedIPsEntry - (*PortInfo_Range)(nil), // 56: daemon.PortInfo.Range - nil, // 57: daemon.SystemEvent.MetadataEntry - (*durationpb.Duration)(nil), // 58: google.protobuf.Duration - (*timestamppb.Timestamp)(nil), // 59: google.protobuf.Timestamp + (*Profile)(nil), // 55: daemon.Profile + (*GetProfilesRequest)(nil), // 56: daemon.GetProfilesRequest + (*GetProfilesResponse)(nil), // 57: daemon.GetProfilesResponse + nil, // 58: daemon.Network.ResolvedIPsEntry + (*PortInfo_Range)(nil), // 59: daemon.PortInfo.Range + nil, // 60: daemon.SystemEvent.MetadataEntry + (*durationpb.Duration)(nil), // 61: google.protobuf.Duration + (*timestamppb.Timestamp)(nil), // 62: google.protobuf.Timestamp } var file_daemon_proto_depIdxs = []int32{ - 58, // 0: daemon.LoginRequest.dnsRouteInterval:type_name -> google.protobuf.Duration + 61, // 0: daemon.LoginRequest.dnsRouteInterval:type_name -> google.protobuf.Duration 22, // 1: daemon.StatusResponse.fullStatus:type_name -> daemon.FullStatus - 59, // 2: daemon.PeerState.connStatusUpdate:type_name -> google.protobuf.Timestamp - 59, // 3: daemon.PeerState.lastWireguardHandshake:type_name -> google.protobuf.Timestamp - 58, // 4: daemon.PeerState.latency:type_name -> google.protobuf.Duration + 62, // 2: daemon.PeerState.connStatusUpdate:type_name -> google.protobuf.Timestamp + 62, // 3: daemon.PeerState.lastWireguardHandshake:type_name -> google.protobuf.Timestamp + 61, // 4: daemon.PeerState.latency:type_name -> google.protobuf.Duration 19, // 5: daemon.FullStatus.managementState:type_name -> daemon.ManagementState 18, // 6: daemon.FullStatus.signalState:type_name -> daemon.SignalState 17, // 7: daemon.FullStatus.localPeerState:type_name -> daemon.LocalPeerState @@ -4309,8 +4467,8 @@ var file_daemon_proto_depIdxs = []int32{ 21, // 10: daemon.FullStatus.dns_servers:type_name -> daemon.NSGroupState 52, // 11: daemon.FullStatus.events:type_name -> daemon.SystemEvent 28, // 12: daemon.ListNetworksResponse.routes:type_name -> daemon.Network - 55, // 13: daemon.Network.resolvedIPs:type_name -> daemon.Network.ResolvedIPsEntry - 56, // 14: daemon.PortInfo.range:type_name -> daemon.PortInfo.Range + 58, // 13: daemon.Network.resolvedIPs:type_name -> daemon.Network.ResolvedIPsEntry + 59, // 14: daemon.PortInfo.range:type_name -> daemon.PortInfo.Range 29, // 15: daemon.ForwardingRule.destinationPort:type_name -> daemon.PortInfo 29, // 16: daemon.ForwardingRule.translatedPort:type_name -> daemon.PortInfo 30, // 17: daemon.ForwardingRulesResponse.rules:type_name -> daemon.ForwardingRule @@ -4321,55 +4479,58 @@ var file_daemon_proto_depIdxs = []int32{ 49, // 22: daemon.TracePacketResponse.stages:type_name -> daemon.TraceStage 1, // 23: daemon.SystemEvent.severity:type_name -> daemon.SystemEvent.Severity 2, // 24: daemon.SystemEvent.category:type_name -> daemon.SystemEvent.Category - 59, // 25: daemon.SystemEvent.timestamp:type_name -> google.protobuf.Timestamp - 57, // 26: daemon.SystemEvent.metadata:type_name -> daemon.SystemEvent.MetadataEntry + 62, // 25: daemon.SystemEvent.timestamp:type_name -> google.protobuf.Timestamp + 60, // 26: daemon.SystemEvent.metadata:type_name -> daemon.SystemEvent.MetadataEntry 52, // 27: daemon.GetEventsResponse.events:type_name -> daemon.SystemEvent - 27, // 28: daemon.Network.ResolvedIPsEntry.value:type_name -> daemon.IPList - 4, // 29: daemon.DaemonService.Login:input_type -> daemon.LoginRequest - 6, // 30: daemon.DaemonService.WaitSSOLogin:input_type -> daemon.WaitSSOLoginRequest - 8, // 31: daemon.DaemonService.Up:input_type -> daemon.UpRequest - 10, // 32: daemon.DaemonService.Status:input_type -> daemon.StatusRequest - 12, // 33: daemon.DaemonService.Down:input_type -> daemon.DownRequest - 14, // 34: daemon.DaemonService.GetConfig:input_type -> daemon.GetConfigRequest - 23, // 35: daemon.DaemonService.ListNetworks:input_type -> daemon.ListNetworksRequest - 25, // 36: daemon.DaemonService.SelectNetworks:input_type -> daemon.SelectNetworksRequest - 25, // 37: daemon.DaemonService.DeselectNetworks:input_type -> daemon.SelectNetworksRequest - 3, // 38: daemon.DaemonService.ForwardingRules:input_type -> daemon.EmptyRequest - 32, // 39: daemon.DaemonService.DebugBundle:input_type -> daemon.DebugBundleRequest - 34, // 40: daemon.DaemonService.GetLogLevel:input_type -> daemon.GetLogLevelRequest - 36, // 41: daemon.DaemonService.SetLogLevel:input_type -> daemon.SetLogLevelRequest - 39, // 42: daemon.DaemonService.ListStates:input_type -> daemon.ListStatesRequest - 41, // 43: daemon.DaemonService.CleanState:input_type -> daemon.CleanStateRequest - 43, // 44: daemon.DaemonService.DeleteState:input_type -> daemon.DeleteStateRequest - 45, // 45: daemon.DaemonService.SetNetworkMapPersistence:input_type -> daemon.SetNetworkMapPersistenceRequest - 48, // 46: daemon.DaemonService.TracePacket:input_type -> daemon.TracePacketRequest - 51, // 47: daemon.DaemonService.SubscribeEvents:input_type -> daemon.SubscribeRequest - 53, // 48: daemon.DaemonService.GetEvents:input_type -> daemon.GetEventsRequest - 5, // 49: daemon.DaemonService.Login:output_type -> daemon.LoginResponse - 7, // 50: daemon.DaemonService.WaitSSOLogin:output_type -> daemon.WaitSSOLoginResponse - 9, // 51: daemon.DaemonService.Up:output_type -> daemon.UpResponse - 11, // 52: daemon.DaemonService.Status:output_type -> daemon.StatusResponse - 13, // 53: daemon.DaemonService.Down:output_type -> daemon.DownResponse - 15, // 54: daemon.DaemonService.GetConfig:output_type -> daemon.GetConfigResponse - 24, // 55: daemon.DaemonService.ListNetworks:output_type -> daemon.ListNetworksResponse - 26, // 56: daemon.DaemonService.SelectNetworks:output_type -> daemon.SelectNetworksResponse - 26, // 57: daemon.DaemonService.DeselectNetworks:output_type -> daemon.SelectNetworksResponse - 31, // 58: daemon.DaemonService.ForwardingRules:output_type -> daemon.ForwardingRulesResponse - 33, // 59: daemon.DaemonService.DebugBundle:output_type -> daemon.DebugBundleResponse - 35, // 60: daemon.DaemonService.GetLogLevel:output_type -> daemon.GetLogLevelResponse - 37, // 61: daemon.DaemonService.SetLogLevel:output_type -> daemon.SetLogLevelResponse - 40, // 62: daemon.DaemonService.ListStates:output_type -> daemon.ListStatesResponse - 42, // 63: daemon.DaemonService.CleanState:output_type -> daemon.CleanStateResponse - 44, // 64: daemon.DaemonService.DeleteState:output_type -> daemon.DeleteStateResponse - 46, // 65: daemon.DaemonService.SetNetworkMapPersistence:output_type -> daemon.SetNetworkMapPersistenceResponse - 50, // 66: daemon.DaemonService.TracePacket:output_type -> daemon.TracePacketResponse - 52, // 67: daemon.DaemonService.SubscribeEvents:output_type -> daemon.SystemEvent - 54, // 68: daemon.DaemonService.GetEvents:output_type -> daemon.GetEventsResponse - 49, // [49:69] is the sub-list for method output_type - 29, // [29:49] is the sub-list for method input_type - 29, // [29:29] is the sub-list for extension type_name - 29, // [29:29] is the sub-list for extension extendee - 0, // [0:29] is the sub-list for field type_name + 55, // 28: daemon.GetProfilesResponse.profiles:type_name -> daemon.Profile + 27, // 29: daemon.Network.ResolvedIPsEntry.value:type_name -> daemon.IPList + 4, // 30: daemon.DaemonService.Login:input_type -> daemon.LoginRequest + 6, // 31: daemon.DaemonService.WaitSSOLogin:input_type -> daemon.WaitSSOLoginRequest + 8, // 32: daemon.DaemonService.Up:input_type -> daemon.UpRequest + 10, // 33: daemon.DaemonService.Status:input_type -> daemon.StatusRequest + 12, // 34: daemon.DaemonService.Down:input_type -> daemon.DownRequest + 14, // 35: daemon.DaemonService.GetConfig:input_type -> daemon.GetConfigRequest + 23, // 36: daemon.DaemonService.ListNetworks:input_type -> daemon.ListNetworksRequest + 25, // 37: daemon.DaemonService.SelectNetworks:input_type -> daemon.SelectNetworksRequest + 25, // 38: daemon.DaemonService.DeselectNetworks:input_type -> daemon.SelectNetworksRequest + 3, // 39: daemon.DaemonService.ForwardingRules:input_type -> daemon.EmptyRequest + 32, // 40: daemon.DaemonService.DebugBundle:input_type -> daemon.DebugBundleRequest + 34, // 41: daemon.DaemonService.GetLogLevel:input_type -> daemon.GetLogLevelRequest + 36, // 42: daemon.DaemonService.SetLogLevel:input_type -> daemon.SetLogLevelRequest + 39, // 43: daemon.DaemonService.ListStates:input_type -> daemon.ListStatesRequest + 41, // 44: daemon.DaemonService.CleanState:input_type -> daemon.CleanStateRequest + 43, // 45: daemon.DaemonService.DeleteState:input_type -> daemon.DeleteStateRequest + 45, // 46: daemon.DaemonService.SetNetworkMapPersistence:input_type -> daemon.SetNetworkMapPersistenceRequest + 48, // 47: daemon.DaemonService.TracePacket:input_type -> daemon.TracePacketRequest + 51, // 48: daemon.DaemonService.SubscribeEvents:input_type -> daemon.SubscribeRequest + 53, // 49: daemon.DaemonService.GetEvents:input_type -> daemon.GetEventsRequest + 56, // 50: daemon.DaemonService.GetProfiles:input_type -> daemon.GetProfilesRequest + 5, // 51: daemon.DaemonService.Login:output_type -> daemon.LoginResponse + 7, // 52: daemon.DaemonService.WaitSSOLogin:output_type -> daemon.WaitSSOLoginResponse + 9, // 53: daemon.DaemonService.Up:output_type -> daemon.UpResponse + 11, // 54: daemon.DaemonService.Status:output_type -> daemon.StatusResponse + 13, // 55: daemon.DaemonService.Down:output_type -> daemon.DownResponse + 15, // 56: daemon.DaemonService.GetConfig:output_type -> daemon.GetConfigResponse + 24, // 57: daemon.DaemonService.ListNetworks:output_type -> daemon.ListNetworksResponse + 26, // 58: daemon.DaemonService.SelectNetworks:output_type -> daemon.SelectNetworksResponse + 26, // 59: daemon.DaemonService.DeselectNetworks:output_type -> daemon.SelectNetworksResponse + 31, // 60: daemon.DaemonService.ForwardingRules:output_type -> daemon.ForwardingRulesResponse + 33, // 61: daemon.DaemonService.DebugBundle:output_type -> daemon.DebugBundleResponse + 35, // 62: daemon.DaemonService.GetLogLevel:output_type -> daemon.GetLogLevelResponse + 37, // 63: daemon.DaemonService.SetLogLevel:output_type -> daemon.SetLogLevelResponse + 40, // 64: daemon.DaemonService.ListStates:output_type -> daemon.ListStatesResponse + 42, // 65: daemon.DaemonService.CleanState:output_type -> daemon.CleanStateResponse + 44, // 66: daemon.DaemonService.DeleteState:output_type -> daemon.DeleteStateResponse + 46, // 67: daemon.DaemonService.SetNetworkMapPersistence:output_type -> daemon.SetNetworkMapPersistenceResponse + 50, // 68: daemon.DaemonService.TracePacket:output_type -> daemon.TracePacketResponse + 52, // 69: daemon.DaemonService.SubscribeEvents:output_type -> daemon.SystemEvent + 54, // 70: daemon.DaemonService.GetEvents:output_type -> daemon.GetEventsResponse + 57, // 71: daemon.DaemonService.GetProfiles:output_type -> daemon.GetProfilesResponse + 51, // [51:72] is the sub-list for method output_type + 30, // [30:51] is the sub-list for method input_type + 30, // [30:30] is the sub-list for extension type_name + 30, // [30:30] is the sub-list for extension extendee + 0, // [0:30] is the sub-list for field type_name } func init() { file_daemon_proto_init() } @@ -5002,7 +5163,43 @@ func file_daemon_proto_init() { return nil } } + file_daemon_proto_msgTypes[52].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Profile); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } file_daemon_proto_msgTypes[53].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetProfilesRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_daemon_proto_msgTypes[54].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetProfilesResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_daemon_proto_msgTypes[56].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*PortInfo_Range); i { case 0: return &v.state @@ -5028,7 +5225,7 @@ func file_daemon_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_daemon_proto_rawDesc, NumEnums: 3, - NumMessages: 55, + NumMessages: 58, NumExtensions: 0, NumServices: 1, }, diff --git a/client/proto/daemon.proto b/client/proto/daemon.proto index 6fa391c8e..7d9766275 100644 --- a/client/proto/daemon.proto +++ b/client/proto/daemon.proto @@ -67,6 +67,9 @@ service DaemonService { rpc SubscribeEvents(SubscribeRequest) returns (stream SystemEvent) {} rpc GetEvents(GetEventsRequest) returns (GetEventsResponse) {} + + // List available networks + rpc GetProfiles(GetProfilesRequest) returns (GetProfilesResponse) {} } @@ -480,3 +483,18 @@ message GetEventsRequest {} message GetEventsResponse { repeated SystemEvent events = 1; } + + +// Profiles +message Profile { + string name = 1; + bool selected = 2; + +} + +message GetProfilesRequest { +} + +message GetProfilesResponse { + repeated Profile profiles = 1; +} \ No newline at end of file diff --git a/client/proto/daemon_grpc.pb.go b/client/proto/daemon_grpc.pb.go index 6251f7c52..9ad7f11b9 100644 --- a/client/proto/daemon_grpc.pb.go +++ b/client/proto/daemon_grpc.pb.go @@ -55,6 +55,8 @@ type DaemonServiceClient interface { TracePacket(ctx context.Context, in *TracePacketRequest, opts ...grpc.CallOption) (*TracePacketResponse, error) SubscribeEvents(ctx context.Context, in *SubscribeRequest, opts ...grpc.CallOption) (DaemonService_SubscribeEventsClient, error) GetEvents(ctx context.Context, in *GetEventsRequest, opts ...grpc.CallOption) (*GetEventsResponse, error) + // List available networks + GetProfiles(ctx context.Context, in *GetProfilesRequest, opts ...grpc.CallOption) (*GetProfilesResponse, error) } type daemonServiceClient struct { @@ -268,6 +270,15 @@ func (c *daemonServiceClient) GetEvents(ctx context.Context, in *GetEventsReques return out, nil } +func (c *daemonServiceClient) GetProfiles(ctx context.Context, in *GetProfilesRequest, opts ...grpc.CallOption) (*GetProfilesResponse, error) { + out := new(GetProfilesResponse) + err := c.cc.Invoke(ctx, "/daemon.DaemonService/GetProfiles", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // DaemonServiceServer is the server API for DaemonService service. // All implementations must embed UnimplementedDaemonServiceServer // for forward compatibility @@ -309,6 +320,8 @@ type DaemonServiceServer interface { TracePacket(context.Context, *TracePacketRequest) (*TracePacketResponse, error) SubscribeEvents(*SubscribeRequest, DaemonService_SubscribeEventsServer) error GetEvents(context.Context, *GetEventsRequest) (*GetEventsResponse, error) + // List available networks + GetProfiles(context.Context, *GetProfilesRequest) (*GetProfilesResponse, error) mustEmbedUnimplementedDaemonServiceServer() } @@ -376,6 +389,9 @@ func (UnimplementedDaemonServiceServer) SubscribeEvents(*SubscribeRequest, Daemo func (UnimplementedDaemonServiceServer) GetEvents(context.Context, *GetEventsRequest) (*GetEventsResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method GetEvents not implemented") } +func (UnimplementedDaemonServiceServer) GetProfiles(context.Context, *GetProfilesRequest) (*GetProfilesResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetProfiles not implemented") +} func (UnimplementedDaemonServiceServer) mustEmbedUnimplementedDaemonServiceServer() {} // UnsafeDaemonServiceServer may be embedded to opt out of forward compatibility for this service. @@ -752,6 +768,24 @@ func _DaemonService_GetEvents_Handler(srv interface{}, ctx context.Context, dec return interceptor(ctx, in, info, handler) } +func _DaemonService_GetProfiles_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetProfilesRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(DaemonServiceServer).GetProfiles(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/daemon.DaemonService/GetProfiles", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(DaemonServiceServer).GetProfiles(ctx, req.(*GetProfilesRequest)) + } + return interceptor(ctx, in, info, handler) +} + // DaemonService_ServiceDesc is the grpc.ServiceDesc for DaemonService service. // It's only intended for direct use with grpc.RegisterService, // and not to be introspected or modified (even as a copy) @@ -835,6 +869,10 @@ var DaemonService_ServiceDesc = grpc.ServiceDesc{ MethodName: "GetEvents", Handler: _DaemonService_GetEvents_Handler, }, + { + MethodName: "GetProfiles", + Handler: _DaemonService_GetProfiles_Handler, + }, }, Streams: []grpc.StreamDesc{ { diff --git a/client/ui/client_ui.go b/client/ui/client_ui.go index 0c79712a0..37075d548 100644 --- a/client/ui/client_ui.go +++ b/client/ui/client_ui.go @@ -51,11 +51,11 @@ const ( ) func main() { - daemonAddr, showSettings, showNetworks, showDebug, errorMsg, saveLogsInFile := parseFlags() + flags := parseFlags() // Initialize file logging if needed. var logFile string - if saveLogsInFile { + if flags.saveLogsInFile { file, err := initLogFile() if err != nil { log.Errorf("error while initializing log: %v", err) @@ -71,19 +71,27 @@ func main() { a.SetIcon(fyne.NewStaticResource("netbird", iconDisconnected)) // Show error message window if needed. - if errorMsg != "" { - showErrorMessage(errorMsg) + if flags.errorMsg != "" { + showErrorMessage(flags.errorMsg) return } // Create the service client (this also builds the settings or networks UI if requested). - client := newServiceClient(daemonAddr, logFile, a, showSettings, showNetworks, showDebug) + client := newServiceClient(&newServiceClientArgs{ + addr: flags.daemonAddr, + logFile: logFile, + app: a, + showSettings: flags.showSettings, + showNetworks: flags.showNetworks, + showDebug: flags.showDebug, + showProfiles: flags.showProfiles, + }) // Watch for theme/settings changes to update the icon. go watchSettingsChanges(a, client) // Run in window mode if any UI flag was set. - if showSettings || showNetworks || showDebug { + if flags.showSettings || flags.showNetworks || flags.showDebug || flags.showProfiles { a.Run() return } @@ -103,20 +111,33 @@ func main() { systray.Run(client.onTrayReady, client.onTrayExit) } +type cliFlags struct { + daemonAddr string + showSettings bool + showNetworks bool + showProfiles bool + showDebug bool + errorMsg string + saveLogsInFile bool +} + // parseFlags reads and returns all needed command-line flags. -func parseFlags() (daemonAddr string, showSettings, showNetworks, showDebug bool, errorMsg string, saveLogsInFile bool) { +func parseFlags() *cliFlags { + var flags cliFlags + defaultDaemonAddr := "unix:///var/run/netbird.sock" if runtime.GOOS == "windows" { defaultDaemonAddr = "tcp://127.0.0.1:41731" } - flag.StringVar(&daemonAddr, "daemon-addr", defaultDaemonAddr, "Daemon service address to serve CLI requests [unix|tcp]://[path|host:port]") - flag.BoolVar(&showSettings, "settings", false, "run settings window") - flag.BoolVar(&showNetworks, "networks", false, "run networks window") - flag.BoolVar(&showDebug, "debug", false, "run debug window") - flag.StringVar(&errorMsg, "error-msg", "", "displays an error message window") - flag.BoolVar(&saveLogsInFile, "use-log-file", false, fmt.Sprintf("save logs in a file: %s/netbird-ui-PID.log", os.TempDir())) + flag.StringVar(&flags.daemonAddr, "daemon-addr", defaultDaemonAddr, "Daemon service address to serve CLI requests [unix|tcp]://[path|host:port]") + flag.BoolVar(&flags.showSettings, "settings", false, "run settings window") + flag.BoolVar(&flags.showNetworks, "networks", false, "run networks window") + flag.BoolVar(&flags.showProfiles, "profiles", false, "run profiles window") + flag.BoolVar(&flags.showDebug, "debug", false, "run debug window") + flag.StringVar(&flags.errorMsg, "error-msg", "", "displays an error message window") + flag.BoolVar(&flags.saveLogsInFile, "use-log-file", false, fmt.Sprintf("save logs in a file: %s/netbird-ui-PID.log", os.TempDir())) flag.Parse() - return + return &flags } // initLogFile initializes logging into a file. @@ -180,6 +201,7 @@ type serviceClient struct { // systray menu items mStatus *systray.MenuItem + mProfileName *systray.MenuItem mUp *systray.MenuItem mDown *systray.MenuItem mSettings *systray.MenuItem @@ -233,6 +255,7 @@ type serviceClient struct { isUpdateIconActive bool showNetworks bool wNetworks fyne.Window + wProfiles fyne.Window eventManager *event.Manager @@ -246,33 +269,45 @@ type menuHandler struct { cancel context.CancelFunc } +type newServiceClientArgs struct { + addr string + logFile string + app fyne.App + showSettings bool + showNetworks bool + showDebug bool + showProfiles bool +} + // newServiceClient instance constructor // // This constructor also builds the UI elements for the settings window. -func newServiceClient(addr string, logFile string, a fyne.App, showSettings bool, showNetworks bool, showDebug bool) *serviceClient { +func newServiceClient(args *newServiceClientArgs) *serviceClient { ctx, cancel := context.WithCancel(context.Background()) s := &serviceClient{ ctx: ctx, cancel: cancel, - addr: addr, - app: a, - logFile: logFile, + addr: args.addr, + app: args.app, + logFile: args.logFile, sendNotification: false, - showAdvancedSettings: showSettings, - showNetworks: showNetworks, + showAdvancedSettings: args.showSettings, + showNetworks: args.showNetworks, update: version.NewUpdate(), } s.setNewIcons() switch { - case showSettings: + case args.showSettings: s.showSettingsUI() - case showNetworks: + case args.showNetworks: s.showNetworksUI() - case showDebug: + case args.showDebug: s.showDebugUI() + case args.showProfiles: + s.showProfilesUI() } return s @@ -624,6 +659,8 @@ func (s *serviceClient) onTrayReady() { // setup systray menu items s.mStatus = systray.AddMenuItem("Disconnected", "Disconnected") s.mStatus.Disable() + s.mProfileName = systray.AddMenuItem("Profile: Home", "Selected Profile: Home") + s.mProfileName.Disable() systray.AddSeparator() s.mUp = systray.AddMenuItem("Connect", "Connect") s.mDown = systray.AddMenuItem("Disconnect", "Disconnect") @@ -641,7 +678,7 @@ func (s *serviceClient) onTrayReady() { s.loadSettings() s.mProfiles = newProfileMenu(systray.AddMenuItem("Profiles", profilesMenuDescr)) - s.mProfiles.loadProfiles() + go s.updateProfiles() s.exitNodeMu.Lock() s.mExitNode = systray.AddMenuItem("Exit Node", exitNodeMenuDescr) @@ -791,6 +828,12 @@ func (s *serviceClient) listenEvents() { defer s.mNetworks.Enable() s.runSelfCommand("networks", "true") }() + case <-s.mProfiles.manageItem.ClickedCh: + s.mProfiles.manageItem.Disable() + go func() { + defer s.mProfiles.manageItem.Enable() + s.runSelfCommand("profiles", "true") + }() case <-s.mNotifications.ClickedCh: if s.mNotifications.Checked() { s.mNotifications.Uncheck() @@ -1039,11 +1082,11 @@ func (s *serviceClient) updateConfig() error { lazyConnectionEnabled := s.mLazyConnEnabled.Checked() loginRequest := proto.LoginRequest{ - IsUnixDesktopClient: runtime.GOOS == "linux" || runtime.GOOS == "freebsd", - ServerSSHAllowed: &sshAllowed, - RosenpassEnabled: &rosenpassEnabled, - DisableAutoConnect: &disableAutoStart, - DisableNotifications: ¬ificationsDisabled, + IsUnixDesktopClient: runtime.GOOS == "linux" || runtime.GOOS == "freebsd", + ServerSSHAllowed: &sshAllowed, + RosenpassEnabled: &rosenpassEnabled, + DisableAutoConnect: &disableAutoStart, + DisableNotifications: ¬ificationsDisabled, LazyConnectionEnabled: &lazyConnectionEnabled, } diff --git a/client/ui/profile.go b/client/ui/profile.go index 60a01aef0..5dc9e7e69 100644 --- a/client/ui/profile.go +++ b/client/ui/profile.go @@ -1,8 +1,186 @@ package main -import "fyne.io/systray" +import ( + "context" + "errors" + "fmt" + "sync" + + "fyne.io/fyne/v2" + "fyne.io/fyne/v2/container" + "fyne.io/fyne/v2/dialog" + "fyne.io/fyne/v2/layout" + "fyne.io/fyne/v2/widget" + "fyne.io/systray" + log "github.com/sirupsen/logrus" + + "github.com/netbirdio/netbird/client/proto" +) + +var mockProfiles = []profile{ + {name: "Default", selected: false}, + {name: "Home", selected: true}, + {name: "Work", selected: false}, +} + +// showProfilesUI creates and displays the Profiles window with a list of existing profiles, +// a button to add new profiles, allows removal, and lets the user switch the active profile. +func (s *serviceClient) showProfilesUI() { + + var idx int + // List widget for profiles + list := widget.NewList( + func() int { return len(mockProfiles) }, + func() fyne.CanvasObject { + // Each item: Selected indicator, Name, spacer, Select & Remove buttons + return container.NewHBox( + widget.NewLabel(""), // indicator + widget.NewLabel(""), // profile name + layout.NewSpacer(), + widget.NewButton("Select", nil), + widget.NewButton("Remove", nil), + ) + }, + func(i widget.ListItemID, item fyne.CanvasObject) { + // Populate each row + row := item.(*fyne.Container) + indicator := row.Objects[0].(*widget.Label) + nameLabel := row.Objects[1].(*widget.Label) + selectBtn := row.Objects[3].(*widget.Button) + removeBtn := row.Objects[4].(*widget.Button) + + profile := mockProfiles[i] + // Show a checkmark if selected + if profile.selected { + indicator.SetText("✓") + } else { + indicator.SetText("") + } + nameLabel.SetText(profile.name) + + // Configure Select/Active button + selectBtn.SetText(func() string { + if profile.selected { + return "Active" + } + return "Select" + }()) + selectBtn.OnTapped = func() { + if profile.selected { + return // already active + } + // confirm switch + dialog.ShowConfirm( + "Switch Profile", + fmt.Sprintf("Are you sure you want to switch to '%s'?", profile.name), + func(confirm bool) { + if !confirm { + return + } + // backend switch + //err := s.switchProfile(profile.name) + var err error + if idx%2 == 0 { + err = errors.New("failed to switch profile") + } else { + if idx%2 == 1 { + dialog.ShowInformation( + "Profile Switched", + fmt.Sprintf("Profile '%s' switched successfully", profile.name), + s.wProfiles, + ) + } + } + idx++ + if err != nil { + dialog.ShowError(fmt.Errorf("failed to select profile: %w", err), s.wProfiles) + return + } + // update slice flags + + //refresh() + }, + s.wProfiles, + ) + } + + // Remove profile + removeBtn.SetText("Remove") + removeBtn.OnTapped = func() { + dialog.ShowConfirm( + "Delete Profile", + fmt.Sprintf("Are you sure you want to delete '%s'?", profile.name), + func(confirm bool) { + if !confirm { + return + } + // backend remove + //s.removeProfile(profile.name) + // update slice and refresh + //profiles = append(profiles[:i], profiles[i+1:]...) + //refresh() + }, + s.wProfiles, + ) + } + }, + ) + + // Button to add a new profile + newBtn := widget.NewButton("New Profile", func() { + nameEntry := widget.NewEntry() + nameEntry.SetPlaceHolder("Enter Profile Name") + + formItems := []*widget.FormItem{{Text: "Name:", Widget: nameEntry}} + dlg := dialog.NewForm( + "New Profile", + "Create", + "Cancel", + formItems, + func(confirm bool) { + if !confirm { + return + } + name := nameEntry.Text + if name == "" { + dialog.ShowError(errors.New("profile name cannot be empty"), s.wProfiles) + return + } + // backend create + //s.createProfile(name) + // add to slice, default unselected + //profiles = append(profiles, profile{name: name, selected: false}) + //refresh() + }, + s.wProfiles, + ) + // make dialog wider + dlg.Resize(fyne.NewSize(350, 150)) + dlg.Show() + }) + + // Assemble window content + content := container.NewBorder(nil, newBtn, nil, nil, list) + s.wProfiles = s.app.NewWindow("NetBird Profiles") + s.wProfiles.SetContent(content) + s.wProfiles.Resize(fyne.NewSize(400, 300)) + s.wProfiles.SetOnClosed(s.cancel) + + s.wProfiles.Show() +} + +func (s *serviceClient) updateProfiles() { + conn, err := s.getSrvClient(defaultFailTimeout) + if err != nil { + log.Errorf("get client: %v", err) + return + } + + s.mProfiles.updateProfiles(s.ctx, conn) +} type profileMenu struct { + mtx sync.Mutex menu *systray.MenuItem profiles []profileMenuItem manageItem *systray.MenuItem @@ -24,21 +202,19 @@ func newProfileMenu(menu *systray.MenuItem) *profileMenu { return p } -func (p *profileMenu) loadProfiles() { - - // Load profiles from the configuration - //profiles := config.GetProfiles() - profiles := []profile{ - {name: "Default", selected: true}, - {name: "Profile 1", selected: false}, - {name: "Profile 2", selected: false}, - } +func (p *profileMenu) loadProfiles(profiles []*proto.Profile) { // Clear existing profiles p.clearProfiles() + p.mtx.Lock() + defer p.mtx.Unlock() for _, profile := range profiles { - p.addProfile(profile) + menuItem := p.menu.AddSubMenuItem(profile.Name, "Switch to "+profile.Name) + if profile.Selected { + menuItem.Check() + } + p.profiles = append(p.profiles, profileMenuItem{menuItem: menuItem}) } // add manage profiles item @@ -47,20 +223,35 @@ func (p *profileMenu) loadProfiles() { } -func (p *profileMenu) addProfile(profile profile) { - profName := profile.name - if profile.selected { - profName += " *" - } - - menuItem := p.menu.AddSubMenuItem(profName, "Switch to "+profile.name) - p.profiles = append(p.profiles, profileMenuItem{menuItem: menuItem}) - -} func (p *profileMenu) clearProfiles() { + p.mtx.Lock() + defer p.mtx.Unlock() // Remove all existing profile menu items for _, item := range p.profiles { item.menuItem.Remove() } p.profiles = nil } + +func (p *profileMenu) updateProfiles(ctx context.Context, conn proto.DaemonServiceClient) { + profiles, err := p.getProfiles(ctx, conn) + if err != nil { + log.Errorf("get profiles: %v", err) + return + } + + p.loadProfiles(profiles) + +} + +func (p *profileMenu) getProfiles(pCtx context.Context, conn proto.DaemonServiceClient) ([]*proto.Profile, error) { + ctx, cancel := context.WithTimeout(pCtx, defaultFailTimeout) + defer cancel() + + resp, err := conn.GetProfiles(ctx, &proto.GetProfilesRequest{}) + if err != nil { + return nil, fmt.Errorf("get profiles: %v", err) + } + + return resp.Profiles, nil +}