From 626df8941d41e3bb146b2822f127ac0c03951955 Mon Sep 17 00:00:00 2001 From: Manuel Bluhm Date: Tue, 17 Sep 2024 19:50:01 +0400 Subject: [PATCH] Refine application processing - add application arguments to protobuffer - add automatic nix to JSON conversion for application definition - add argument processing to agent: - parsing application manifest - validate extra arguments - add extra (optional) arguments to givc-cli - add admin server args forwarding - remove obsolete application start function from go implementation - update nixpkgs - update go + deps Signed-off-by: Manuel Bluhm --- README.md | 15 +- api/admin/admin.pb.go | 479 +++++++++++++++--- api/admin/admin.proto | 3 +- api/admin/admin_grpc.pb.go | 106 +++- api/hwid/hwid.pb.go | 10 +- api/hwid/hwid_grpc.pb.go | 2 +- api/protoc.sh | 1 + api/systemd/systemd.pb.go | 250 +++++---- api/systemd/systemd.proto | 7 +- api/systemd/systemd_grpc.pb.go | 14 +- api/wifi/wifi.pb.go | 2 +- api/wifi/wifi_grpc.pb.go | 2 +- client/src/client.rs | 13 +- flake.lock | 6 +- go.mod | 12 +- go.sum | 25 +- internal/cmd/givc-agent/main.go | 13 +- internal/pkgs/applications/applications.go | 160 ++++++ .../pkgs/applications/applications_test.go | 360 +++++++++++++ internal/pkgs/serviceclient/transport.go | 33 -- internal/pkgs/servicemanager/controller.go | 29 +- internal/pkgs/servicemanager/transport.go | 9 +- internal/pkgs/types/types.go | 11 + internal/pkgs/utility/utility.go | 9 + nixos/modules/appvm.nix | 90 ++-- nixos/packages/givc-agent.nix | 5 +- nixos/tests/admin.nix | 14 +- src/admin/server.rs | 2 +- src/bin/givc-cli.rs | 6 +- src/systemd_api/client.rs | 11 +- src/systemd_api/server.rs | 2 +- 31 files changed, 1397 insertions(+), 304 deletions(-) create mode 100644 internal/pkgs/applications/applications.go create mode 100644 internal/pkgs/applications/applications_test.go diff --git a/README.md b/README.md index 5df53ff..3d46a44 100644 --- a/README.md +++ b/README.md @@ -17,8 +17,7 @@ This project was started to support the development of system modules across a v ### Systemd Management Agent -The systemd management agent runs in the host and VMs, and connects to the systemd manager of the system. It provides functionality to control services in host, system VMs, and application VMs. The agent can connect to the system manager to control system units, or -to the user manager to control applications running as transient systemd services. +The systemd management agent runs in the host and VMs, and connects to the systemd manager of the system. It provides functionality to control services in host, system VMs, and application VMs. The agent can connect to the system manager to control system units, or to the user manager to control applications running as transient systemd services. ### Admin Service (System Manager) @@ -137,10 +136,14 @@ To use the agent as application controller, include the `appvm` module as follow addr = "192.168.1.123"; port = "9000"; - # Specify applications with "name":"command" (JSON) - applications = ''{ - "appflowy": "run-waypipe appflowy" - }''; + # Specify applications by name, command, and argument types accepted + applications = [ + { + name = "foot"; + command = "${pkgs.foot}/bin/foot"; + args = [ "flag" ]; + } + ]; # Provide TLS configuration files tls = { diff --git a/api/admin/admin.pb.go b/api/admin/admin.pb.go index 28a12aa..bc873b8 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.1 -// protoc v4.24.4 +// protoc-gen-go v1.34.2 +// protoc v4.25.4 // source: admin.proto package admin @@ -304,7 +304,9 @@ type ApplicationRequest struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - AppName string `protobuf:"bytes,1,opt,name=AppName,proto3" json:"AppName,omitempty"` + AppName string `protobuf:"bytes,1,opt,name=AppName,proto3" json:"AppName,omitempty"` + VmName *string `protobuf:"bytes,2,opt,name=VmName,proto3,oneof" json:"VmName,omitempty"` + Args []string `protobuf:"bytes,3,rep,name=Args,proto3" json:"Args,omitempty"` } func (x *ApplicationRequest) Reset() { @@ -346,6 +348,20 @@ func (x *ApplicationRequest) GetAppName() string { return "" } +func (x *ApplicationRequest) GetVmName() string { + if x != nil && x.VmName != nil { + return *x.VmName + } + return "" +} + +func (x *ApplicationRequest) GetArgs() []string { + if x != nil { + return x.Args + } + return nil +} + type ApplicationResponse struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -439,6 +455,233 @@ func (*Empty) Descriptor() ([]byte, []int) { return file_admin_proto_rawDescGZIP(), []int{6} } +type QueryListItem struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Name string `protobuf:"bytes,1,opt,name=Name,proto3" json:"Name,omitempty"` + Description string `protobuf:"bytes,2,opt,name=Description,proto3" json:"Description,omitempty"` + VmStatus string `protobuf:"bytes,3,opt,name=VmStatus,proto3" json:"VmStatus,omitempty"` + TrustLevel string `protobuf:"bytes,4,opt,name=TrustLevel,proto3" json:"TrustLevel,omitempty"` +} + +func (x *QueryListItem) Reset() { + *x = QueryListItem{} + if protoimpl.UnsafeEnabled { + mi := &file_admin_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *QueryListItem) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*QueryListItem) ProtoMessage() {} + +func (x *QueryListItem) ProtoReflect() protoreflect.Message { + mi := &file_admin_proto_msgTypes[7] + 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 QueryListItem.ProtoReflect.Descriptor instead. +func (*QueryListItem) Descriptor() ([]byte, []int) { + return file_admin_proto_rawDescGZIP(), []int{7} +} + +func (x *QueryListItem) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *QueryListItem) GetDescription() string { + if x != nil { + return x.Description + } + return "" +} + +func (x *QueryListItem) GetVmStatus() string { + if x != nil { + return x.VmStatus + } + return "" +} + +func (x *QueryListItem) GetTrustLevel() string { + if x != nil { + return x.TrustLevel + } + return "" +} + +type QueryListResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + List []*QueryListItem `protobuf:"bytes,1,rep,name=List,proto3" json:"List,omitempty"` +} + +func (x *QueryListResponse) Reset() { + *x = QueryListResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_admin_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *QueryListResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*QueryListResponse) ProtoMessage() {} + +func (x *QueryListResponse) ProtoReflect() protoreflect.Message { + mi := &file_admin_proto_msgTypes[8] + 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 QueryListResponse.ProtoReflect.Descriptor instead. +func (*QueryListResponse) Descriptor() ([]byte, []int) { + return file_admin_proto_rawDescGZIP(), []int{8} +} + +func (x *QueryListResponse) GetList() []*QueryListItem { + if x != nil { + return x.List + } + return nil +} + +type WatchItem struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Types that are assignable to Status: + // + // *WatchItem_Initial + // *WatchItem_Added + // *WatchItem_Updated + // *WatchItem_Removed + Status isWatchItem_Status `protobuf_oneof:"Status"` +} + +func (x *WatchItem) Reset() { + *x = WatchItem{} + if protoimpl.UnsafeEnabled { + mi := &file_admin_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *WatchItem) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*WatchItem) ProtoMessage() {} + +func (x *WatchItem) ProtoReflect() protoreflect.Message { + mi := &file_admin_proto_msgTypes[9] + 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 WatchItem.ProtoReflect.Descriptor instead. +func (*WatchItem) Descriptor() ([]byte, []int) { + return file_admin_proto_rawDescGZIP(), []int{9} +} + +func (m *WatchItem) GetStatus() isWatchItem_Status { + if m != nil { + return m.Status + } + return nil +} + +func (x *WatchItem) GetInitial() *QueryListResponse { + if x, ok := x.GetStatus().(*WatchItem_Initial); ok { + return x.Initial + } + return nil +} + +func (x *WatchItem) GetAdded() *QueryListItem { + if x, ok := x.GetStatus().(*WatchItem_Added); ok { + return x.Added + } + return nil +} + +func (x *WatchItem) GetUpdated() *QueryListItem { + if x, ok := x.GetStatus().(*WatchItem_Updated); ok { + return x.Updated + } + return nil +} + +func (x *WatchItem) GetRemoved() *QueryListItem { + if x, ok := x.GetStatus().(*WatchItem_Removed); ok { + return x.Removed + } + return nil +} + +type isWatchItem_Status interface { + isWatchItem_Status() +} + +type WatchItem_Initial struct { + Initial *QueryListResponse `protobuf:"bytes,1,opt,name=Initial,proto3,oneof"` +} + +type WatchItem_Added struct { + Added *QueryListItem `protobuf:"bytes,2,opt,name=Added,proto3,oneof"` +} + +type WatchItem_Updated struct { + Updated *QueryListItem `protobuf:"bytes,3,opt,name=Updated,proto3,oneof"` +} + +type WatchItem_Removed struct { + Removed *QueryListItem `protobuf:"bytes,4,opt,name=Removed,proto3,oneof"` +} + +func (*WatchItem_Initial) isWatchItem_Status() {} + +func (*WatchItem_Added) isWatchItem_Status() {} + +func (*WatchItem_Updated) isWatchItem_Status() {} + +func (*WatchItem_Removed) isWatchItem_Status() {} + var File_admin_proto protoreflect.FileDescriptor var file_admin_proto_rawDesc = []byte{ @@ -474,46 +717,83 @@ var file_admin_proto_rawDesc = []byte{ 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, 0x2e, 0x0a, 0x12, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, + 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, 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, 0x32, - 0xda, 0x03, 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, 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, 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, 0x42, 0x09, 0x5a, 0x07, - 0x2e, 0x2f, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 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, 0xbe, + 0x04, 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, + 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, + 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 ( @@ -528,8 +808,8 @@ func file_admin_proto_rawDescGZIP() []byte { return file_admin_proto_rawDescData } -var file_admin_proto_msgTypes = make([]protoimpl.MessageInfo, 7) -var file_admin_proto_goTypes = []interface{}{ +var file_admin_proto_msgTypes = make([]protoimpl.MessageInfo, 10) +var file_admin_proto_goTypes = []any{ (*UnitStatus)(nil), // 0: admin.UnitStatus (*TransportConfig)(nil), // 1: admin.TransportConfig (*RegistryRequest)(nil), // 2: admin.RegistryRequest @@ -537,29 +817,41 @@ var file_admin_proto_goTypes = []interface{}{ (*ApplicationRequest)(nil), // 4: admin.ApplicationRequest (*ApplicationResponse)(nil), // 5: admin.ApplicationResponse (*Empty)(nil), // 6: admin.Empty + (*QueryListItem)(nil), // 7: admin.QueryListItem + (*QueryListResponse)(nil), // 8: admin.QueryListResponse + (*WatchItem)(nil), // 9: admin.WatchItem } var file_admin_proto_depIdxs = []int32{ - 1, // 0: admin.RegistryRequest.Transport:type_name -> admin.TransportConfig - 0, // 1: admin.RegistryRequest.State:type_name -> admin.UnitStatus - 2, // 2: admin.AdminService.RegisterService:input_type -> admin.RegistryRequest - 4, // 3: admin.AdminService.StartApplication:input_type -> admin.ApplicationRequest - 4, // 4: admin.AdminService.PauseApplication:input_type -> admin.ApplicationRequest - 4, // 5: admin.AdminService.ResumeApplication:input_type -> admin.ApplicationRequest - 4, // 6: admin.AdminService.StopApplication:input_type -> admin.ApplicationRequest - 6, // 7: admin.AdminService.Poweroff:input_type -> admin.Empty - 6, // 8: admin.AdminService.Reboot:input_type -> admin.Empty - 3, // 9: admin.AdminService.RegisterService:output_type -> admin.RegistryResponse - 5, // 10: admin.AdminService.StartApplication:output_type -> admin.ApplicationResponse - 5, // 11: admin.AdminService.PauseApplication:output_type -> admin.ApplicationResponse - 5, // 12: admin.AdminService.ResumeApplication:output_type -> admin.ApplicationResponse - 5, // 13: admin.AdminService.StopApplication:output_type -> admin.ApplicationResponse - 6, // 14: admin.AdminService.Poweroff:output_type -> admin.Empty - 6, // 15: admin.AdminService.Reboot:output_type -> admin.Empty - 9, // [9:16] is the sub-list for method output_type - 2, // [2:9] is the sub-list for method input_type - 2, // [2:2] is the sub-list for extension type_name - 2, // [2:2] is the sub-list for extension extendee - 0, // [0:2] is the sub-list for field type_name + 1, // 0: admin.RegistryRequest.Transport:type_name -> admin.TransportConfig + 0, // 1: admin.RegistryRequest.State:type_name -> admin.UnitStatus + 7, // 2: admin.QueryListResponse.List:type_name -> admin.QueryListItem + 8, // 3: admin.WatchItem.Initial:type_name -> admin.QueryListResponse + 7, // 4: admin.WatchItem.Added:type_name -> admin.QueryListItem + 7, // 5: admin.WatchItem.Updated:type_name -> admin.QueryListItem + 7, // 6: admin.WatchItem.Removed:type_name -> admin.QueryListItem + 2, // 7: admin.AdminService.RegisterService:input_type -> admin.RegistryRequest + 4, // 8: admin.AdminService.StartApplication:input_type -> admin.ApplicationRequest + 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.QueryList:input_type -> admin.Empty + 6, // 15: admin.AdminService.Watch:input_type -> admin.Empty + 3, // 16: admin.AdminService.RegisterService:output_type -> admin.RegistryResponse + 5, // 17: admin.AdminService.StartApplication:output_type -> admin.ApplicationResponse + 5, // 18: admin.AdminService.PauseApplication:output_type -> admin.ApplicationResponse + 5, // 19: admin.AdminService.ResumeApplication:output_type -> admin.ApplicationResponse + 5, // 20: admin.AdminService.StopApplication:output_type -> admin.ApplicationResponse + 6, // 21: admin.AdminService.Poweroff:output_type -> admin.Empty + 6, // 22: admin.AdminService.Reboot:output_type -> admin.Empty + 8, // 23: admin.AdminService.QueryList:output_type -> admin.QueryListResponse + 9, // 24: admin.AdminService.Watch:output_type -> admin.WatchItem + 16, // [16:25] is the sub-list for method output_type + 7, // [7:16] 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 } func init() { file_admin_proto_init() } @@ -568,7 +860,7 @@ func file_admin_proto_init() { return } if !protoimpl.UnsafeEnabled { - file_admin_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + file_admin_proto_msgTypes[0].Exporter = func(v any, i int) any { switch v := v.(*UnitStatus); i { case 0: return &v.state @@ -580,7 +872,7 @@ func file_admin_proto_init() { return nil } } - file_admin_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + file_admin_proto_msgTypes[1].Exporter = func(v any, i int) any { switch v := v.(*TransportConfig); i { case 0: return &v.state @@ -592,7 +884,7 @@ func file_admin_proto_init() { return nil } } - file_admin_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + file_admin_proto_msgTypes[2].Exporter = func(v any, i int) any { switch v := v.(*RegistryRequest); i { case 0: return &v.state @@ -604,7 +896,7 @@ func file_admin_proto_init() { return nil } } - file_admin_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + file_admin_proto_msgTypes[3].Exporter = func(v any, i int) any { switch v := v.(*RegistryResponse); i { case 0: return &v.state @@ -616,7 +908,7 @@ func file_admin_proto_init() { return nil } } - file_admin_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + file_admin_proto_msgTypes[4].Exporter = func(v any, i int) any { switch v := v.(*ApplicationRequest); i { case 0: return &v.state @@ -628,7 +920,7 @@ func file_admin_proto_init() { return nil } } - file_admin_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { + file_admin_proto_msgTypes[5].Exporter = func(v any, i int) any { switch v := v.(*ApplicationResponse); i { case 0: return &v.state @@ -640,7 +932,7 @@ func file_admin_proto_init() { return nil } } - file_admin_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { + file_admin_proto_msgTypes[6].Exporter = func(v any, i int) any { switch v := v.(*Empty); i { case 0: return &v.state @@ -652,6 +944,49 @@ func file_admin_proto_init() { return nil } } + file_admin_proto_msgTypes[7].Exporter = func(v any, i int) any { + switch v := v.(*QueryListItem); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_admin_proto_msgTypes[8].Exporter = func(v any, i int) any { + switch v := v.(*QueryListResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_admin_proto_msgTypes[9].Exporter = func(v any, i int) any { + switch v := v.(*WatchItem); 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{ + (*WatchItem_Initial)(nil), + (*WatchItem_Added)(nil), + (*WatchItem_Updated)(nil), + (*WatchItem_Removed)(nil), } type x struct{} out := protoimpl.TypeBuilder{ @@ -659,7 +994,7 @@ func file_admin_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_admin_proto_rawDesc, NumEnums: 0, - NumMessages: 7, + NumMessages: 10, NumExtensions: 0, NumServices: 1, }, diff --git a/api/admin/admin.proto b/api/admin/admin.proto index 7ad1757..f574456 100644 --- a/api/admin/admin.proto +++ b/api/admin/admin.proto @@ -34,6 +34,7 @@ message RegistryResponse { message ApplicationRequest { string AppName = 1; optional string VmName = 2; + repeated string Args = 3; } message ApplicationResponse { @@ -74,5 +75,5 @@ service AdminService { rpc Reboot(Empty) returns (Empty) {} rpc QueryList(Empty) returns (QueryListResponse) {} - rpc Watch(Empty) returns (stream WatchItem) {} + rpc Watch(Empty) returns (stream WatchItem) {} } diff --git a/api/admin/admin_grpc.pb.go b/api/admin/admin_grpc.pb.go index e9c5444..7a44397 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.24.4 +// - protoc v4.25.4 // source: admin.proto package admin @@ -29,6 +29,8 @@ const ( AdminService_StopApplication_FullMethodName = "/admin.AdminService/StopApplication" AdminService_Poweroff_FullMethodName = "/admin.AdminService/Poweroff" AdminService_Reboot_FullMethodName = "/admin.AdminService/Reboot" + AdminService_QueryList_FullMethodName = "/admin.AdminService/QueryList" + AdminService_Watch_FullMethodName = "/admin.AdminService/Watch" ) // AdminServiceClient is the client API for AdminService service. @@ -42,6 +44,8 @@ type AdminServiceClient interface { StopApplication(ctx context.Context, in *ApplicationRequest, opts ...grpc.CallOption) (*ApplicationResponse, error) Poweroff(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*Empty, error) Reboot(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*Empty, error) + QueryList(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*QueryListResponse, error) + Watch(ctx context.Context, in *Empty, opts ...grpc.CallOption) (AdminService_WatchClient, error) } type adminServiceClient struct { @@ -115,6 +119,47 @@ func (c *adminServiceClient) Reboot(ctx context.Context, in *Empty, opts ...grpc return out, nil } +func (c *adminServiceClient) QueryList(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*QueryListResponse, error) { + out := new(QueryListResponse) + err := c.cc.Invoke(ctx, AdminService_QueryList_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *adminServiceClient) Watch(ctx context.Context, in *Empty, opts ...grpc.CallOption) (AdminService_WatchClient, error) { + stream, err := c.cc.NewStream(ctx, &AdminService_ServiceDesc.Streams[0], AdminService_Watch_FullMethodName, opts...) + if err != nil { + return nil, err + } + x := &adminServiceWatchClient{stream} + if err := x.ClientStream.SendMsg(in); err != nil { + return nil, err + } + if err := x.ClientStream.CloseSend(); err != nil { + return nil, err + } + return x, nil +} + +type AdminService_WatchClient interface { + Recv() (*WatchItem, error) + grpc.ClientStream +} + +type adminServiceWatchClient struct { + grpc.ClientStream +} + +func (x *adminServiceWatchClient) Recv() (*WatchItem, error) { + m := new(WatchItem) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + // AdminServiceServer is the server API for AdminService service. // All implementations must embed UnimplementedAdminServiceServer // for forward compatibility @@ -126,6 +171,8 @@ type AdminServiceServer interface { StopApplication(context.Context, *ApplicationRequest) (*ApplicationResponse, error) Poweroff(context.Context, *Empty) (*Empty, error) Reboot(context.Context, *Empty) (*Empty, error) + QueryList(context.Context, *Empty) (*QueryListResponse, error) + Watch(*Empty, AdminService_WatchServer) error mustEmbedUnimplementedAdminServiceServer() } @@ -154,6 +201,12 @@ func (UnimplementedAdminServiceServer) Poweroff(context.Context, *Empty) (*Empty func (UnimplementedAdminServiceServer) Reboot(context.Context, *Empty) (*Empty, error) { return nil, status.Errorf(codes.Unimplemented, "method Reboot not implemented") } +func (UnimplementedAdminServiceServer) QueryList(context.Context, *Empty) (*QueryListResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method QueryList not implemented") +} +func (UnimplementedAdminServiceServer) Watch(*Empty, AdminService_WatchServer) error { + return status.Errorf(codes.Unimplemented, "method Watch not implemented") +} func (UnimplementedAdminServiceServer) mustEmbedUnimplementedAdminServiceServer() {} // UnsafeAdminServiceServer may be embedded to opt out of forward compatibility for this service. @@ -293,6 +346,45 @@ func _AdminService_Reboot_Handler(srv interface{}, ctx context.Context, dec func return interceptor(ctx, in, info, handler) } +func _AdminService_QueryList_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(Empty) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(AdminServiceServer).QueryList(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: AdminService_QueryList_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(AdminServiceServer).QueryList(ctx, req.(*Empty)) + } + return interceptor(ctx, in, info, handler) +} + +func _AdminService_Watch_Handler(srv interface{}, stream grpc.ServerStream) error { + m := new(Empty) + if err := stream.RecvMsg(m); err != nil { + return err + } + return srv.(AdminServiceServer).Watch(m, &adminServiceWatchServer{stream}) +} + +type AdminService_WatchServer interface { + Send(*WatchItem) error + grpc.ServerStream +} + +type adminServiceWatchServer struct { + grpc.ServerStream +} + +func (x *adminServiceWatchServer) Send(m *WatchItem) error { + return x.ServerStream.SendMsg(m) +} + // AdminService_ServiceDesc is the grpc.ServiceDesc for AdminService service. // It's only intended for direct use with grpc.RegisterService, // and not to be introspected or modified (even as a copy) @@ -328,7 +420,17 @@ var AdminService_ServiceDesc = grpc.ServiceDesc{ MethodName: "Reboot", Handler: _AdminService_Reboot_Handler, }, + { + MethodName: "QueryList", + Handler: _AdminService_QueryList_Handler, + }, + }, + Streams: []grpc.StreamDesc{ + { + StreamName: "Watch", + Handler: _AdminService_Watch_Handler, + ServerStreams: true, + }, }, - Streams: []grpc.StreamDesc{}, Metadata: "admin.proto", } diff --git a/api/hwid/hwid.pb.go b/api/hwid/hwid.pb.go index ac069c8..db38367 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.1 -// protoc v4.24.4 +// protoc-gen-go v1.34.2 +// protoc v4.25.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 = []interface{}{ +var file_hwid_proto_goTypes = []any{ (*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 interface{}, i int) interface{} { + file_hwid_proto_msgTypes[0].Exporter = func(v any, i int) any { 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 interface{}, i int) interface{} { + file_hwid_proto_msgTypes[1].Exporter = func(v any, i int) any { 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 d3099a5..68b84e4 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.24.4 +// - protoc v4.25.4 // source: hwid.proto package hwid diff --git a/api/protoc.sh b/api/protoc.sh index 39a524a..2d2bfa3 100755 --- a/api/protoc.sh +++ b/api/protoc.sh @@ -7,6 +7,7 @@ gen_protoc() { "$1"/"$2" } +gen_protoc api/admin admin.proto gen_protoc api/systemd systemd.proto gen_protoc api/wifi wifi.proto gen_protoc api/hwid hwid.proto diff --git a/api/systemd/systemd.pb.go b/api/systemd/systemd.pb.go index 052aeef..f35c87b 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.1 -// protoc v4.24.4 +// protoc-gen-go v1.34.2 +// protoc v4.25.4 // source: systemd.proto package systemd @@ -117,6 +117,61 @@ func (x *UnitResponse) GetCmdStatus() string { return "" } +type AppUnitRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + UnitName string `protobuf:"bytes,1,opt,name=UnitName,proto3" json:"UnitName,omitempty"` + Args []string `protobuf:"bytes,2,rep,name=Args,proto3" json:"Args,omitempty"` +} + +func (x *AppUnitRequest) Reset() { + *x = AppUnitRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_systemd_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *AppUnitRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AppUnitRequest) ProtoMessage() {} + +func (x *AppUnitRequest) ProtoReflect() protoreflect.Message { + mi := &file_systemd_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use AppUnitRequest.ProtoReflect.Descriptor instead. +func (*AppUnitRequest) Descriptor() ([]byte, []int) { + return file_systemd_proto_rawDescGZIP(), []int{2} +} + +func (x *AppUnitRequest) GetUnitName() string { + if x != nil { + return x.UnitName + } + return "" +} + +func (x *AppUnitRequest) GetArgs() []string { + if x != nil { + return x.Args + } + return nil +} + type UnitStatus struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -133,7 +188,7 @@ type UnitStatus struct { func (x *UnitStatus) Reset() { *x = UnitStatus{} if protoimpl.UnsafeEnabled { - mi := &file_systemd_proto_msgTypes[2] + mi := &file_systemd_proto_msgTypes[3] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -146,7 +201,7 @@ func (x *UnitStatus) String() string { func (*UnitStatus) ProtoMessage() {} func (x *UnitStatus) ProtoReflect() protoreflect.Message { - mi := &file_systemd_proto_msgTypes[2] + mi := &file_systemd_proto_msgTypes[3] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -159,7 +214,7 @@ func (x *UnitStatus) ProtoReflect() protoreflect.Message { // Deprecated: Use UnitStatus.ProtoReflect.Descriptor instead. func (*UnitStatus) Descriptor() ([]byte, []int) { - return file_systemd_proto_rawDescGZIP(), []int{2} + return file_systemd_proto_rawDescGZIP(), []int{3} } func (x *UnitStatus) GetName() string { @@ -216,7 +271,7 @@ type UnitStatusResponse struct { func (x *UnitStatusResponse) Reset() { *x = UnitStatusResponse{} if protoimpl.UnsafeEnabled { - mi := &file_systemd_proto_msgTypes[3] + mi := &file_systemd_proto_msgTypes[4] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -229,7 +284,7 @@ func (x *UnitStatusResponse) String() string { func (*UnitStatusResponse) ProtoMessage() {} func (x *UnitStatusResponse) ProtoReflect() protoreflect.Message { - mi := &file_systemd_proto_msgTypes[3] + mi := &file_systemd_proto_msgTypes[4] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -242,7 +297,7 @@ func (x *UnitStatusResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use UnitStatusResponse.ProtoReflect.Descriptor instead. func (*UnitStatusResponse) Descriptor() ([]byte, []int) { - return file_systemd_proto_rawDescGZIP(), []int{3} + return file_systemd_proto_rawDescGZIP(), []int{4} } func (x *UnitStatusResponse) GetCmdStatus() string { @@ -270,7 +325,7 @@ type UnitResourceRequest struct { func (x *UnitResourceRequest) Reset() { *x = UnitResourceRequest{} if protoimpl.UnsafeEnabled { - mi := &file_systemd_proto_msgTypes[4] + mi := &file_systemd_proto_msgTypes[5] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -283,7 +338,7 @@ func (x *UnitResourceRequest) String() string { func (*UnitResourceRequest) ProtoMessage() {} func (x *UnitResourceRequest) ProtoReflect() protoreflect.Message { - mi := &file_systemd_proto_msgTypes[4] + mi := &file_systemd_proto_msgTypes[5] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -296,7 +351,7 @@ func (x *UnitResourceRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use UnitResourceRequest.ProtoReflect.Descriptor instead. func (*UnitResourceRequest) Descriptor() ([]byte, []int) { - return file_systemd_proto_rawDescGZIP(), []int{4} + return file_systemd_proto_rawDescGZIP(), []int{5} } func (x *UnitResourceRequest) GetUnitName() string { @@ -318,7 +373,7 @@ type UnitResourceResponse struct { func (x *UnitResourceResponse) Reset() { *x = UnitResourceResponse{} if protoimpl.UnsafeEnabled { - mi := &file_systemd_proto_msgTypes[5] + mi := &file_systemd_proto_msgTypes[6] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -331,7 +386,7 @@ func (x *UnitResourceResponse) String() string { func (*UnitResourceResponse) ProtoMessage() {} func (x *UnitResourceResponse) ProtoReflect() protoreflect.Message { - mi := &file_systemd_proto_msgTypes[5] + mi := &file_systemd_proto_msgTypes[6] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -344,7 +399,7 @@ func (x *UnitResourceResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use UnitResourceResponse.ProtoReflect.Descriptor instead. func (*UnitResourceResponse) Descriptor() ([]byte, []int) { - return file_systemd_proto_rawDescGZIP(), []int{5} + return file_systemd_proto_rawDescGZIP(), []int{6} } func (x *UnitResourceResponse) GetCpuUsage() float64 { @@ -371,68 +426,72 @@ var file_systemd_proto_rawDesc = []byte{ 0x61, 0x6d, 0x65, 0x22, 0x2c, 0x0a, 0x0c, 0x55, 0x6e, 0x69, 0x74, 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, 0xb2, 0x01, 0x0a, 0x0a, 0x55, 0x6e, 0x69, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, - 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, 0x1c, 0x0a, 0x09, 0x4c, 0x6f, 0x61, 0x64, 0x53, 0x74, - 0x61, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x4c, 0x6f, 0x61, 0x64, 0x53, - 0x74, 0x61, 0x74, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x41, 0x63, 0x74, 0x69, 0x76, 0x65, 0x53, 0x74, - 0x61, 0x74, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x41, 0x63, 0x74, 0x69, 0x76, - 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x53, 0x75, 0x62, 0x53, 0x74, 0x61, - 0x74, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x53, 0x75, 0x62, 0x53, 0x74, 0x61, - 0x74, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x50, 0x61, 0x74, 0x68, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x04, 0x50, 0x61, 0x74, 0x68, 0x22, 0x67, 0x0a, 0x12, 0x55, 0x6e, 0x69, 0x74, 0x53, 0x74, - 0x61, 0x74, 0x75, 0x73, 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, 0x33, 0x0a, 0x0a, 0x55, 0x6e, - 0x69, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, - 0x2e, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x64, 0x2e, 0x55, 0x6e, 0x69, 0x74, 0x53, 0x74, 0x61, - 0x74, 0x75, 0x73, 0x52, 0x0a, 0x55, 0x6e, 0x69, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, - 0x31, 0x0a, 0x13, 0x55, 0x6e, 0x69, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x55, 0x6e, 0x69, 0x74, 0x4e, 0x61, - 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x55, 0x6e, 0x69, 0x74, 0x4e, 0x61, - 0x6d, 0x65, 0x22, 0x54, 0x0a, 0x14, 0x55, 0x6e, 0x69, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, - 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x43, 0x70, - 0x75, 0x55, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x01, 0x52, 0x08, 0x43, 0x70, - 0x75, 0x55, 0x73, 0x61, 0x67, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, - 0x55, 0x73, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x02, 0x52, 0x0b, 0x4d, 0x65, 0x6d, - 0x6f, 0x72, 0x79, 0x55, 0x73, 0x61, 0x67, 0x65, 0x32, 0x9b, 0x04, 0x0a, 0x12, 0x55, 0x6e, 0x69, - 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, - 0x44, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x55, 0x6e, 0x69, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, - 0x12, 0x14, 0x2e, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x64, 0x2e, 0x55, 0x6e, 0x69, 0x74, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x64, - 0x2e, 0x55, 0x6e, 0x69, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x3a, 0x0a, 0x09, 0x53, 0x74, 0x61, 0x72, 0x74, 0x55, 0x6e, - 0x69, 0x74, 0x12, 0x14, 0x2e, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x64, 0x2e, 0x55, 0x6e, 0x69, - 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x15, 0x2e, 0x73, 0x79, 0x73, 0x74, 0x65, - 0x6d, 0x64, 0x2e, 0x55, 0x6e, 0x69, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, - 0x00, 0x12, 0x39, 0x0a, 0x08, 0x53, 0x74, 0x6f, 0x70, 0x55, 0x6e, 0x69, 0x74, 0x12, 0x14, 0x2e, - 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x64, 0x2e, 0x55, 0x6e, 0x69, 0x74, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x15, 0x2e, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x64, 0x2e, 0x55, 0x6e, - 0x69, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x39, 0x0a, 0x08, - 0x4b, 0x69, 0x6c, 0x6c, 0x55, 0x6e, 0x69, 0x74, 0x12, 0x14, 0x2e, 0x73, 0x79, 0x73, 0x74, 0x65, - 0x6d, 0x64, 0x2e, 0x55, 0x6e, 0x69, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x15, - 0x2e, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x64, 0x2e, 0x55, 0x6e, 0x69, 0x74, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x3b, 0x0a, 0x0a, 0x46, 0x72, 0x65, 0x65, 0x7a, - 0x65, 0x55, 0x6e, 0x69, 0x74, 0x12, 0x14, 0x2e, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x64, 0x2e, - 0x55, 0x6e, 0x69, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x15, 0x2e, 0x73, 0x79, - 0x73, 0x74, 0x65, 0x6d, 0x64, 0x2e, 0x55, 0x6e, 0x69, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0x00, 0x12, 0x3d, 0x0a, 0x0c, 0x55, 0x6e, 0x66, 0x72, 0x65, 0x65, 0x7a, 0x65, + 0x73, 0x22, 0x40, 0x0a, 0x0e, 0x41, 0x70, 0x70, 0x55, 0x6e, 0x69, 0x74, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x55, 0x6e, 0x69, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x55, 0x6e, 0x69, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x12, + 0x12, 0x0a, 0x04, 0x41, 0x72, 0x67, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x04, 0x41, + 0x72, 0x67, 0x73, 0x22, 0xb2, 0x01, 0x0a, 0x0a, 0x55, 0x6e, 0x69, 0x74, 0x53, 0x74, 0x61, 0x74, + 0x75, 0x73, 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, 0x1c, 0x0a, 0x09, 0x4c, 0x6f, 0x61, 0x64, + 0x53, 0x74, 0x61, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x4c, 0x6f, 0x61, + 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x41, 0x63, 0x74, 0x69, 0x76, 0x65, + 0x53, 0x74, 0x61, 0x74, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x41, 0x63, 0x74, + 0x69, 0x76, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x53, 0x75, 0x62, 0x53, + 0x74, 0x61, 0x74, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x53, 0x75, 0x62, 0x53, + 0x74, 0x61, 0x74, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x50, 0x61, 0x74, 0x68, 0x18, 0x06, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x04, 0x50, 0x61, 0x74, 0x68, 0x22, 0x67, 0x0a, 0x12, 0x55, 0x6e, 0x69, 0x74, + 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 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, 0x33, 0x0a, 0x0a, + 0x55, 0x6e, 0x69, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x13, 0x2e, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x64, 0x2e, 0x55, 0x6e, 0x69, 0x74, 0x53, + 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x0a, 0x55, 0x6e, 0x69, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, + 0x73, 0x22, 0x31, 0x0a, 0x13, 0x55, 0x6e, 0x69, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x55, 0x6e, 0x69, 0x74, + 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x55, 0x6e, 0x69, 0x74, + 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x54, 0x0a, 0x14, 0x55, 0x6e, 0x69, 0x74, 0x52, 0x65, 0x73, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1a, 0x0a, 0x08, + 0x43, 0x70, 0x75, 0x55, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x01, 0x52, 0x08, + 0x43, 0x70, 0x75, 0x55, 0x73, 0x61, 0x67, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x4d, 0x65, 0x6d, 0x6f, + 0x72, 0x79, 0x55, 0x73, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x02, 0x52, 0x0b, 0x4d, + 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x55, 0x73, 0x61, 0x67, 0x65, 0x32, 0x9e, 0x04, 0x0a, 0x12, 0x55, + 0x6e, 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, + 0x65, 0x12, 0x44, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x55, 0x6e, 0x69, 0x74, 0x53, 0x74, 0x61, 0x74, + 0x75, 0x73, 0x12, 0x14, 0x2e, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x64, 0x2e, 0x55, 0x6e, 0x69, + 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x73, 0x79, 0x73, 0x74, 0x65, + 0x6d, 0x64, 0x2e, 0x55, 0x6e, 0x69, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x3a, 0x0a, 0x09, 0x53, 0x74, 0x61, 0x72, 0x74, 0x55, 0x6e, 0x69, 0x74, 0x12, 0x14, 0x2e, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x64, 0x2e, 0x55, 0x6e, 0x69, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x15, 0x2e, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x64, 0x2e, 0x55, 0x6e, 0x69, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x22, 0x00, 0x12, 0x4e, 0x0a, 0x0b, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x55, 0x6e, - 0x69, 0x74, 0x12, 0x1c, 0x2e, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x64, 0x2e, 0x55, 0x6e, 0x69, - 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x1d, 0x2e, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x64, 0x2e, 0x55, 0x6e, 0x69, 0x74, 0x52, - 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, - 0x00, 0x30, 0x01, 0x12, 0x41, 0x0a, 0x10, 0x53, 0x74, 0x61, 0x72, 0x74, 0x41, 0x70, 0x70, 0x6c, - 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x14, 0x2e, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, + 0x65, 0x22, 0x00, 0x12, 0x39, 0x0a, 0x08, 0x53, 0x74, 0x6f, 0x70, 0x55, 0x6e, 0x69, 0x74, 0x12, + 0x14, 0x2e, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x64, 0x2e, 0x55, 0x6e, 0x69, 0x74, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x15, 0x2e, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x64, 0x2e, + 0x55, 0x6e, 0x69, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x39, + 0x0a, 0x08, 0x4b, 0x69, 0x6c, 0x6c, 0x55, 0x6e, 0x69, 0x74, 0x12, 0x14, 0x2e, 0x73, 0x79, 0x73, + 0x74, 0x65, 0x6d, 0x64, 0x2e, 0x55, 0x6e, 0x69, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x15, 0x2e, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x64, 0x2e, 0x55, 0x6e, 0x69, 0x74, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x3b, 0x0a, 0x0a, 0x46, 0x72, 0x65, + 0x65, 0x7a, 0x65, 0x55, 0x6e, 0x69, 0x74, 0x12, 0x14, 0x2e, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x64, 0x2e, 0x55, 0x6e, 0x69, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x15, 0x2e, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x64, 0x2e, 0x55, 0x6e, 0x69, 0x74, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x0b, 0x5a, 0x09, 0x2e, 0x2f, 0x73, 0x79, 0x73, 0x74, - 0x65, 0x6d, 0x64, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x3d, 0x0a, 0x0c, 0x55, 0x6e, 0x66, 0x72, 0x65, 0x65, + 0x7a, 0x65, 0x55, 0x6e, 0x69, 0x74, 0x12, 0x14, 0x2e, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x64, + 0x2e, 0x55, 0x6e, 0x69, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x15, 0x2e, 0x73, + 0x79, 0x73, 0x74, 0x65, 0x6d, 0x64, 0x2e, 0x55, 0x6e, 0x69, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x4e, 0x0a, 0x0b, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, + 0x55, 0x6e, 0x69, 0x74, 0x12, 0x1c, 0x2e, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x64, 0x2e, 0x55, + 0x6e, 0x69, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x64, 0x2e, 0x55, 0x6e, 0x69, + 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x22, 0x00, 0x30, 0x01, 0x12, 0x44, 0x0a, 0x10, 0x53, 0x74, 0x61, 0x72, 0x74, 0x41, 0x70, + 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x17, 0x2e, 0x73, 0x79, 0x73, 0x74, + 0x65, 0x6d, 0x64, 0x2e, 0x41, 0x70, 0x70, 0x55, 0x6e, 0x69, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x15, 0x2e, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x64, 0x2e, 0x55, 0x6e, 0x69, + 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x0b, 0x5a, 0x09, 0x2e, + 0x2f, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x64, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -447,32 +506,33 @@ func file_systemd_proto_rawDescGZIP() []byte { return file_systemd_proto_rawDescData } -var file_systemd_proto_msgTypes = make([]protoimpl.MessageInfo, 6) -var file_systemd_proto_goTypes = []interface{}{ +var file_systemd_proto_msgTypes = make([]protoimpl.MessageInfo, 7) +var file_systemd_proto_goTypes = []any{ (*UnitRequest)(nil), // 0: systemd.UnitRequest (*UnitResponse)(nil), // 1: systemd.UnitResponse - (*UnitStatus)(nil), // 2: systemd.UnitStatus - (*UnitStatusResponse)(nil), // 3: systemd.UnitStatusResponse - (*UnitResourceRequest)(nil), // 4: systemd.UnitResourceRequest - (*UnitResourceResponse)(nil), // 5: systemd.UnitResourceResponse + (*AppUnitRequest)(nil), // 2: systemd.AppUnitRequest + (*UnitStatus)(nil), // 3: systemd.UnitStatus + (*UnitStatusResponse)(nil), // 4: systemd.UnitStatusResponse + (*UnitResourceRequest)(nil), // 5: systemd.UnitResourceRequest + (*UnitResourceResponse)(nil), // 6: systemd.UnitResourceResponse } var file_systemd_proto_depIdxs = []int32{ - 2, // 0: systemd.UnitStatusResponse.UnitStatus:type_name -> systemd.UnitStatus + 3, // 0: systemd.UnitStatusResponse.UnitStatus:type_name -> systemd.UnitStatus 0, // 1: systemd.UnitControlService.GetUnitStatus:input_type -> systemd.UnitRequest 0, // 2: systemd.UnitControlService.StartUnit:input_type -> systemd.UnitRequest 0, // 3: systemd.UnitControlService.StopUnit:input_type -> systemd.UnitRequest 0, // 4: systemd.UnitControlService.KillUnit:input_type -> systemd.UnitRequest 0, // 5: systemd.UnitControlService.FreezeUnit:input_type -> systemd.UnitRequest 0, // 6: systemd.UnitControlService.UnfreezeUnit:input_type -> systemd.UnitRequest - 4, // 7: systemd.UnitControlService.MonitorUnit:input_type -> systemd.UnitResourceRequest - 0, // 8: systemd.UnitControlService.StartApplication:input_type -> systemd.UnitRequest - 3, // 9: systemd.UnitControlService.GetUnitStatus:output_type -> systemd.UnitStatusResponse + 5, // 7: systemd.UnitControlService.MonitorUnit:input_type -> systemd.UnitResourceRequest + 2, // 8: systemd.UnitControlService.StartApplication:input_type -> systemd.AppUnitRequest + 4, // 9: systemd.UnitControlService.GetUnitStatus:output_type -> systemd.UnitStatusResponse 1, // 10: systemd.UnitControlService.StartUnit:output_type -> systemd.UnitResponse 1, // 11: systemd.UnitControlService.StopUnit:output_type -> systemd.UnitResponse 1, // 12: systemd.UnitControlService.KillUnit:output_type -> systemd.UnitResponse 1, // 13: systemd.UnitControlService.FreezeUnit:output_type -> systemd.UnitResponse 1, // 14: systemd.UnitControlService.UnfreezeUnit:output_type -> systemd.UnitResponse - 5, // 15: systemd.UnitControlService.MonitorUnit:output_type -> systemd.UnitResourceResponse + 6, // 15: systemd.UnitControlService.MonitorUnit:output_type -> systemd.UnitResourceResponse 1, // 16: systemd.UnitControlService.StartApplication:output_type -> systemd.UnitResponse 9, // [9:17] is the sub-list for method output_type 1, // [1:9] is the sub-list for method input_type @@ -487,7 +547,7 @@ func file_systemd_proto_init() { return } if !protoimpl.UnsafeEnabled { - file_systemd_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + file_systemd_proto_msgTypes[0].Exporter = func(v any, i int) any { switch v := v.(*UnitRequest); i { case 0: return &v.state @@ -499,7 +559,7 @@ func file_systemd_proto_init() { return nil } } - file_systemd_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + file_systemd_proto_msgTypes[1].Exporter = func(v any, i int) any { switch v := v.(*UnitResponse); i { case 0: return &v.state @@ -511,7 +571,19 @@ func file_systemd_proto_init() { return nil } } - file_systemd_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + file_systemd_proto_msgTypes[2].Exporter = func(v any, i int) any { + switch v := v.(*AppUnitRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_systemd_proto_msgTypes[3].Exporter = func(v any, i int) any { switch v := v.(*UnitStatus); i { case 0: return &v.state @@ -523,7 +595,7 @@ func file_systemd_proto_init() { return nil } } - file_systemd_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + file_systemd_proto_msgTypes[4].Exporter = func(v any, i int) any { switch v := v.(*UnitStatusResponse); i { case 0: return &v.state @@ -535,7 +607,7 @@ func file_systemd_proto_init() { return nil } } - file_systemd_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + file_systemd_proto_msgTypes[5].Exporter = func(v any, i int) any { switch v := v.(*UnitResourceRequest); i { case 0: return &v.state @@ -547,7 +619,7 @@ func file_systemd_proto_init() { return nil } } - file_systemd_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { + file_systemd_proto_msgTypes[6].Exporter = func(v any, i int) any { switch v := v.(*UnitResourceResponse); i { case 0: return &v.state @@ -566,7 +638,7 @@ func file_systemd_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_systemd_proto_rawDesc, NumEnums: 0, - NumMessages: 6, + NumMessages: 7, NumExtensions: 0, NumServices: 1, }, diff --git a/api/systemd/systemd.proto b/api/systemd/systemd.proto index 5ee3757..718f56a 100644 --- a/api/systemd/systemd.proto +++ b/api/systemd/systemd.proto @@ -12,6 +12,11 @@ message UnitResponse { string CmdStatus = 1; } +message AppUnitRequest { + string UnitName = 1; + repeated string Args = 2; +} + message UnitStatus { string Name = 1; string Description = 2; @@ -43,5 +48,5 @@ service UnitControlService { rpc FreezeUnit(UnitRequest) returns (UnitResponse) {} rpc UnfreezeUnit(UnitRequest) returns (UnitResponse) {} rpc MonitorUnit(UnitResourceRequest) returns (stream UnitResourceResponse) {} - rpc StartApplication(UnitRequest) returns (UnitResponse) {} + rpc StartApplication(AppUnitRequest) returns (UnitResponse) {} } \ No newline at end of file diff --git a/api/systemd/systemd_grpc.pb.go b/api/systemd/systemd_grpc.pb.go index 6c1cb19..60fea3f 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.24.4 +// - protoc v4.25.4 // source: systemd.proto package systemd @@ -43,7 +43,7 @@ type UnitControlServiceClient interface { FreezeUnit(ctx context.Context, in *UnitRequest, opts ...grpc.CallOption) (*UnitResponse, error) UnfreezeUnit(ctx context.Context, in *UnitRequest, opts ...grpc.CallOption) (*UnitResponse, error) MonitorUnit(ctx context.Context, in *UnitResourceRequest, opts ...grpc.CallOption) (UnitControlService_MonitorUnitClient, error) - StartApplication(ctx context.Context, in *UnitRequest, opts ...grpc.CallOption) (*UnitResponse, error) + StartApplication(ctx context.Context, in *AppUnitRequest, opts ...grpc.CallOption) (*UnitResponse, error) } type unitControlServiceClient struct { @@ -140,7 +140,7 @@ func (x *unitControlServiceMonitorUnitClient) Recv() (*UnitResourceResponse, err return m, nil } -func (c *unitControlServiceClient) StartApplication(ctx context.Context, in *UnitRequest, opts ...grpc.CallOption) (*UnitResponse, error) { +func (c *unitControlServiceClient) StartApplication(ctx context.Context, in *AppUnitRequest, opts ...grpc.CallOption) (*UnitResponse, error) { out := new(UnitResponse) err := c.cc.Invoke(ctx, UnitControlService_StartApplication_FullMethodName, in, out, opts...) if err != nil { @@ -160,7 +160,7 @@ type UnitControlServiceServer interface { FreezeUnit(context.Context, *UnitRequest) (*UnitResponse, error) UnfreezeUnit(context.Context, *UnitRequest) (*UnitResponse, error) MonitorUnit(*UnitResourceRequest, UnitControlService_MonitorUnitServer) error - StartApplication(context.Context, *UnitRequest) (*UnitResponse, error) + StartApplication(context.Context, *AppUnitRequest) (*UnitResponse, error) mustEmbedUnimplementedUnitControlServiceServer() } @@ -189,7 +189,7 @@ func (UnimplementedUnitControlServiceServer) UnfreezeUnit(context.Context, *Unit func (UnimplementedUnitControlServiceServer) MonitorUnit(*UnitResourceRequest, UnitControlService_MonitorUnitServer) error { return status.Errorf(codes.Unimplemented, "method MonitorUnit not implemented") } -func (UnimplementedUnitControlServiceServer) StartApplication(context.Context, *UnitRequest) (*UnitResponse, error) { +func (UnimplementedUnitControlServiceServer) StartApplication(context.Context, *AppUnitRequest) (*UnitResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method StartApplication not implemented") } func (UnimplementedUnitControlServiceServer) mustEmbedUnimplementedUnitControlServiceServer() {} @@ -335,7 +335,7 @@ func (x *unitControlServiceMonitorUnitServer) Send(m *UnitResourceResponse) erro } func _UnitControlService_StartApplication_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(UnitRequest) + in := new(AppUnitRequest) if err := dec(in); err != nil { return nil, err } @@ -347,7 +347,7 @@ func _UnitControlService_StartApplication_Handler(srv interface{}, ctx context.C FullMethod: UnitControlService_StartApplication_FullMethodName, } handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(UnitControlServiceServer).StartApplication(ctx, req.(*UnitRequest)) + return srv.(UnitControlServiceServer).StartApplication(ctx, req.(*AppUnitRequest)) } return interceptor(ctx, in, info, handler) } diff --git a/api/wifi/wifi.pb.go b/api/wifi/wifi.pb.go index 884765b..84dd9bd 100644 --- a/api/wifi/wifi.pb.go +++ b/api/wifi/wifi.pb.go @@ -4,7 +4,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.34.2 -// protoc v4.25.3 +// protoc v4.25.4 // source: wifi.proto package wifi diff --git a/api/wifi/wifi_grpc.pb.go b/api/wifi/wifi_grpc.pb.go index 077291a..6cbaf0a 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.3 +// - protoc v4.25.4 // source: wifi.proto package wifi diff --git a/client/src/client.rs b/client/src/client.rs index a7b16f0..3a773ee 100644 --- a/client/src/client.rs +++ b/client/src/client.rs @@ -76,8 +76,17 @@ impl AdminClient { Ok(response.into_inner().cmd_status) } - pub async fn start(&self, app_name: String, vm_name: Option) -> anyhow::Result<()> { - let request = pb::admin::ApplicationRequest { app_name, vm_name }; + pub async fn start( + &self, + app_name: String, + vm_name: Option, + args: Vec, + ) -> anyhow::Result<()> { + let request = pb::admin::ApplicationRequest { + app_name, + vm_name, + args, + }; let response = self.connect_to().await?.start_application(request).await?; // Ok(response.into_inner().cmd_status) Ok(()) diff --git a/flake.lock b/flake.lock index 331466a..cdf1692 100644 --- a/flake.lock +++ b/flake.lock @@ -114,11 +114,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1724479785, - "narHash": "sha256-pP3Azj5d6M5nmG68Fu4JqZmdGt4S4vqI5f8te+E/FTw=", + "lastModified": 1726243404, + "narHash": "sha256-sjiGsMh+1cWXb53Tecsm4skyFNag33GPbVgCdfj3n9I=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "d0e1602ddde669d5beb01aec49d71a51937ed7be", + "rev": "345c263f2f53a3710abe117f28a5cb86d0ba4059", "type": "github" }, "original": { diff --git a/go.mod b/go.mod index f6a0e62..60a9a08 100644 --- a/go.mod +++ b/go.mod @@ -4,24 +4,26 @@ go 1.21.4 require ( github.com/coreos/go-systemd/v22 v22.5.0 + github.com/go-ozzo/ozzo-validation/v4 v4.3.0 github.com/godbus/dbus/v5 v5.1.0 github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0 github.com/shirou/gopsutil v3.21.11+incompatible github.com/sirupsen/logrus v1.9.3 golang.org/x/sync v0.8.0 - google.golang.org/grpc v1.65.0 + google.golang.org/grpc v1.66.2 google.golang.org/protobuf v1.34.2 ) require ( + github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect github.com/go-ole/go-ole v1.3.0 // indirect github.com/golang/protobuf v1.5.4 // indirect github.com/tklauser/go-sysconf v0.3.14 // indirect github.com/tklauser/numcpus v0.8.0 // indirect github.com/yusufpapurcu/wmi v1.2.4 // indirect - golang.org/x/net v0.28.0 // indirect - golang.org/x/sys v0.24.0 // indirect - golang.org/x/text v0.17.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240827150818-7e3bb234dfed // indirect + golang.org/x/net v0.29.0 // indirect + golang.org/x/sys v0.25.0 // indirect + golang.org/x/text v0.18.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 // indirect ) diff --git a/go.sum b/go.sum index 5371f76..0b3758a 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,8 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/asaskevich/govalidator v0.0.0-20200108200545-475eaeb16496/go.mod h1:oGkLhpf+kjZl6xBf758TQhh5XrAeiJv/7FRz/2spLIg= +github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so= +github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= @@ -18,6 +21,8 @@ github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= +github.com/go-ozzo/ozzo-validation/v4 v4.3.0 h1:byhDUpfEwjsVQb1vBunvIjh2BHQ9ead57VkAEY4V+Es= +github.com/go-ozzo/ozzo-validation/v4 v4.3.0/go.mod h1:2NKgrcHl3z6cJs+3Oo940FPRiTzuqKbvfrL2RxCj6Ew= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= @@ -92,8 +97,8 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE= -golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg= +golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo= +golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -111,12 +116,12 @@ golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg= -golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= +golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc= -golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= +golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224= +golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= @@ -135,15 +140,15 @@ google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7 google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240827150818-7e3bb234dfed h1:J6izYgfBXAI3xTKLgxzTmUltdYaLsuBxFCgDHWJ/eXg= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240827150818-7e3bb234dfed/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 h1:pPJltXNxVzT4pK9yD8vR9X75DaWYYmLGMsEvBfFQZzQ= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= -google.golang.org/grpc v1.65.0 h1:bs/cUb4lp1G5iImFFd3u5ixQzweKizoZJAwBNLR42lc= -google.golang.org/grpc v1.65.0/go.mod h1:WgYC2ypjlB0EiQi6wdKixMqukr6lBc0Vo+oOgjrM5ZQ= +google.golang.org/grpc v1.66.2 h1:3QdXkuq3Bkh7w+ywLdLvM56cmGvQHUMZpiCzt6Rqaoo= +google.golang.org/grpc v1.66.2/go.mod h1:s3/l6xSSCURdVfAnL+TqCNMyTDAGN6+lZeVxnZR128Y= google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/internal/cmd/givc-agent/main.go b/internal/cmd/givc-agent/main.go index 5e706e4..1477704 100644 --- a/internal/cmd/givc-agent/main.go +++ b/internal/cmd/givc-agent/main.go @@ -5,13 +5,13 @@ package main import ( "context" "crypto/tls" - "encoding/json" "os" "path/filepath" "strconv" "strings" "givc/api/admin" + givc_app "givc/internal/pkgs/applications" givc_grpc "givc/internal/pkgs/grpc" "givc/internal/pkgs/hwidmanager" "givc/internal/pkgs/serviceclient" @@ -65,15 +65,16 @@ func main() { if servicesPresent { services = strings.Split(servicesString, " ") } - var applications map[string]string + + var applications []types.ApplicationManifest jsonApplicationString, appPresent := os.LookupEnv("APPLICATIONS") if appPresent && jsonApplicationString != "" { - applications = make(map[string]string) - err := json.Unmarshal([]byte(jsonApplicationString), &applications) + applications, err = givc_app.ParseApplicationManifests(jsonApplicationString) if err != nil { - log.Fatalf("Error unmarshalling JSON string.") + log.Fatalf("Error parsing application manifests: %s", err) } } + adminServerName := os.Getenv("ADMIN_SERVER_NAME") if adminServerName == "" { log.Fatalf("A name for the admin server is required in environment variable $ADMIN_SERVER_NAME.") @@ -144,9 +145,9 @@ func main() { }, TlsConfig: tlsConfig, } - agentServiceName := "givc-" + name + ".service" // Add services + agentServiceName := "givc-" + name + ".service" cfgAgent.Services = append(cfgAgent.Services, agentServiceName) if servicesPresent { cfgAgent.Services = append(cfgAgent.Services, services...) diff --git a/internal/pkgs/applications/applications.go b/internal/pkgs/applications/applications.go new file mode 100644 index 0000000..9ee05ea --- /dev/null +++ b/internal/pkgs/applications/applications.go @@ -0,0 +1,160 @@ +package applications + +import ( + "encoding/json" + "fmt" + "givc/internal/pkgs/types" + "givc/internal/pkgs/utility" + "net/url" + "regexp" + "strings" + + log "github.com/sirupsen/logrus" + + validation "github.com/go-ozzo/ozzo-validation/v4" + "github.com/go-ozzo/ozzo-validation/v4/is" +) + +func validateServiceName(serviceName string) error { + return validation.Validate( + serviceName, + validation.Required, + is.PrintableASCII, + validation.Match(regexp.MustCompile(`^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+\.service$`)), + ) +} + +func validateUrl(urlString string) error { + err := validation.Validate( + urlString, + validation.Required, + is.URL, + ) + if err != nil { + log.Warnf("Invalid URL in args: %v Error: %v", urlString, err) + return fmt.Errorf("failure in parsing URL") + } + + // Disallow some more shenanigans + reqUrl, err := url.Parse(urlString) + if err != nil { + log.Warnf("Invalid URL in args: %v", urlString) + return fmt.Errorf("failure in parsing URL") + } + if reqUrl.Scheme != "https" && reqUrl.Scheme != "http" { + log.Warnf("Non-HTTP(S) scheme in URL: %v", reqUrl.Scheme) + return fmt.Errorf("failure in parsing URL") + } + if reqUrl.User != nil { + log.Warnf("User info in URL: %v", reqUrl.User) + return fmt.Errorf("failure in parsing URL") + } + return nil +} + +func validateApplicationArgs(args []string, allowedArgs []string) error { + + checkAllowed := func(err error, argType string, allowedArgs []string) bool { + if err == nil { + return utility.CheckStringInArray(argType, allowedArgs) + } + return false + } + + // Check if arg is allowed + var err error + for _, arg := range args { + err = validation.Validate( + arg, + validation.Required, + is.PrintableASCII, + validation.Match(regexp.MustCompile(`^-[-]?[a-zA-Z0-9_-]+$`)), + ) + valid := checkAllowed(err, types.APP_ARG_FLAG, allowedArgs) + if valid { + continue + } + + err = validateUrl(arg) + valid = checkAllowed(err, types.APP_ARG_URL, allowedArgs) + if valid { + continue + } + return fmt.Errorf("invalid application argument: %s", arg) + } + return nil +} + +func ParseApplicationManifests(jsonApplicationString string) ([]types.ApplicationManifest, error) { + var applications []types.ApplicationManifest + + // Unmarshal JSON string into applications + err := json.Unmarshal([]byte(jsonApplicationString), &applications) + if err != nil { + return nil, fmt.Errorf("error unmarshalling JSON string: %v", err) + } + + // Verify application manifest formats + appNames := []string{} + for _, app := range applications { + // Check app name not empty + if app.Name == "" { + return nil, fmt.Errorf("application name is empty") + } + for _, name := range appNames { + if name == app.Name { + return nil, fmt.Errorf("duplicate application name") + } + } + appNames = append(appNames, app.Name) + + // Check app command not empty + if app.Command == "" { + return nil, fmt.Errorf("application command is empty") + } + + // Check app args types + if app.Args != nil { + for _, argType := range app.Args { + switch argType { + case types.APP_ARG_FLAG: + case types.APP_ARG_URL: + default: + return nil, fmt.Errorf("application argument type not supported") + } + } + } + } + return applications, nil +} + +func ValidateAppUnitRequest(serviceName string, appArgs []string, applications []types.ApplicationManifest) error { + + // Verify application request + name := strings.Split(serviceName, "@")[0] + validEntryFound := false + for _, app := range applications { + if app.Name == name { + validEntryFound = true + + // Validate application name format + err := validateServiceName(serviceName) + if err != nil { + return fmt.Errorf("failure parsing application name") + } + + // Validate application args + if appArgs != nil { + err = validateApplicationArgs(appArgs, app.Args) + if err != nil { + return err + } + } + } + } + if !validEntryFound { + return fmt.Errorf("application not found in manifest") + } + + return nil +} diff --git a/internal/pkgs/applications/applications_test.go b/internal/pkgs/applications/applications_test.go new file mode 100644 index 0000000..f3bffcc --- /dev/null +++ b/internal/pkgs/applications/applications_test.go @@ -0,0 +1,360 @@ +package applications + +import ( + "givc/internal/pkgs/types" + "reflect" + "testing" +) + +func Test_validateServiceName(t *testing.T) { + type args struct { + serviceName string + } + tests := []struct { + name string + args args + wantErr bool + }{ + {"valid service name", args{serviceName: "-@-.service"}, false}, + {"valid service name", args{serviceName: "1@1.service"}, false}, + {"valid service name", args{serviceName: "-_1@1_-.service"}, false}, + {"valid service name", args{serviceName: "valid@my-service.service"}, false}, + {"valid service name", args{serviceName: "valid@my.service"}, false}, + + {"invalid service name", args{serviceName: "a@valid@my-service.service"}, true}, + {"invalid service name", args{serviceName: "a@a@my-service.service"}, true}, + {"invalid service name", args{serviceName: "a@valid.service@my-service.service"}, true}, + {"invalid service name", args{serviceName: "@1.service"}, true}, + {"invalid service name", args{serviceName: "my-service.service"}, true}, + {"invalid service name", args{serviceName: "my-service@.service"}, true}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := validateServiceName(tt.args.serviceName); (err != nil) != tt.wantErr { + t.Errorf("validateServiceName() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} + +func Test_validateUrl(t *testing.T) { + type args struct { + urlString string + } + tests := []struct { + name string + args args + wantErr bool + }{ + // Valid URLs + {"valid url", args{urlString: "http://example.com"}, false}, + {"valid url", args{urlString: "https://example.com"}, false}, + {"valid url", args{urlString: "https://example.com/something."}, false}, + {"valid url", args{urlString: "https://example.com?q=2#first"}, false}, + {"valid url", args{urlString: "https://localhost:8080/"}, false}, + + // Invalid URLs + {"invalid protocol", args{urlString: "file:///etc/passwd"}, true}, + {"inject shell cmd", args{urlString: "https://example.com$(touch IWASHERE)"}, true}, + {"inject shell cmd", args{urlString: "https://example.com/ $(touch IWASHERE)"}, true}, + {"inject shell cmd", args{urlString: "$(touch IWASHERE)https://google.com"}, true}, + {"inject shell cmd", args{urlString: "https://example.com\\%20$(touch IWASHERE)"}, true}, + {"inject shell cmd", args{urlString: "https://example.com/a;\\$(touch IWASHERE)"}, true}, + {"inject shell cmd", args{urlString: "https://example.com;touch IWASHERE"}, true}, + {"inject shell cmd", args{urlString: "https://example.com/'$(touch IWASHERE)"}, true}, + {"user info in url", args{urlString: "https://bob:pass123@www.example.com/"}, true}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := validateUrl(tt.args.urlString); (err != nil) != tt.wantErr { + t.Errorf("validateUrl() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} + +func TestParseApplicationManifests(t *testing.T) { + type args struct { + jsonApplicationString string + } + tests := []struct { + name string + args args + want []types.ApplicationManifest + wantErr bool + }{ + { + "single application", + args{`[{ + "Name":"test-app", + "Command":"chromium", + "Args":["url"] + }]`}, + []types.ApplicationManifest{ + { + Name: "test-app", + Command: "chromium", + Args: []string{types.APP_ARG_URL}, + }, + }, + false, + }, + { + "single application without args", + args{`[{"Name":"test-app","Command":"chromium"}]`}, + []types.ApplicationManifest{ + { + Name: "test-app", + Command: "chromium", + Args: nil, + }, + }, + false, + }, + { + "single application with two args", + args{`[{"Name":"test-app","Command":"chromium","Args":["flag","url"]}]`}, + []types.ApplicationManifest{ + { + Name: "test-app", + Command: "chromium", + Args: []string{types.APP_ARG_FLAG, types.APP_ARG_URL}, + }, + }, + false, + }, + { + "two applications with args", + args{`[ + {"Name":"test-app","Command":"chromium","Args":["flag","url"]}, + {"Name":"test-app2","Command":"firefox","Args":["url"]} + ]`}, + []types.ApplicationManifest{ + { + Name: "test-app", + Command: "chromium", + Args: []string{types.APP_ARG_FLAG, types.APP_ARG_URL}, + }, + { + Name: "test-app2", + Command: "firefox", + Args: []string{types.APP_ARG_URL}, + }, + }, + false, + }, + { + "two applications without args", + args{`[ + {"Name":"test-app","Command":"chromium"}, + {"Name":"test-app2","Command":"firefox"} + ]`}, + []types.ApplicationManifest{ + { + Name: "test-app", + Command: "chromium", + Args: nil, + }, + { + Name: "test-app2", + Command: "firefox", + Args: nil, + }, + }, + false, + }, + + { + "single application with wrong arg", + args{`[{"Name":"test-app","Command":"chromium", "Args":["argument"]}]`}, + nil, + true, + }, + { + "single application two args one wrong", + args{`[{"Name":"test-app","Command":"chromium", "Args":["url", "argument"]}]`}, + nil, + true, + }, + { + "two applications, one with wrong args", + args{`[ + {"Name":"test-app","Command":"chromium", "Args":["url", "argument"]"}, + {"Name":"test-app2","Command":"firefox", "Args":["url", "argument"]"}, + ]`}, + nil, + true, + }, + { + "two applications, same name", + args{`[ + {"Name":"test-app","Command":"chromium"}, + {"Name":"test-app","Command":"firefox"} + ]`}, + nil, + true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := ParseApplicationManifests(tt.args.jsonApplicationString) + if (err != nil) != tt.wantErr { + t.Errorf("ParseApplicationManifests() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("ParseApplicationManifests() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestValidateAppUnitRequest(t *testing.T) { + type args struct { + serviceName string + serviceArgs []string + applications []types.ApplicationManifest + } + tests := []struct { + name string + args args + wantErr bool + }{ + // Valid cases + { + "Simple app request", + args{ + serviceName: "test-app@1.service", + serviceArgs: nil, + applications: []types.ApplicationManifest{ + { + Name: "test-app", + Command: "chromium", + Args: nil, + }, + }, + }, + false, + }, + { + "App request with args", + args{ + serviceName: "test-app@1.service", + serviceArgs: []string{"https://example.com", "--incognito"}, + applications: []types.ApplicationManifest{ + { + Name: "test-app", + Command: "chromium", + Args: []string{types.APP_ARG_URL, types.APP_ARG_FLAG}, + }, + }, + }, + false, + }, + { + "App request single arg with more allowed", + args{ + serviceName: "test-app@1.service", + serviceArgs: []string{"-incognito", "--incognito"}, + applications: []types.ApplicationManifest{ + { + Name: "test-app", + Command: "chromium", + Args: []string{types.APP_ARG_URL, types.APP_ARG_FLAG}, + }, + }, + }, + false, + }, + + // Error cases + + { + "App request, wrong service name", + args{ + serviceName: "test-app3@1.service", + serviceArgs: nil, + applications: []types.ApplicationManifest{ + { + Name: "test-app", + Command: "chromium", + Args: nil, + }, + { + Name: "test-app2", + Command: "firefox", + Args: nil, + }, + }, + }, + true, + }, + { + "App request with wrong arg content", + args{ + serviceName: "test-app@1.service", + serviceArgs: []string{"--incognito;echo something"}, + applications: []types.ApplicationManifest{ + { + Name: "test-app", + Command: "chromium", + Args: []string{types.APP_ARG_URL, types.APP_ARG_FLAG}, + }, + }, + }, + true, + }, + { + "App request with wrong arg content", + args{ + serviceName: "test-app@1.service", + serviceArgs: []string{"--incognito;echo something"}, + applications: []types.ApplicationManifest{ + { + Name: "test-app", + Command: "chromium", + Args: []string{types.APP_ARG_URL, types.APP_ARG_FLAG}, + }, + }, + }, + true, + }, + { + "App request to wrong service", + args{ + serviceName: "test-app2@1.service", + serviceArgs: []string{"https://example.com", "--incognito"}, + applications: []types.ApplicationManifest{ + { + Name: "test-app", + Command: "chromium", + Args: []string{types.APP_ARG_URL, types.APP_ARG_FLAG}, + }, + { + Name: "test-app2", + Command: "firefox", + Args: nil, + }, + }, + }, + true, + }, + + { + "Wrong service name test", + args{ + serviceName: "test-app2@1.service", + serviceArgs: nil, + applications: nil, + }, + true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := ValidateAppUnitRequest(tt.args.serviceName, tt.args.serviceArgs, tt.args.applications); (err != nil) != tt.wantErr { + t.Errorf("ValidateAppUnitRequest() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/pkgs/serviceclient/transport.go b/internal/pkgs/serviceclient/transport.go index ff5d048..958923d 100644 --- a/internal/pkgs/serviceclient/transport.go +++ b/internal/pkgs/serviceclient/transport.go @@ -118,39 +118,6 @@ func StartRemoteService(cfg *types.EndpointConfig, unitName string) (*systemd_ap return resp, nil } -func StartRemoteApplication(cfg *types.EndpointConfig, unitName string) (*systemd_api.UnitResponse, error) { - - // Setup and dial GRPC client - var conn *grpc.ClientConn - conn, err := givc_grpc.NewClient(cfg, false) - if err != nil { - log.Errorf("Cannot create grpc client: %v", err) - return nil, err - } - defer conn.Close() - - // Create client - client := systemd_api.NewUnitControlServiceClient(conn) - if client == nil { - log.Errorf("Failed to create 'NewUnitControlServiceClient'") - return nil, err - } - - // Start unit - request := systemd_api.UnitRequest{ - UnitName: unitName, - } - ctx := context.Background() - resp, err := client.StartApplication(ctx, &request) - if err != nil { - log.Errorf("Not the response we hoped for: %v", err) - return nil, err - } - - log.Infoln(resp) - return resp, nil -} - func PauseRemoteService(cfg *types.EndpointConfig, unitName string) (*systemd_api.UnitResponse, error) { // Setup and dial GRPC client diff --git a/internal/pkgs/servicemanager/controller.go b/internal/pkgs/servicemanager/controller.go index 0d765dc..856caf4 100644 --- a/internal/pkgs/servicemanager/controller.go +++ b/internal/pkgs/servicemanager/controller.go @@ -8,6 +8,8 @@ import ( "strings" "syscall" + givc_app "givc/internal/pkgs/applications" + types "givc/internal/pkgs/types" util "givc/internal/pkgs/utility" "github.com/coreos/go-systemd/v22/dbus" @@ -19,10 +21,10 @@ import ( type SystemdController struct { conn *dbus.Conn whitelist []string - applications map[string]string + applications []types.ApplicationManifest } -func NewController(whitelist []string, applications map[string]string) (*SystemdController, error) { +func NewController(whitelist []string, applications []types.ApplicationManifest) (*SystemdController, error) { var err error var c SystemdController @@ -327,19 +329,25 @@ func (c *SystemdController) GetUnitProperties(ctx context.Context, unitName stri return props, nil } -func (c *SystemdController) StartApplication(ctx context.Context, serviceName string) (string, error) { +func (c *SystemdController) StartApplication(ctx context.Context, serviceName string, serviceArgs []string) (string, error) { cmdFailure := "Command failed." - // Verify input format - if !strings.Contains(serviceName, ".service") || !strings.Contains(serviceName, "@") { - return cmdFailure, fmt.Errorf("incorrect application service name") + // Validate application request + err := givc_app.ValidateAppUnitRequest(serviceName, serviceArgs, c.applications) + if err != nil { + return cmdFailure, err } // Assemble command appName := strings.Split(serviceName, "@")[0] - appCmd, ok := c.applications[appName] - if !ok { + appCmd := "" + for _, app := range c.applications { + if app.Name == appName { + appCmd = app.Command + } + } + if appCmd == "" { return cmdFailure, fmt.Errorf("application unknown") } cmd := strings.Split(appCmd, " ") @@ -347,6 +355,9 @@ func (c *SystemdController) StartApplication(ctx context.Context, serviceName st return cmdFailure, fmt.Errorf("incorrect application string format") } + // Add arguments + cmd = append(cmd, serviceArgs...) + // Setup properties var props []dbus.Property propDescription := dbus.PropDescription("Application service for " + appName) @@ -360,7 +371,7 @@ func (c *SystemdController) StartApplication(ctx context.Context, serviceName st // Run command as transient service jobStatus := make(chan string) - _, err := c.conn.StartTransientUnitContext(ctx, serviceName, "replace", props, jobStatus) + _, err = c.conn.StartTransientUnitContext(ctx, serviceName, "replace", props, jobStatus) if err != nil { return cmdFailure, fmt.Errorf("error starting application: %s (%s)", appCmd, err) } diff --git a/internal/pkgs/servicemanager/transport.go b/internal/pkgs/servicemanager/transport.go index 353b3ef..ddf742d 100644 --- a/internal/pkgs/servicemanager/transport.go +++ b/internal/pkgs/servicemanager/transport.go @@ -9,6 +9,7 @@ import ( "time" systemd_api "givc/api/systemd" + "givc/internal/pkgs/types" log "github.com/sirupsen/logrus" "google.golang.org/grpc" @@ -33,7 +34,7 @@ func (s *SystemdControlServer) RegisterGrpcService(srv *grpc.Server) { systemd_api.RegisterUnitControlServiceServer(srv, s) } -func NewSystemdControlServer(whitelist []string, applications map[string]string) (*SystemdControlServer, error) { +func NewSystemdControlServer(whitelist []string, applications []types.ApplicationManifest) (*SystemdControlServer, error) { systemdController, err := NewController(whitelist, applications) if err != nil { @@ -181,9 +182,9 @@ func (s *SystemdControlServer) MonitorUnit(req *systemd_api.UnitResourceRequest, return nil } -func (s *SystemdControlServer) StartApplication(ctx context.Context, req *systemd_api.UnitRequest) (*systemd_api.UnitResponse, error) { - log.Infof("Executing application start method.\n") - resp, err := s.Controller.StartApplication(ctx, req.UnitName) +func (s *SystemdControlServer) StartApplication(ctx context.Context, req *systemd_api.AppUnitRequest) (*systemd_api.UnitResponse, error) { + log.Infof("Executing application start method for: %s\n", req.UnitName) + resp, err := s.Controller.StartApplication(ctx, req.UnitName, req.Args) if err != nil { return nil, err } diff --git a/internal/pkgs/types/types.go b/internal/pkgs/types/types.go index 63b88e0..86411c0 100644 --- a/internal/pkgs/types/types.go +++ b/internal/pkgs/types/types.go @@ -31,6 +31,11 @@ const ( UNIT_TYPE_APPVM_APP UnitType = 14 ) +const ( + APP_ARG_FLAG = "flag" + APP_ARG_URL = "url" +) + type UnitStatus struct { Name string Description string @@ -62,6 +67,12 @@ type RegistryEntry struct { Watch bool } +type ApplicationManifest struct { + Name string `json:"Name"` + Command string `json:"Command"` + Args []string `json:"Args,omitempty"` +} + type GrpcServiceRegistration interface { Name() string RegisterGrpcService(*grpc.Server) diff --git a/internal/pkgs/utility/utility.go b/internal/pkgs/utility/utility.go index 842c892..e68638e 100644 --- a/internal/pkgs/utility/utility.go +++ b/internal/pkgs/utility/utility.go @@ -163,3 +163,12 @@ func GetOutboundIP() net.IP { return localAddr.IP } + +func CheckStringInArray(element string, array []string) bool { + for _, e := range array { + if e == element { + return true + } + } + return false +} diff --git a/nixos/modules/appvm.nix b/nixos/modules/appvm.nix index 79db7ce..e9a634e 100644 --- a/nixos/modules/appvm.nix +++ b/nixos/modules/appvm.nix @@ -18,6 +18,29 @@ let trivial attrsets ; + + applicationSubmodule = types.submodule { + options = { + name = mkOption { + description = "Name of the application."; + type = types.str; + }; + command = mkOption { + description = "Command to run the application."; + type = types.str; + }; + args = mkOption { + description = '' + List of allowed argument types for the application. Currently implemented arguments: + - 'url': URL provided to the application as string + - 'flag': Flag provided to the application as string. Arguments automatically prefixed with '--'. + ''; + type = types.listOf types.str; + default = [ ]; + }; + }; + }; + in { options.givc.appvm = { @@ -51,15 +74,17 @@ in applications = mkOption { description = '' - List of applications to be supported by the service. Expects a JSON string with the format: - "name": "command" - with: - - name: name of the application - - command: command to start the application + List of applications to be supported by the service. ''; - type = types.str; - default = ""; - example = ''{"chromium": "run-waypipe chromium --enable-features=UseOzonePlatform --ozone-platform=wayland"}''; + type = types.listOf applicationSubmodule; + default = [ { } ]; + example = [ + { + Name = "app"; + Command = "/bin/bash"; + Args = [ "url" ]; + } + ]; }; admin = mkOption { @@ -104,32 +129,30 @@ in TLS options for gRPC connections. It is enabled by default to discourage unprotected connections, and requires paths to certificates and key being set. To disable it use 'tls.enable = false;'. ''; - type = - with types; - submodule { - options = { - enable = mkOption { - description = "Enable TLS. Defaults to 'true'."; - type = bool; - default = true; - }; - caCertPath = mkOption { - description = "Path to the CA certificate file."; - type = str; - default = ""; - }; - certPath = mkOption { - description = "Path to the service certificate file."; - type = str; - default = ""; - }; - keyPath = mkOption { - description = "Path to the service key file."; - type = str; - default = ""; - }; + type = types.submodule { + options = { + enable = mkOption { + description = "Enable TLS. Defaults to 'true'."; + type = types.bool; + default = true; + }; + caCertPath = mkOption { + description = "Path to the CA certificate file."; + type = types.str; + default = ""; + }; + certPath = mkOption { + description = "Path to the service certificate file."; + type = types.str; + default = ""; + }; + keyPath = mkOption { + description = "Path to the service key file."; + type = types.str; + default = ""; }; }; + }; default = { enable = true; caCertPath = ""; @@ -163,6 +186,7 @@ in ExecStart = "${givc-agent}/bin/givc-agent"; Restart = "always"; RestartSec = 1; + PrivateTmp = true; }; environment = { @@ -175,7 +199,7 @@ in "SUBTYPE" = "13"; "TLS" = "${trivial.boolToString cfg.tls.enable}"; "PARENT" = "microvm@${cfg.name}.service"; - "APPLICATIONS" = "${cfg.applications}"; + "APPLICATIONS" = "${builtins.toJSON cfg.applications}"; "ADMIN_SERVER_NAME" = "${cfg.admin.name}"; "ADMIN_SERVER_ADDR" = "${cfg.admin.addr}"; "ADMIN_SERVER_PORT" = "${cfg.admin.port}"; diff --git a/nixos/packages/givc-agent.nix b/nixos/packages/givc-agent.nix index 330b104..8285e6e 100644 --- a/nixos/packages/givc-agent.nix +++ b/nixos/packages/givc-agent.nix @@ -3,13 +3,14 @@ { pkgs, src }: pkgs.buildGoModule { pname = "givc-agent"; - version = "0.0.1"; + version = "0.0.2"; inherit src; - vendorHash = "sha256-6732pQNGtc8oKbNoCffa8Rp1gxWmcTIie2pieU0Ik3c="; + vendorHash = "sha256-QXzrdiRtd1eugUyWQQYaBthMNbiRoqiWW1y8MZV0d20="; subPackages = [ "internal/pkgs/grpc" "internal/pkgs/servicemanager" "internal/pkgs/serviceclient" + "internal/pkgs/applications" "internal/pkgs/utility" "internal/cmd/givc-agent" ]; diff --git a/nixos/tests/admin.nix b/nixos/tests/admin.nix index 8ba7825..e6e07ee 100644 --- a/nixos/tests/admin.nix +++ b/nixos/tests/admin.nix @@ -199,12 +199,16 @@ in addr = addrs.appvm; admin = adminSettings; tls = mkTls "chromium-vm"; - applications = lib.mkForce ( - builtins.toJSON { - "foot" = "/run/current-system/sw/bin/run-waypipe ${pkgs.foot}/bin/foot"; - "clearexit" = "/run/current-system/sw/bin/sleep 5"; + applications = [ + { + name = "foot"; + command = "/run/current-system/sw/bin/run-waypipe ${pkgs.foot}/bin/foot"; } - ); + { + name = "clearexit"; + command = "/run/current-system/sw/bin/sleep 5"; + } + ]; }; }; }; diff --git a/src/admin/server.rs b/src/admin/server.rs index 0b23bb1..9f670c0 100644 --- a/src/admin/server.rs +++ b/src/admin/server.rs @@ -259,7 +259,7 @@ impl AdminServiceImpl { let endpoint = self.agent_endpoint(&systemd_agent)?; let client = SystemDClient::new(endpoint.clone()); let app_name = self.registry.create_unique_entry_name(&name.to_string()); - client.start_application(app_name.clone()).await?; + client.start_application(app_name.clone(), req.args).await?; let status = client.get_remote_status(app_name.clone()).await?; if status.active_state != "active" { bail!("cannot start unit: {app_name}") diff --git a/src/bin/givc-cli.rs b/src/bin/givc-cli.rs index f9e41ac..2892e67 100644 --- a/src/bin/givc-cli.rs +++ b/src/bin/givc-cli.rs @@ -42,9 +42,11 @@ struct Cli { #[derive(Debug, Subcommand)] enum Commands { Start { + app: String, #[arg(long)] vm: Option, - app: String, + #[arg(last = true)] + args: Vec, }, Stop { app: String, @@ -132,7 +134,7 @@ async fn main() -> std::result::Result<(), Box> { match cli.command { Commands::Test { test } => test_subcommands(test, admin).await?, - Commands::Start { app, vm } => admin.start(app, vm).await?, + Commands::Start { app, vm, args } => admin.start(app, vm, args).await?, Commands::Stop { app } => admin.stop(app).await?, Commands::Pause { app } => admin.pause(app).await?, Commands::Resume { app } => admin.resume(app).await?, diff --git a/src/systemd_api/client.rs b/src/systemd_api/client.rs index 371fc67..a260dff 100644 --- a/src/systemd_api/client.rs +++ b/src/systemd_api/client.rs @@ -74,8 +74,15 @@ impl SystemDClient { Ok(status.cmd_status) } - pub async fn start_application(&self, unit: String) -> anyhow::Result { - let request = pb::systemd::UnitRequest { unit_name: unit }; + pub async fn start_application( + &self, + unit: String, + args: Vec, + ) -> anyhow::Result { + let request = pb::systemd::AppUnitRequest { + unit_name: unit, + args: args, + }; let resp = self.connect().await?.start_application(request).await?; let status = resp.into_inner(); Ok(status.cmd_status) diff --git a/src/systemd_api/server.rs b/src/systemd_api/server.rs index 6c73347..e9877a3 100644 --- a/src/systemd_api/server.rs +++ b/src/systemd_api/server.rs @@ -71,7 +71,7 @@ impl pb::systemd::unit_control_service_server::UnitControlService for SystemdSer // } async fn start_application( &self, - _request: tonic::Request, + _request: tonic::Request, ) -> std::result::Result, tonic::Status> { unimplemented!() }