From 9e1264d40ac67a11de7b51acdcfc31577344cc66 Mon Sep 17 00:00:00 2001 From: Santtu Lakkala Date: Tue, 24 Sep 2024 13:00:58 +0300 Subject: [PATCH] Implement locale and timezone setting --- Cargo.toml | 2 +- api/admin/admin.pb.go | 383 ++++++++++++++++++++++---------- api/admin/admin.proto | 13 +- api/admin/admin_grpc.pb.go | 76 ++++++- api/hwid/hwid.pb.go | 10 +- api/hwid/hwid_grpc.pb.go | 2 +- api/systemd/systemd.pb.go | 20 +- api/systemd/systemd_grpc.pb.go | 2 +- api/wifi/wifi.pb.go | 18 +- api/wifi/wifi_grpc.pb.go | 2 +- client/src/client.rs | 29 ++- internal/cmd/givc-agent/main.go | 23 +- nixos/modules/appvm.nix | 15 ++ src/admin/server.rs | 51 ++++- src/bin/givc-agent.rs | 20 +- src/bin/givc-cli.rs | 14 ++ 16 files changed, 523 insertions(+), 157 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 335d00d..809e98b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,7 +24,7 @@ http = "0.2" http-body = "0.4.2" hyper = "0.14" prost = "0.12" -tokio = {version = "1.0", features = ["rt-multi-thread", "time", "macros"]} +tokio = {version = "1.0", features = ["rt-multi-thread", "time", "macros", "fs"]} tokio-stream = "0.1" tonic = {version="0.11.0", features = ["tls"]} tonic-types = {version="0.11.0"} diff --git a/api/admin/admin.pb.go b/api/admin/admin.pb.go index 2a969fe..ba46fda 100644 --- a/api/admin/admin.pb.go +++ b/api/admin/admin.pb.go @@ -3,8 +3,8 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.34.2 -// protoc v4.25.4 +// protoc-gen-go v1.34.1 +// protoc v4.24.4 // source: admin.proto package admin @@ -257,7 +257,8 @@ type RegistryResponse struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - CmdStatus string `protobuf:"bytes,1,opt,name=CmdStatus,proto3" json:"CmdStatus,omitempty"` + Timezone string `protobuf:"bytes,1,opt,name=Timezone,proto3" json:"Timezone,omitempty"` + Locale string `protobuf:"bytes,2,opt,name=Locale,proto3" json:"Locale,omitempty"` } func (x *RegistryResponse) Reset() { @@ -292,9 +293,16 @@ func (*RegistryResponse) Descriptor() ([]byte, []int) { return file_admin_proto_rawDescGZIP(), []int{3} } -func (x *RegistryResponse) GetCmdStatus() string { +func (x *RegistryResponse) GetTimezone() string { if x != nil { - return x.CmdStatus + return x.Timezone + } + return "" +} + +func (x *RegistryResponse) GetLocale() string { + if x != nil { + return x.Locale } return "" } @@ -682,6 +690,100 @@ func (*WatchItem_Updated) isWatchItem_Status() {} func (*WatchItem_Removed) isWatchItem_Status() {} +type LocaleRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Locale string `protobuf:"bytes,1,opt,name=Locale,proto3" json:"Locale,omitempty"` +} + +func (x *LocaleRequest) Reset() { + *x = LocaleRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_admin_proto_msgTypes[10] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *LocaleRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*LocaleRequest) ProtoMessage() {} + +func (x *LocaleRequest) ProtoReflect() protoreflect.Message { + mi := &file_admin_proto_msgTypes[10] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use LocaleRequest.ProtoReflect.Descriptor instead. +func (*LocaleRequest) Descriptor() ([]byte, []int) { + return file_admin_proto_rawDescGZIP(), []int{10} +} + +func (x *LocaleRequest) GetLocale() string { + if x != nil { + return x.Locale + } + return "" +} + +type TimezoneRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Timezone string `protobuf:"bytes,1,opt,name=Timezone,proto3" json:"Timezone,omitempty"` +} + +func (x *TimezoneRequest) Reset() { + *x = TimezoneRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_admin_proto_msgTypes[11] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *TimezoneRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TimezoneRequest) ProtoMessage() {} + +func (x *TimezoneRequest) ProtoReflect() protoreflect.Message { + mi := &file_admin_proto_msgTypes[11] + 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 TimezoneRequest.ProtoReflect.Descriptor instead. +func (*TimezoneRequest) Descriptor() ([]byte, []int) { + return file_admin_proto_rawDescGZIP(), []int{11} +} + +func (x *TimezoneRequest) GetTimezone() string { + if x != nil { + return x.Timezone + } + return "" +} + var File_admin_proto protoreflect.FileDescriptor var file_admin_proto_rawDesc = []byte{ @@ -714,91 +816,104 @@ var file_admin_proto_rawDesc = []byte{ 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x27, 0x0a, 0x05, 0x53, 0x74, 0x61, 0x74, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x55, 0x6e, 0x69, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x05, 0x53, 0x74, 0x61, 0x74, - 0x65, 0x22, 0x30, 0x0a, 0x10, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x43, 0x6d, 0x64, 0x53, 0x74, 0x61, 0x74, - 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x43, 0x6d, 0x64, 0x53, 0x74, 0x61, - 0x74, 0x75, 0x73, 0x22, 0x6a, 0x0a, 0x12, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x41, 0x70, 0x70, - 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x41, 0x70, 0x70, 0x4e, - 0x61, 0x6d, 0x65, 0x12, 0x1b, 0x0a, 0x06, 0x56, 0x6d, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x06, 0x56, 0x6d, 0x4e, 0x61, 0x6d, 0x65, 0x88, 0x01, 0x01, - 0x12, 0x12, 0x0a, 0x04, 0x41, 0x72, 0x67, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x04, - 0x41, 0x72, 0x67, 0x73, 0x42, 0x09, 0x0a, 0x07, 0x5f, 0x56, 0x6d, 0x4e, 0x61, 0x6d, 0x65, 0x22, - 0x51, 0x0a, 0x13, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x43, 0x6d, 0x64, 0x53, 0x74, 0x61, - 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x43, 0x6d, 0x64, 0x53, 0x74, - 0x61, 0x74, 0x75, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x41, 0x70, 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, - 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x41, 0x70, 0x70, 0x53, 0x74, 0x61, 0x74, - 0x75, 0x73, 0x22, 0x07, 0x0a, 0x05, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x81, 0x01, 0x0a, 0x0d, - 0x51, 0x75, 0x65, 0x72, 0x79, 0x4c, 0x69, 0x73, 0x74, 0x49, 0x74, 0x65, 0x6d, 0x12, 0x12, 0x0a, - 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, - 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, - 0x69, 0x6f, 0x6e, 0x12, 0x1a, 0x0a, 0x08, 0x56, 0x6d, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x56, 0x6d, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, - 0x1e, 0x0a, 0x0a, 0x54, 0x72, 0x75, 0x73, 0x74, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x04, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x0a, 0x54, 0x72, 0x75, 0x73, 0x74, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x22, - 0x3d, 0x0a, 0x11, 0x51, 0x75, 0x65, 0x72, 0x79, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x28, 0x0a, 0x04, 0x4c, 0x69, 0x73, 0x74, 0x18, 0x01, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, - 0x4c, 0x69, 0x73, 0x74, 0x49, 0x74, 0x65, 0x6d, 0x52, 0x04, 0x4c, 0x69, 0x73, 0x74, 0x22, 0xdd, - 0x01, 0x0a, 0x09, 0x57, 0x61, 0x74, 0x63, 0x68, 0x49, 0x74, 0x65, 0x6d, 0x12, 0x34, 0x0a, 0x07, - 0x49, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, - 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x4c, 0x69, 0x73, 0x74, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x48, 0x00, 0x52, 0x07, 0x49, 0x6e, 0x69, 0x74, 0x69, - 0x61, 0x6c, 0x12, 0x2c, 0x0a, 0x05, 0x41, 0x64, 0x64, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x14, 0x2e, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x4c, - 0x69, 0x73, 0x74, 0x49, 0x74, 0x65, 0x6d, 0x48, 0x00, 0x52, 0x05, 0x41, 0x64, 0x64, 0x65, 0x64, - 0x12, 0x30, 0x0a, 0x07, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x14, 0x2e, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x4c, - 0x69, 0x73, 0x74, 0x49, 0x74, 0x65, 0x6d, 0x48, 0x00, 0x52, 0x07, 0x55, 0x70, 0x64, 0x61, 0x74, - 0x65, 0x64, 0x12, 0x30, 0x0a, 0x07, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x18, 0x04, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x51, 0x75, 0x65, 0x72, - 0x79, 0x4c, 0x69, 0x73, 0x74, 0x49, 0x74, 0x65, 0x6d, 0x48, 0x00, 0x52, 0x07, 0x52, 0x65, 0x6d, - 0x6f, 0x76, 0x65, 0x64, 0x42, 0x08, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x32, 0x8f, - 0x05, 0x0a, 0x0c, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, - 0x44, 0x0a, 0x0f, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x53, 0x65, 0x72, 0x76, 0x69, - 0x63, 0x65, 0x12, 0x16, 0x2e, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, - 0x74, 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x61, 0x64, 0x6d, - 0x69, 0x6e, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x4b, 0x0a, 0x10, 0x53, 0x74, 0x61, 0x72, 0x74, 0x41, 0x70, - 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x19, 0x2e, 0x61, 0x64, 0x6d, 0x69, - 0x6e, 0x2e, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x41, 0x70, 0x70, - 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x22, 0x00, 0x12, 0x4b, 0x0a, 0x10, 0x50, 0x61, 0x75, 0x73, 0x65, 0x41, 0x70, 0x70, 0x6c, 0x69, - 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x19, 0x2e, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x41, - 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x1a, 0x2e, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, - 0x4c, 0x0a, 0x11, 0x52, 0x65, 0x73, 0x75, 0x6d, 0x65, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, + 0x65, 0x22, 0x46, 0x0a, 0x10, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x54, 0x69, 0x6d, 0x65, 0x7a, 0x6f, 0x6e, + 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x54, 0x69, 0x6d, 0x65, 0x7a, 0x6f, 0x6e, + 0x65, 0x12, 0x16, 0x0a, 0x06, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x06, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x65, 0x22, 0x6a, 0x0a, 0x12, 0x41, 0x70, 0x70, + 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, + 0x18, 0x0a, 0x07, 0x41, 0x70, 0x70, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x07, 0x41, 0x70, 0x70, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1b, 0x0a, 0x06, 0x56, 0x6d, 0x4e, + 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x06, 0x56, 0x6d, 0x4e, + 0x61, 0x6d, 0x65, 0x88, 0x01, 0x01, 0x12, 0x12, 0x0a, 0x04, 0x41, 0x72, 0x67, 0x73, 0x18, 0x03, + 0x20, 0x03, 0x28, 0x09, 0x52, 0x04, 0x41, 0x72, 0x67, 0x73, 0x42, 0x09, 0x0a, 0x07, 0x5f, 0x56, + 0x6d, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x51, 0x0a, 0x13, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1c, 0x0a, 0x09, + 0x43, 0x6d, 0x64, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x09, 0x43, 0x6d, 0x64, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x41, 0x70, + 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x41, + 0x70, 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0x07, 0x0a, 0x05, 0x45, 0x6d, 0x70, 0x74, + 0x79, 0x22, 0x81, 0x01, 0x0a, 0x0d, 0x51, 0x75, 0x65, 0x72, 0x79, 0x4c, 0x69, 0x73, 0x74, 0x49, + 0x74, 0x65, 0x6d, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x44, 0x65, 0x73, 0x63, 0x72, + 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x44, 0x65, + 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1a, 0x0a, 0x08, 0x56, 0x6d, 0x53, + 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x56, 0x6d, 0x53, + 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1e, 0x0a, 0x0a, 0x54, 0x72, 0x75, 0x73, 0x74, 0x4c, 0x65, + 0x76, 0x65, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x54, 0x72, 0x75, 0x73, 0x74, + 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x22, 0x3d, 0x0a, 0x11, 0x51, 0x75, 0x65, 0x72, 0x79, 0x4c, 0x69, + 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x28, 0x0a, 0x04, 0x4c, 0x69, + 0x73, 0x74, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x61, 0x64, 0x6d, 0x69, 0x6e, + 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x4c, 0x69, 0x73, 0x74, 0x49, 0x74, 0x65, 0x6d, 0x52, 0x04, + 0x4c, 0x69, 0x73, 0x74, 0x22, 0xdd, 0x01, 0x0a, 0x09, 0x57, 0x61, 0x74, 0x63, 0x68, 0x49, 0x74, + 0x65, 0x6d, 0x12, 0x34, 0x0a, 0x07, 0x49, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x51, 0x75, 0x65, 0x72, + 0x79, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x48, 0x00, 0x52, + 0x07, 0x49, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x12, 0x2c, 0x0a, 0x05, 0x41, 0x64, 0x64, 0x65, + 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, + 0x51, 0x75, 0x65, 0x72, 0x79, 0x4c, 0x69, 0x73, 0x74, 0x49, 0x74, 0x65, 0x6d, 0x48, 0x00, 0x52, + 0x05, 0x41, 0x64, 0x64, 0x65, 0x64, 0x12, 0x30, 0x0a, 0x07, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, + 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, + 0x51, 0x75, 0x65, 0x72, 0x79, 0x4c, 0x69, 0x73, 0x74, 0x49, 0x74, 0x65, 0x6d, 0x48, 0x00, 0x52, + 0x07, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x12, 0x30, 0x0a, 0x07, 0x52, 0x65, 0x6d, 0x6f, + 0x76, 0x65, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x61, 0x64, 0x6d, 0x69, + 0x6e, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x4c, 0x69, 0x73, 0x74, 0x49, 0x74, 0x65, 0x6d, 0x48, + 0x00, 0x52, 0x07, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x42, 0x08, 0x0a, 0x06, 0x53, 0x74, + 0x61, 0x74, 0x75, 0x73, 0x22, 0x27, 0x0a, 0x0d, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x65, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x65, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x65, 0x22, 0x2d, 0x0a, + 0x0f, 0x54, 0x69, 0x6d, 0x65, 0x7a, 0x6f, 0x6e, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x12, 0x1a, 0x0a, 0x08, 0x54, 0x69, 0x6d, 0x65, 0x7a, 0x6f, 0x6e, 0x65, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x08, 0x54, 0x69, 0x6d, 0x65, 0x7a, 0x6f, 0x6e, 0x65, 0x32, 0xf9, 0x05, 0x0a, + 0x0c, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x44, 0x0a, + 0x0f, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x12, 0x16, 0x2e, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, + 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x61, 0x64, 0x6d, 0x69, 0x6e, + 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x22, 0x00, 0x12, 0x4b, 0x0a, 0x10, 0x53, 0x74, 0x61, 0x72, 0x74, 0x41, 0x70, 0x70, 0x6c, + 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x19, 0x2e, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, + 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x41, 0x70, 0x70, 0x6c, 0x69, + 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, + 0x12, 0x4b, 0x0a, 0x10, 0x50, 0x61, 0x75, 0x73, 0x65, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x19, 0x2e, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x4a, 0x0a, - 0x0f, 0x53, 0x74, 0x6f, 0x70, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x12, 0x19, 0x2e, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x61, 0x64, - 0x6d, 0x69, 0x6e, 0x2e, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x28, 0x0a, 0x08, 0x50, 0x6f, 0x77, - 0x65, 0x72, 0x6f, 0x66, 0x66, 0x12, 0x0c, 0x2e, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x45, 0x6d, - 0x70, 0x74, 0x79, 0x1a, 0x0c, 0x2e, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x45, 0x6d, 0x70, 0x74, - 0x79, 0x22, 0x00, 0x12, 0x26, 0x0a, 0x06, 0x52, 0x65, 0x62, 0x6f, 0x6f, 0x74, 0x12, 0x0c, 0x2e, + 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x4c, 0x0a, + 0x11, 0x52, 0x65, 0x73, 0x75, 0x6d, 0x65, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x12, 0x19, 0x2e, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x41, 0x70, 0x70, 0x6c, 0x69, + 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, + 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x4a, 0x0a, 0x0f, 0x53, + 0x74, 0x6f, 0x70, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x19, + 0x2e, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x61, 0x64, 0x6d, 0x69, + 0x6e, 0x2e, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x31, 0x0a, 0x09, 0x53, 0x65, 0x74, 0x4c, 0x6f, + 0x63, 0x61, 0x6c, 0x65, 0x12, 0x14, 0x2e, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x4c, 0x6f, 0x63, + 0x61, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0c, 0x2e, 0x61, 0x64, 0x6d, + 0x69, 0x6e, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x12, 0x35, 0x0a, 0x0b, 0x53, 0x65, + 0x74, 0x54, 0x69, 0x6d, 0x65, 0x7a, 0x6f, 0x6e, 0x65, 0x12, 0x16, 0x2e, 0x61, 0x64, 0x6d, 0x69, + 0x6e, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x7a, 0x6f, 0x6e, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x0c, 0x2e, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, + 0x00, 0x12, 0x28, 0x0a, 0x08, 0x50, 0x6f, 0x77, 0x65, 0x72, 0x6f, 0x66, 0x66, 0x12, 0x0c, 0x2e, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x0c, 0x2e, 0x61, 0x64, - 0x6d, 0x69, 0x6e, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x12, 0x27, 0x0a, 0x07, 0x53, - 0x75, 0x73, 0x70, 0x65, 0x6e, 0x64, 0x12, 0x0c, 0x2e, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x45, - 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x0c, 0x2e, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x45, 0x6d, 0x70, - 0x74, 0x79, 0x22, 0x00, 0x12, 0x26, 0x0a, 0x06, 0x57, 0x61, 0x6b, 0x65, 0x75, 0x70, 0x12, 0x0c, + 0x6d, 0x69, 0x6e, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x12, 0x26, 0x0a, 0x06, 0x52, + 0x65, 0x62, 0x6f, 0x6f, 0x74, 0x12, 0x0c, 0x2e, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x45, 0x6d, + 0x70, 0x74, 0x79, 0x1a, 0x0c, 0x2e, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x45, 0x6d, 0x70, 0x74, + 0x79, 0x22, 0x00, 0x12, 0x27, 0x0a, 0x07, 0x53, 0x75, 0x73, 0x70, 0x65, 0x6e, 0x64, 0x12, 0x0c, 0x2e, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x0c, 0x2e, 0x61, - 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x12, 0x35, 0x0a, 0x09, - 0x51, 0x75, 0x65, 0x72, 0x79, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x0c, 0x2e, 0x61, 0x64, 0x6d, 0x69, - 0x6e, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x18, 0x2e, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, - 0x51, 0x75, 0x65, 0x72, 0x79, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x22, 0x00, 0x12, 0x2b, 0x0a, 0x05, 0x57, 0x61, 0x74, 0x63, 0x68, 0x12, 0x0c, 0x2e, 0x61, - 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x10, 0x2e, 0x61, 0x64, 0x6d, - 0x69, 0x6e, 0x2e, 0x57, 0x61, 0x74, 0x63, 0x68, 0x49, 0x74, 0x65, 0x6d, 0x22, 0x00, 0x30, 0x01, - 0x42, 0x09, 0x5a, 0x07, 0x2e, 0x2f, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x62, 0x06, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x33, + 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x12, 0x26, 0x0a, 0x06, + 0x57, 0x61, 0x6b, 0x65, 0x75, 0x70, 0x12, 0x0c, 0x2e, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x45, + 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x0c, 0x2e, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x45, 0x6d, 0x70, + 0x74, 0x79, 0x22, 0x00, 0x12, 0x35, 0x0a, 0x09, 0x51, 0x75, 0x65, 0x72, 0x79, 0x4c, 0x69, 0x73, + 0x74, 0x12, 0x0c, 0x2e, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, + 0x18, 0x2e, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x4c, 0x69, 0x73, + 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x2b, 0x0a, 0x05, 0x57, + 0x61, 0x74, 0x63, 0x68, 0x12, 0x0c, 0x2e, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x45, 0x6d, 0x70, + 0x74, 0x79, 0x1a, 0x10, 0x2e, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x57, 0x61, 0x74, 0x63, 0x68, + 0x49, 0x74, 0x65, 0x6d, 0x22, 0x00, 0x30, 0x01, 0x42, 0x09, 0x5a, 0x07, 0x2e, 0x2f, 0x61, 0x64, + 0x6d, 0x69, 0x6e, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -813,8 +928,8 @@ func file_admin_proto_rawDescGZIP() []byte { return file_admin_proto_rawDescData } -var file_admin_proto_msgTypes = make([]protoimpl.MessageInfo, 10) -var file_admin_proto_goTypes = []any{ +var file_admin_proto_msgTypes = make([]protoimpl.MessageInfo, 12) +var file_admin_proto_goTypes = []interface{}{ (*UnitStatus)(nil), // 0: admin.UnitStatus (*TransportConfig)(nil), // 1: admin.TransportConfig (*RegistryRequest)(nil), // 2: admin.RegistryRequest @@ -825,6 +940,8 @@ var file_admin_proto_goTypes = []any{ (*QueryListItem)(nil), // 7: admin.QueryListItem (*QueryListResponse)(nil), // 8: admin.QueryListResponse (*WatchItem)(nil), // 9: admin.WatchItem + (*LocaleRequest)(nil), // 10: admin.LocaleRequest + (*TimezoneRequest)(nil), // 11: admin.TimezoneRequest } var file_admin_proto_depIdxs = []int32{ 1, // 0: admin.RegistryRequest.Transport:type_name -> admin.TransportConfig @@ -839,25 +956,29 @@ var file_admin_proto_depIdxs = []int32{ 4, // 9: admin.AdminService.PauseApplication:input_type -> admin.ApplicationRequest 4, // 10: admin.AdminService.ResumeApplication:input_type -> admin.ApplicationRequest 4, // 11: admin.AdminService.StopApplication:input_type -> admin.ApplicationRequest - 6, // 12: admin.AdminService.Poweroff:input_type -> admin.Empty - 6, // 13: admin.AdminService.Reboot:input_type -> admin.Empty - 6, // 14: admin.AdminService.Suspend:input_type -> admin.Empty - 6, // 15: admin.AdminService.Wakeup:input_type -> admin.Empty - 6, // 16: admin.AdminService.QueryList:input_type -> admin.Empty - 6, // 17: admin.AdminService.Watch:input_type -> admin.Empty - 3, // 18: admin.AdminService.RegisterService:output_type -> admin.RegistryResponse - 5, // 19: admin.AdminService.StartApplication:output_type -> admin.ApplicationResponse - 5, // 20: admin.AdminService.PauseApplication:output_type -> admin.ApplicationResponse - 5, // 21: admin.AdminService.ResumeApplication:output_type -> admin.ApplicationResponse - 5, // 22: admin.AdminService.StopApplication:output_type -> admin.ApplicationResponse - 6, // 23: admin.AdminService.Poweroff:output_type -> admin.Empty - 6, // 24: admin.AdminService.Reboot:output_type -> admin.Empty - 6, // 25: admin.AdminService.Suspend:output_type -> admin.Empty - 6, // 26: admin.AdminService.Wakeup:output_type -> admin.Empty - 8, // 27: admin.AdminService.QueryList:output_type -> admin.QueryListResponse - 9, // 28: admin.AdminService.Watch:output_type -> admin.WatchItem - 18, // [18:29] is the sub-list for method output_type - 7, // [7:18] is the sub-list for method input_type + 10, // 12: admin.AdminService.SetLocale:input_type -> admin.LocaleRequest + 11, // 13: admin.AdminService.SetTimezone:input_type -> admin.TimezoneRequest + 6, // 14: admin.AdminService.Poweroff:input_type -> admin.Empty + 6, // 15: admin.AdminService.Reboot:input_type -> admin.Empty + 6, // 16: admin.AdminService.Suspend:input_type -> admin.Empty + 6, // 17: admin.AdminService.Wakeup:input_type -> admin.Empty + 6, // 18: admin.AdminService.QueryList:input_type -> admin.Empty + 6, // 19: admin.AdminService.Watch:input_type -> admin.Empty + 3, // 20: admin.AdminService.RegisterService:output_type -> admin.RegistryResponse + 5, // 21: admin.AdminService.StartApplication:output_type -> admin.ApplicationResponse + 5, // 22: admin.AdminService.PauseApplication:output_type -> admin.ApplicationResponse + 5, // 23: admin.AdminService.ResumeApplication:output_type -> admin.ApplicationResponse + 5, // 24: admin.AdminService.StopApplication:output_type -> admin.ApplicationResponse + 6, // 25: admin.AdminService.SetLocale:output_type -> admin.Empty + 6, // 26: admin.AdminService.SetTimezone:output_type -> admin.Empty + 6, // 27: admin.AdminService.Poweroff:output_type -> admin.Empty + 6, // 28: admin.AdminService.Reboot:output_type -> admin.Empty + 6, // 29: admin.AdminService.Suspend:output_type -> admin.Empty + 6, // 30: admin.AdminService.Wakeup:output_type -> admin.Empty + 8, // 31: admin.AdminService.QueryList:output_type -> admin.QueryListResponse + 9, // 32: admin.AdminService.Watch:output_type -> admin.WatchItem + 20, // [20:33] is the sub-list for method output_type + 7, // [7:20] is the sub-list for method input_type 7, // [7:7] is the sub-list for extension type_name 7, // [7:7] is the sub-list for extension extendee 0, // [0:7] is the sub-list for field type_name @@ -869,7 +990,7 @@ func file_admin_proto_init() { return } if !protoimpl.UnsafeEnabled { - file_admin_proto_msgTypes[0].Exporter = func(v any, i int) any { + file_admin_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*UnitStatus); i { case 0: return &v.state @@ -881,7 +1002,7 @@ func file_admin_proto_init() { return nil } } - file_admin_proto_msgTypes[1].Exporter = func(v any, i int) any { + file_admin_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*TransportConfig); i { case 0: return &v.state @@ -893,7 +1014,7 @@ func file_admin_proto_init() { return nil } } - file_admin_proto_msgTypes[2].Exporter = func(v any, i int) any { + file_admin_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*RegistryRequest); i { case 0: return &v.state @@ -905,7 +1026,7 @@ func file_admin_proto_init() { return nil } } - file_admin_proto_msgTypes[3].Exporter = func(v any, i int) any { + file_admin_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*RegistryResponse); i { case 0: return &v.state @@ -917,7 +1038,7 @@ func file_admin_proto_init() { return nil } } - file_admin_proto_msgTypes[4].Exporter = func(v any, i int) any { + file_admin_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ApplicationRequest); i { case 0: return &v.state @@ -929,7 +1050,7 @@ func file_admin_proto_init() { return nil } } - file_admin_proto_msgTypes[5].Exporter = func(v any, i int) any { + file_admin_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ApplicationResponse); i { case 0: return &v.state @@ -941,7 +1062,7 @@ func file_admin_proto_init() { return nil } } - file_admin_proto_msgTypes[6].Exporter = func(v any, i int) any { + file_admin_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Empty); i { case 0: return &v.state @@ -953,7 +1074,7 @@ func file_admin_proto_init() { return nil } } - file_admin_proto_msgTypes[7].Exporter = func(v any, i int) any { + file_admin_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*QueryListItem); i { case 0: return &v.state @@ -965,7 +1086,7 @@ func file_admin_proto_init() { return nil } } - file_admin_proto_msgTypes[8].Exporter = func(v any, i int) any { + file_admin_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*QueryListResponse); i { case 0: return &v.state @@ -977,7 +1098,7 @@ func file_admin_proto_init() { return nil } } - file_admin_proto_msgTypes[9].Exporter = func(v any, i int) any { + file_admin_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*WatchItem); i { case 0: return &v.state @@ -989,9 +1110,33 @@ func file_admin_proto_init() { return nil } } + file_admin_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*LocaleRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_admin_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*TimezoneRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } } - file_admin_proto_msgTypes[4].OneofWrappers = []any{} - file_admin_proto_msgTypes[9].OneofWrappers = []any{ + file_admin_proto_msgTypes[4].OneofWrappers = []interface{}{} + file_admin_proto_msgTypes[9].OneofWrappers = []interface{}{ (*WatchItem_Initial)(nil), (*WatchItem_Added)(nil), (*WatchItem_Updated)(nil), @@ -1003,7 +1148,7 @@ func file_admin_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_admin_proto_rawDesc, NumEnums: 0, - NumMessages: 10, + NumMessages: 12, NumExtensions: 0, NumServices: 1, }, diff --git a/api/admin/admin.proto b/api/admin/admin.proto index b371dc5..035ad6a 100644 --- a/api/admin/admin.proto +++ b/api/admin/admin.proto @@ -28,7 +28,8 @@ message RegistryRequest { } message RegistryResponse { - string CmdStatus = 1; + string Timezone = 1; + string Locale = 2; } message ApplicationRequest { @@ -65,12 +66,22 @@ message WatchItem { } } +message LocaleRequest { + string Locale = 1; +} + +message TimezoneRequest { + string Timezone = 1; +} + service AdminService { rpc RegisterService(RegistryRequest) returns (RegistryResponse) {} rpc StartApplication(ApplicationRequest) returns (ApplicationResponse) {} rpc PauseApplication(ApplicationRequest) returns (ApplicationResponse) {} rpc ResumeApplication(ApplicationRequest) returns (ApplicationResponse) {} rpc StopApplication(ApplicationRequest) returns (ApplicationResponse) {} + rpc SetLocale(LocaleRequest) returns (Empty) {} + rpc SetTimezone(TimezoneRequest) returns (Empty) {} rpc Poweroff(Empty) returns (Empty) {} rpc Reboot(Empty) returns (Empty) {} rpc Suspend(Empty) returns (Empty) {} diff --git a/api/admin/admin_grpc.pb.go b/api/admin/admin_grpc.pb.go index dc85519..a37c0ff 100644 --- a/api/admin/admin_grpc.pb.go +++ b/api/admin/admin_grpc.pb.go @@ -4,7 +4,7 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. // versions: // - protoc-gen-go-grpc v1.3.0 -// - protoc v4.25.4 +// - protoc v4.24.4 // source: admin.proto package admin @@ -27,6 +27,8 @@ const ( AdminService_PauseApplication_FullMethodName = "/admin.AdminService/PauseApplication" AdminService_ResumeApplication_FullMethodName = "/admin.AdminService/ResumeApplication" AdminService_StopApplication_FullMethodName = "/admin.AdminService/StopApplication" + AdminService_SetLocale_FullMethodName = "/admin.AdminService/SetLocale" + AdminService_SetTimezone_FullMethodName = "/admin.AdminService/SetTimezone" AdminService_Poweroff_FullMethodName = "/admin.AdminService/Poweroff" AdminService_Reboot_FullMethodName = "/admin.AdminService/Reboot" AdminService_Suspend_FullMethodName = "/admin.AdminService/Suspend" @@ -44,6 +46,8 @@ type AdminServiceClient interface { PauseApplication(ctx context.Context, in *ApplicationRequest, opts ...grpc.CallOption) (*ApplicationResponse, error) ResumeApplication(ctx context.Context, in *ApplicationRequest, opts ...grpc.CallOption) (*ApplicationResponse, error) StopApplication(ctx context.Context, in *ApplicationRequest, opts ...grpc.CallOption) (*ApplicationResponse, error) + SetLocale(ctx context.Context, in *LocaleRequest, opts ...grpc.CallOption) (*Empty, error) + SetTimezone(ctx context.Context, in *TimezoneRequest, opts ...grpc.CallOption) (*Empty, error) Poweroff(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*Empty, error) Reboot(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*Empty, error) Suspend(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*Empty, error) @@ -105,6 +109,24 @@ func (c *adminServiceClient) StopApplication(ctx context.Context, in *Applicatio return out, nil } +func (c *adminServiceClient) SetLocale(ctx context.Context, in *LocaleRequest, opts ...grpc.CallOption) (*Empty, error) { + out := new(Empty) + err := c.cc.Invoke(ctx, AdminService_SetLocale_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *adminServiceClient) SetTimezone(ctx context.Context, in *TimezoneRequest, opts ...grpc.CallOption) (*Empty, error) { + out := new(Empty) + err := c.cc.Invoke(ctx, AdminService_SetTimezone_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *adminServiceClient) Poweroff(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*Empty, error) { out := new(Empty) err := c.cc.Invoke(ctx, AdminService_Poweroff_FullMethodName, in, out, opts...) @@ -191,6 +213,8 @@ type AdminServiceServer interface { PauseApplication(context.Context, *ApplicationRequest) (*ApplicationResponse, error) ResumeApplication(context.Context, *ApplicationRequest) (*ApplicationResponse, error) StopApplication(context.Context, *ApplicationRequest) (*ApplicationResponse, error) + SetLocale(context.Context, *LocaleRequest) (*Empty, error) + SetTimezone(context.Context, *TimezoneRequest) (*Empty, error) Poweroff(context.Context, *Empty) (*Empty, error) Reboot(context.Context, *Empty) (*Empty, error) Suspend(context.Context, *Empty) (*Empty, error) @@ -219,6 +243,12 @@ func (UnimplementedAdminServiceServer) ResumeApplication(context.Context, *Appli func (UnimplementedAdminServiceServer) StopApplication(context.Context, *ApplicationRequest) (*ApplicationResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method StopApplication not implemented") } +func (UnimplementedAdminServiceServer) SetLocale(context.Context, *LocaleRequest) (*Empty, error) { + return nil, status.Errorf(codes.Unimplemented, "method SetLocale not implemented") +} +func (UnimplementedAdminServiceServer) SetTimezone(context.Context, *TimezoneRequest) (*Empty, error) { + return nil, status.Errorf(codes.Unimplemented, "method SetTimezone not implemented") +} func (UnimplementedAdminServiceServer) Poweroff(context.Context, *Empty) (*Empty, error) { return nil, status.Errorf(codes.Unimplemented, "method Poweroff not implemented") } @@ -340,6 +370,42 @@ func _AdminService_StopApplication_Handler(srv interface{}, ctx context.Context, return interceptor(ctx, in, info, handler) } +func _AdminService_SetLocale_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(LocaleRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(AdminServiceServer).SetLocale(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: AdminService_SetLocale_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(AdminServiceServer).SetLocale(ctx, req.(*LocaleRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _AdminService_SetTimezone_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(TimezoneRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(AdminServiceServer).SetTimezone(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: AdminService_SetTimezone_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(AdminServiceServer).SetTimezone(ctx, req.(*TimezoneRequest)) + } + return interceptor(ctx, in, info, handler) +} + func _AdminService_Poweroff_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(Empty) if err := dec(in); err != nil { @@ -478,6 +544,14 @@ var AdminService_ServiceDesc = grpc.ServiceDesc{ MethodName: "StopApplication", Handler: _AdminService_StopApplication_Handler, }, + { + MethodName: "SetLocale", + Handler: _AdminService_SetLocale_Handler, + }, + { + MethodName: "SetTimezone", + Handler: _AdminService_SetTimezone_Handler, + }, { MethodName: "Poweroff", Handler: _AdminService_Poweroff_Handler, diff --git a/api/hwid/hwid.pb.go b/api/hwid/hwid.pb.go index db38367..ac069c8 100644 --- a/api/hwid/hwid.pb.go +++ b/api/hwid/hwid.pb.go @@ -3,8 +3,8 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.34.2 -// protoc v4.25.4 +// protoc-gen-go v1.34.1 +// protoc v4.24.4 // source: hwid.proto package hwid @@ -137,7 +137,7 @@ func file_hwid_proto_rawDescGZIP() []byte { } var file_hwid_proto_msgTypes = make([]protoimpl.MessageInfo, 2) -var file_hwid_proto_goTypes = []any{ +var file_hwid_proto_goTypes = []interface{}{ (*HwIdRequest)(nil), // 0: hwid.HwIdRequest (*HwIdResponse)(nil), // 1: hwid.HwIdResponse } @@ -157,7 +157,7 @@ func file_hwid_proto_init() { return } if !protoimpl.UnsafeEnabled { - file_hwid_proto_msgTypes[0].Exporter = func(v any, i int) any { + file_hwid_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*HwIdRequest); i { case 0: return &v.state @@ -169,7 +169,7 @@ func file_hwid_proto_init() { return nil } } - file_hwid_proto_msgTypes[1].Exporter = func(v any, i int) any { + file_hwid_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*HwIdResponse); i { case 0: return &v.state diff --git a/api/hwid/hwid_grpc.pb.go b/api/hwid/hwid_grpc.pb.go index 68b84e4..d3099a5 100644 --- a/api/hwid/hwid_grpc.pb.go +++ b/api/hwid/hwid_grpc.pb.go @@ -4,7 +4,7 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. // versions: // - protoc-gen-go-grpc v1.3.0 -// - protoc v4.25.4 +// - protoc v4.24.4 // source: hwid.proto package hwid diff --git a/api/systemd/systemd.pb.go b/api/systemd/systemd.pb.go index f35c87b..e606890 100644 --- a/api/systemd/systemd.pb.go +++ b/api/systemd/systemd.pb.go @@ -3,8 +3,8 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.34.2 -// protoc v4.25.4 +// protoc-gen-go v1.34.1 +// protoc v4.24.4 // source: systemd.proto package systemd @@ -507,7 +507,7 @@ func file_systemd_proto_rawDescGZIP() []byte { } var file_systemd_proto_msgTypes = make([]protoimpl.MessageInfo, 7) -var file_systemd_proto_goTypes = []any{ +var file_systemd_proto_goTypes = []interface{}{ (*UnitRequest)(nil), // 0: systemd.UnitRequest (*UnitResponse)(nil), // 1: systemd.UnitResponse (*AppUnitRequest)(nil), // 2: systemd.AppUnitRequest @@ -547,7 +547,7 @@ func file_systemd_proto_init() { return } if !protoimpl.UnsafeEnabled { - file_systemd_proto_msgTypes[0].Exporter = func(v any, i int) any { + file_systemd_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*UnitRequest); i { case 0: return &v.state @@ -559,7 +559,7 @@ func file_systemd_proto_init() { return nil } } - file_systemd_proto_msgTypes[1].Exporter = func(v any, i int) any { + file_systemd_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*UnitResponse); i { case 0: return &v.state @@ -571,7 +571,7 @@ func file_systemd_proto_init() { return nil } } - file_systemd_proto_msgTypes[2].Exporter = func(v any, i int) any { + file_systemd_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*AppUnitRequest); i { case 0: return &v.state @@ -583,7 +583,7 @@ func file_systemd_proto_init() { return nil } } - file_systemd_proto_msgTypes[3].Exporter = func(v any, i int) any { + file_systemd_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*UnitStatus); i { case 0: return &v.state @@ -595,7 +595,7 @@ func file_systemd_proto_init() { return nil } } - file_systemd_proto_msgTypes[4].Exporter = func(v any, i int) any { + file_systemd_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*UnitStatusResponse); i { case 0: return &v.state @@ -607,7 +607,7 @@ func file_systemd_proto_init() { return nil } } - file_systemd_proto_msgTypes[5].Exporter = func(v any, i int) any { + file_systemd_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*UnitResourceRequest); i { case 0: return &v.state @@ -619,7 +619,7 @@ func file_systemd_proto_init() { return nil } } - file_systemd_proto_msgTypes[6].Exporter = func(v any, i int) any { + file_systemd_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*UnitResourceResponse); i { case 0: return &v.state diff --git a/api/systemd/systemd_grpc.pb.go b/api/systemd/systemd_grpc.pb.go index 60fea3f..ef30f63 100644 --- a/api/systemd/systemd_grpc.pb.go +++ b/api/systemd/systemd_grpc.pb.go @@ -4,7 +4,7 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. // versions: // - protoc-gen-go-grpc v1.3.0 -// - protoc v4.25.4 +// - protoc v4.24.4 // source: systemd.proto package systemd diff --git a/api/wifi/wifi.pb.go b/api/wifi/wifi.pb.go index 84dd9bd..849bd34 100644 --- a/api/wifi/wifi.pb.go +++ b/api/wifi/wifi.pb.go @@ -3,8 +3,8 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.34.2 -// protoc v4.25.4 +// protoc-gen-go v1.34.1 +// protoc v4.24.4 // source: wifi.proto package wifi @@ -416,7 +416,7 @@ func file_wifi_proto_rawDescGZIP() []byte { } var file_wifi_proto_msgTypes = make([]protoimpl.MessageInfo, 6) -var file_wifi_proto_goTypes = []any{ +var file_wifi_proto_goTypes = []interface{}{ (*EmptyRequest)(nil), // 0: wifimanager.EmptyRequest (*WifiNetworkRequest)(nil), // 1: wifimanager.WifiNetworkRequest (*WifiConnectionRequest)(nil), // 2: wifimanager.WifiConnectionRequest @@ -451,7 +451,7 @@ func file_wifi_proto_init() { return } if !protoimpl.UnsafeEnabled { - file_wifi_proto_msgTypes[0].Exporter = func(v any, i int) any { + file_wifi_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*EmptyRequest); i { case 0: return &v.state @@ -463,7 +463,7 @@ func file_wifi_proto_init() { return nil } } - file_wifi_proto_msgTypes[1].Exporter = func(v any, i int) any { + file_wifi_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*WifiNetworkRequest); i { case 0: return &v.state @@ -475,7 +475,7 @@ func file_wifi_proto_init() { return nil } } - file_wifi_proto_msgTypes[2].Exporter = func(v any, i int) any { + file_wifi_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*WifiConnectionRequest); i { case 0: return &v.state @@ -487,7 +487,7 @@ func file_wifi_proto_init() { return nil } } - file_wifi_proto_msgTypes[3].Exporter = func(v any, i int) any { + file_wifi_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*AccessPoint); i { case 0: return &v.state @@ -499,7 +499,7 @@ func file_wifi_proto_init() { return nil } } - file_wifi_proto_msgTypes[4].Exporter = func(v any, i int) any { + file_wifi_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*WifiNetworkResponse); i { case 0: return &v.state @@ -511,7 +511,7 @@ func file_wifi_proto_init() { return nil } } - file_wifi_proto_msgTypes[5].Exporter = func(v any, i int) any { + file_wifi_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*WifiConnectionResponse); i { case 0: return &v.state diff --git a/api/wifi/wifi_grpc.pb.go b/api/wifi/wifi_grpc.pb.go index 6cbaf0a..6656cfb 100644 --- a/api/wifi/wifi_grpc.pb.go +++ b/api/wifi/wifi_grpc.pb.go @@ -4,7 +4,7 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. // versions: // - protoc-gen-go-grpc v1.3.0 -// - protoc v4.25.4 +// - protoc v4.24.4 // source: wifi.proto package wifi diff --git a/client/src/client.rs b/client/src/client.rs index 90a697b..7a44d86 100644 --- a/client/src/client.rs +++ b/client/src/client.rs @@ -63,17 +63,22 @@ impl AdminClient { ty: UnitType, endpoint: EndpointEntry, status: UnitStatus, - ) -> anyhow::Result { + ) -> anyhow::Result<(String, String)> { // Convert everything into wire format let request = pb::admin::RegistryRequest { - name: name, + name, parent: "".to_owned(), r#type: ty.into(), transport: Some(endpoint.into()), state: Some(status.into()), }; - let response = self.connect_to().await?.register_service(request).await?; - Ok(response.into_inner().cmd_status) + let response = self + .connect_to() + .await? + .register_service(request) + .await? + .into_inner(); + Ok((response.timezone, response.locale)) } pub async fn start( @@ -142,6 +147,22 @@ impl AdminClient { .collect() } + pub async fn set_locale(&self, locale: String) -> anyhow::Result<()> { + self.connect_to() + .await? + .set_locale(pb::admin::LocaleRequest { locale }) + .await?; + Ok(()) + } + + pub async fn set_timezone(&self, timezone: String) -> anyhow::Result<()> { + self.connect_to() + .await? + .set_timezone(pb::admin::TimezoneRequest { timezone }) + .await?; + Ok(()) + } + pub async fn watch(&self) -> anyhow::Result { let (tx, rx) = async_channel::bounded::(10); diff --git a/internal/cmd/givc-agent/main.go b/internal/cmd/givc-agent/main.go index 1477704..beffde0 100644 --- a/internal/cmd/givc-agent/main.go +++ b/internal/cmd/givc-agent/main.go @@ -6,6 +6,7 @@ import ( "context" "crypto/tls" "os" + "os/exec" "path/filepath" "strconv" "strings" @@ -176,9 +177,29 @@ func main() { <-serverStarted // Register agent - _, err := serviceclient.RegisterRemoteService(cfgAdminServer, agentEntryRequest) + response, err := serviceclient.RegisterRemoteService(cfgAdminServer, agentEntryRequest) if err != nil { log.Fatalf("Error register agent: %s", err) + } else { + if response.Locale != "" { + if err := exec.Command("localectl", "set-locale", response.Locale).Run(); err != nil { + log.Warningf("Failed to set locale: %s", err) + } + if givc_util.IsRoot() { + if err := exec.Command("systemctl", "set-environment", "LANG="+response.Locale).Run(); err != nil { + log.Warningf("Failed to set environment: %s", err) + } + } else { + if err := exec.Command("systemctl", "--user", "set-environment", "LANG="+response.Locale).Run(); err != nil { + log.Warningf("Failed to set environment: %s", err) + } + } + } + if response.Timezone != "" { + if err := exec.Command("timedatectl", "set-timezone", response.Timezone).Run(); err != nil { + log.Warningf("Failed to set timezone: %s", err) + } + } } // Register services diff --git a/nixos/modules/appvm.nix b/nixos/modules/appvm.nix index 062bb67..d6d851f 100644 --- a/nixos/modules/appvm.nix +++ b/nixos/modules/appvm.nix @@ -175,6 +175,21 @@ in } ]; + security.polkit = { + enable = true; + extraConfig = '' + polkit.addRule(function(action, subject) { + if (action.id == "org.freedesktop.locale1.set-locale" && subject.user == "ghaf") { + return polkit.Result.YES; + } + }); + polkit.addRule(function(action, subject) { + if (action.id == "org.freedesktop.timedate1.set-timezone" && subject.user == "ghaf") { + return polkit.Result.YES; + } + }); + ''; + }; systemd.user.services."givc-${cfg.name}" = { description = "GIVC remote service manager for application VMs."; enable = true; diff --git a/src/admin/server.rs b/src/admin/server.rs index 6ebae05..9ea4286 100644 --- a/src/admin/server.rs +++ b/src/admin/server.rs @@ -6,6 +6,7 @@ use givc_common::query::Event; use std::pin::Pin; use std::sync::Arc; use std::time::Duration; +use tokio::sync::Mutex; use tonic::{Code, Response, Status}; use tracing::{debug, error, info}; @@ -20,6 +21,8 @@ use givc_client::endpoint::{EndpointConfig, TlsConfig}; use givc_common::query::*; const VM_STARTUP_TIME: Duration = Duration::new(10, 0); +const TIMEZONE_CONF: &str = "/etc/timezone.conf"; +const LOCALE_CONF: &str = "/etc/locale-givc.conf"; // FIXME: this is almost copy of sysfsm::Event. #[derive(Copy, Clone, Debug, PartialEq)] @@ -35,6 +38,8 @@ pub struct AdminServiceImpl { registry: Registry, state: State, // FIXME: use sysfsm statemachine tls_config: Option, + locale: Mutex, + timezone: Mutex, } #[derive(Debug, Clone)] @@ -49,16 +54,31 @@ impl AdminService { tokio::task::spawn(async move { clone.monitor().await; }); - Self { inner: inner } + Self { inner } } } impl AdminServiceImpl { pub fn new(use_tls: Option) -> Self { + let timezone = std::fs::read_to_string(TIMEZONE_CONF) + .ok() + .and_then(|l| l.lines().next().map(ToOwned::to_owned)) + .unwrap_or_default(); + let locale = std::fs::read_to_string(LOCALE_CONF) + .ok() + .and_then(|l| { + l.lines() + .filter_map(|l| l.strip_prefix("LANG=")) + .next() + .map(ToOwned::to_owned) + }) + .unwrap_or_default(); Self { registry: Registry::new(), state: State::Init, tls_config: use_tls, + timezone: Mutex::new(timezone), + locale: Mutex::new(locale), } } @@ -300,13 +320,16 @@ impl pb::admin_service_server::AdminService for AdminService { ) -> std::result::Result, tonic::Status> { let req = request.into_inner(); + info!("Registering service {:?}", req); let entry = RegistryEntry::try_from(req) .map_err(|e| Status::new(Code::InvalidArgument, format!("{e}")))?; self.inner.register(entry); let res = RegistryResponse { - cmd_status: String::from("Registration successful"), + timezone: self.inner.timezone.lock().await.clone(), + locale: self.inner.locale.lock().await.clone(), }; + info!("Responding with {res:?}"); Ok(Response::new(res)) } async fn start_application( @@ -430,6 +453,30 @@ impl pb::admin_service_server::AdminService for AdminService { .await } + async fn set_locale( + &self, + request: tonic::Request, + ) -> std::result::Result, tonic::Status> { + escalate(request, |req| async move { + let _ = tokio::fs::write(LOCALE_CONF, format!("LANG={}", req.locale)).await; + *self.inner.locale.lock().await = req.locale; + Ok(Empty {}) + }) + .await + } + + async fn set_timezone( + &self, + request: tonic::Request, + ) -> std::result::Result, tonic::Status> { + escalate(request, |req| async move { + let _ = tokio::fs::write(TIMEZONE_CONF, &req.timezone).await; + *self.inner.timezone.lock().await = req.timezone; + Ok(Empty {}) + }) + .await + } + type WatchStream = Stream; async fn watch( &self, diff --git a/src/bin/givc-agent.rs b/src/bin/givc-agent.rs index 1b565f7..5cc08a6 100644 --- a/src/bin/givc-agent.rs +++ b/src/bin/givc-agent.rs @@ -8,6 +8,7 @@ use givc_common::pb; use givc_common::pb::reflection::SYSTEMD_DESCRIPTOR; use std::net::SocketAddr; use std::path::PathBuf; +use std::process::{Command, Stdio}; use tonic::transport::Server; use tracing::info; @@ -105,10 +106,27 @@ async fn main() -> std::result::Result<(), Box> { let admin_tls = tls.clone().map(|tls| (cli.admin_server_name, tls)); let admin = AdminClient::new(cli.admin_server_addr, cli.admin_server_port, admin_tls); - admin + let (timezone, locale) = admin .register_service(agent_service_name, cli.r#type.try_into()?, endpoint, status) .await?; + if !timezone.is_empty() { + Command::new("timedatectl") + .args(["set-timezone", timezone.as_str()]) + .stdin(Stdio::null()) + .stdout(Stdio::null()) + .stderr(Stdio::null()) + .spawn()?; + } + if !locale.is_empty() { + Command::new("localectl") + .args(["set-locale", locale.as_str()]) + .stdin(Stdio::null()) + .stdout(Stdio::null()) + .stderr(Stdio::null()) + .spawn()?; + } + let reflect = tonic_reflection::server::Builder::configure() .register_encoded_file_descriptor_set(SYSTEMD_DESCRIPTOR) .build() diff --git a/src/bin/givc-cli.rs b/src/bin/givc-cli.rs index 9851259..aca6e65 100644 --- a/src/bin/givc-cli.rs +++ b/src/bin/givc-cli.rs @@ -74,6 +74,12 @@ enum Commands { #[arg(long, default_value_t = false)] as_json: bool, }, + SetLocale { + locale: String, + }, + SetTimezone { + timezone: String, + }, Watch { #[arg(long, default_value_t = false)] as_json: bool, @@ -161,6 +167,14 @@ async fn main() -> std::result::Result<(), Box> { let reply = admin.query_list().await?; dump(&reply, as_json)? } + + Commands::SetLocale { locale } => { + admin.set_locale(locale).await?; + } + + Commands::SetTimezone { timezone } => { + admin.set_timezone(timezone).await?; + } Commands::Watch { as_json, limit,