From 4177c00e751b1f5008bc463da489194118ce6dff Mon Sep 17 00:00:00 2001 From: lorsan Date: Sat, 4 Apr 2026 20:19:16 +0300 Subject: [PATCH] feat: base grpc system and base use --- api/gen/homeops/hub.pb.go | 128 +++++++++++++++++++++++++++++++++ api/gen/homeops/hub_grpc.pb.go | 122 +++++++++++++++++++++++++++++++ api/proto/homeops/hub.proto | 13 ++++ cmd/agent/main.go | 31 ++++++++ cmd/hub/main.go | 24 +++++++ go.mod | 14 +++- go.sum | 41 ++++++++++- internal/agent/grpc/client.go | 1 + internal/hub/grpc/server.go | 19 +++++ 9 files changed, 388 insertions(+), 5 deletions(-) create mode 100644 api/gen/homeops/hub.pb.go create mode 100644 api/gen/homeops/hub_grpc.pb.go create mode 100644 api/proto/homeops/hub.proto create mode 100644 internal/agent/grpc/client.go create mode 100644 internal/hub/grpc/server.go diff --git a/api/gen/homeops/hub.pb.go b/api/gen/homeops/hub.pb.go new file mode 100644 index 0000000..d002a53 --- /dev/null +++ b/api/gen/homeops/hub.pb.go @@ -0,0 +1,128 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.36.11 +// protoc v7.34.1 +// source: homeops/hub.proto + +package homeops + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + emptypb "google.golang.org/protobuf/types/known/emptypb" + reflect "reflect" + sync "sync" + unsafe "unsafe" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type PongResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Pong string `protobuf:"bytes,1,opt,name=pong,proto3" json:"pong,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *PongResponse) Reset() { + *x = PongResponse{} + mi := &file_homeops_hub_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *PongResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PongResponse) ProtoMessage() {} + +func (x *PongResponse) ProtoReflect() protoreflect.Message { + mi := &file_homeops_hub_proto_msgTypes[0] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PongResponse.ProtoReflect.Descriptor instead. +func (*PongResponse) Descriptor() ([]byte, []int) { + return file_homeops_hub_proto_rawDescGZIP(), []int{0} +} + +func (x *PongResponse) GetPong() string { + if x != nil { + return x.Pong + } + return "" +} + +var File_homeops_hub_proto protoreflect.FileDescriptor + +const file_homeops_hub_proto_rawDesc = "" + + "\n" + + "\x11homeops/hub.proto\x1a\x1bgoogle/protobuf/empty.proto\"\"\n" + + "\fPongResponse\x12\x12\n" + + "\x04pong\x18\x01 \x01(\tR\x04pong26\n" + + "\x03Hub\x12/\n" + + "\x04Ping\x12\x16.google.protobuf.Empty\x1a\r.PongResponse\"\x00B google.protobuf.Empty + 0, // 1: Hub.Ping:output_type -> PongResponse + 1, // [1:2] is the sub-list for method output_type + 0, // [0:1] is the sub-list for method input_type + 0, // [0:0] is the sub-list for extension type_name + 0, // [0:0] is the sub-list for extension extendee + 0, // [0:0] is the sub-list for field type_name +} + +func init() { file_homeops_hub_proto_init() } +func file_homeops_hub_proto_init() { + if File_homeops_hub_proto != nil { + return + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: unsafe.Slice(unsafe.StringData(file_homeops_hub_proto_rawDesc), len(file_homeops_hub_proto_rawDesc)), + NumEnums: 0, + NumMessages: 1, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_homeops_hub_proto_goTypes, + DependencyIndexes: file_homeops_hub_proto_depIdxs, + MessageInfos: file_homeops_hub_proto_msgTypes, + }.Build() + File_homeops_hub_proto = out.File + file_homeops_hub_proto_goTypes = nil + file_homeops_hub_proto_depIdxs = nil +} diff --git a/api/gen/homeops/hub_grpc.pb.go b/api/gen/homeops/hub_grpc.pb.go new file mode 100644 index 0000000..7a39a48 --- /dev/null +++ b/api/gen/homeops/hub_grpc.pb.go @@ -0,0 +1,122 @@ +// Code generated by protoc-gen-go-grpc. DO NOT EDIT. +// versions: +// - protoc-gen-go-grpc v1.6.1 +// - protoc v7.34.1 +// source: homeops/hub.proto + +package homeops + +import ( + context "context" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" + emptypb "google.golang.org/protobuf/types/known/emptypb" +) + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +// Requires gRPC-Go v1.64.0 or later. +const _ = grpc.SupportPackageIsVersion9 + +const ( + Hub_Ping_FullMethodName = "/Hub/Ping" +) + +// HubClient is the client API for Hub service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +type HubClient interface { + Ping(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*PongResponse, error) +} + +type hubClient struct { + cc grpc.ClientConnInterface +} + +func NewHubClient(cc grpc.ClientConnInterface) HubClient { + return &hubClient{cc} +} + +func (c *hubClient) Ping(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*PongResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(PongResponse) + err := c.cc.Invoke(ctx, Hub_Ping_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +// HubServer is the server API for Hub service. +// All implementations must embed UnimplementedHubServer +// for forward compatibility. +type HubServer interface { + Ping(context.Context, *emptypb.Empty) (*PongResponse, error) + mustEmbedUnimplementedHubServer() +} + +// UnimplementedHubServer must be embedded to have +// forward compatible implementations. +// +// NOTE: this should be embedded by value instead of pointer to avoid a nil +// pointer dereference when methods are called. +type UnimplementedHubServer struct{} + +func (UnimplementedHubServer) Ping(context.Context, *emptypb.Empty) (*PongResponse, error) { + return nil, status.Error(codes.Unimplemented, "method Ping not implemented") +} +func (UnimplementedHubServer) mustEmbedUnimplementedHubServer() {} +func (UnimplementedHubServer) testEmbeddedByValue() {} + +// UnsafeHubServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to HubServer will +// result in compilation errors. +type UnsafeHubServer interface { + mustEmbedUnimplementedHubServer() +} + +func RegisterHubServer(s grpc.ServiceRegistrar, srv HubServer) { + // If the following call panics, it indicates UnimplementedHubServer was + // embedded by pointer and is nil. This will cause panics if an + // unimplemented method is ever invoked, so we test this at initialization + // time to prevent it from happening at runtime later due to I/O. + if t, ok := srv.(interface{ testEmbeddedByValue() }); ok { + t.testEmbeddedByValue() + } + s.RegisterService(&Hub_ServiceDesc, srv) +} + +func _Hub_Ping_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(emptypb.Empty) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(HubServer).Ping(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Hub_Ping_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(HubServer).Ping(ctx, req.(*emptypb.Empty)) + } + return interceptor(ctx, in, info, handler) +} + +// Hub_ServiceDesc is the grpc.ServiceDesc for Hub service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var Hub_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "Hub", + HandlerType: (*HubServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "Ping", + Handler: _Hub_Ping_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "homeops/hub.proto", +} diff --git a/api/proto/homeops/hub.proto b/api/proto/homeops/hub.proto new file mode 100644 index 0000000..3a45528 --- /dev/null +++ b/api/proto/homeops/hub.proto @@ -0,0 +1,13 @@ +syntax = "proto3"; + +import "google/protobuf/empty.proto"; + +option go_package = "github.com/lorsanstand/HomeOps-Hub/api/gen/homeops;homeops"; + +service Hub { + rpc Ping (google.protobuf.Empty) returns (PongResponse) {} +} + +message PongResponse { + string pong = 1; +} \ No newline at end of file diff --git a/cmd/agent/main.go b/cmd/agent/main.go index 06ab7d0..9b9e4c9 100644 --- a/cmd/agent/main.go +++ b/cmd/agent/main.go @@ -1 +1,32 @@ package main + +import ( + "context" + "log" + "time" + + "github.com/lorsanstand/HomeOps-Hub/api/gen/homeops" + "google.golang.org/grpc" + "google.golang.org/grpc/credentials/insecure" + "google.golang.org/protobuf/types/known/emptypb" +) + +func main() { + conn, err := grpc.Dial("127.0.0.1:6756", grpc.WithTransportCredentials(insecure.NewCredentials())) + if err != nil { + log.Fatalf("dial: %v", err) + } + defer conn.Close() + + client := homeops.NewHubClient(conn) + + ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second) + resp, err := client.Ping(ctx, &emptypb.Empty{}) + if err != nil { + log.Fatalf("dial: %v", err) + } + + defer cancel() + + log.Printf("pong: %+v", resp.Pong) +} diff --git a/cmd/hub/main.go b/cmd/hub/main.go index 06ab7d0..b26c383 100644 --- a/cmd/hub/main.go +++ b/cmd/hub/main.go @@ -1 +1,25 @@ package main + +import ( + "log" + "net" + + "github.com/lorsanstand/HomeOps-Hub/api/gen/homeops" + grpcserver "github.com/lorsanstand/HomeOps-Hub/internal/hub/grpc" + "google.golang.org/grpc" +) + +func main() { + lis, err := net.Listen("tcp", ":6756") + if err != nil { + return + } + + grpcServer := grpc.NewServer() + + srv := &grpcserver.Server{} + homeops.RegisterHubServer(grpcServer, srv) + + log.Println("Start serve") + grpcServer.Serve(lis) +} diff --git a/go.mod b/go.mod index 9b04953..c165978 100644 --- a/go.mod +++ b/go.mod @@ -2,14 +2,22 @@ module github.com/lorsanstand/HomeOps-Hub go 1.26.1 +require ( + github.com/ilyakaznacheev/cleanenv v1.5.0 + github.com/rs/zerolog v1.35.0 + google.golang.org/grpc v1.80.0 + google.golang.org/protobuf v1.36.11 +) + require ( github.com/BurntSushi/toml v1.2.1 // indirect - github.com/ilyakaznacheev/cleanenv v1.5.0 // indirect github.com/joho/godotenv v1.5.1 // indirect github.com/mattn/go-colorable v0.1.14 // indirect github.com/mattn/go-isatty v0.0.20 // indirect - github.com/rs/zerolog v1.35.0 // indirect - golang.org/x/sys v0.29.0 // indirect + golang.org/x/net v0.49.0 // indirect + golang.org/x/sys v0.40.0 // indirect + golang.org/x/text v0.33.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20260120221211-b8f7ae30c516 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect olympos.io/encoding/edn v0.0.0-20201019073823-d3554ca0b0a3 // indirect ) diff --git a/go.sum b/go.sum index fc6972b..f0de907 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,17 @@ github.com/BurntSushi/toml v1.2.1 h1:9F2/+DoOYIOksmaJFPw1tGFy1eDnIJXg+UHjuD8lTak= github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= +github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= +github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= +github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/ilyakaznacheev/cleanenv v1.5.0 h1:0VNZXggJE2OYdXE87bfSSwGxeiGt9moSR2lOrsHHvr4= github.com/ilyakaznacheev/cleanenv v1.5.0/go.mod h1:a5aDzaJrLCQZsazHol1w8InnDcOX0OColm64SlIi6gk= github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= @@ -10,9 +22,34 @@ github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWE github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/rs/zerolog v1.35.0 h1:VD0ykx7HMiMJytqINBsKcbLS+BJ4WYjz+05us+LRTdI= github.com/rs/zerolog v1.35.0/go.mod h1:EjML9kdfa/RMA7h/6z6pYmq1ykOuA8/mjWaEvGI+jcw= +go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64= +go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y= +go.opentelemetry.io/otel v1.39.0 h1:8yPrr/S0ND9QEfTfdP9V+SiwT4E0G7Y5MO7p85nis48= +go.opentelemetry.io/otel v1.39.0/go.mod h1:kLlFTywNWrFyEdH0oj2xK0bFYZtHRYUdv1NklR/tgc8= +go.opentelemetry.io/otel/metric v1.39.0 h1:d1UzonvEZriVfpNKEVmHXbdf909uGTOQjA0HF0Ls5Q0= +go.opentelemetry.io/otel/metric v1.39.0/go.mod h1:jrZSWL33sD7bBxg1xjrqyDjnuzTUB0x1nBERXd7Ftcs= +go.opentelemetry.io/otel/sdk v1.39.0 h1:nMLYcjVsvdui1B/4FRkwjzoRVsMK8uL/cj0OyhKzt18= +go.opentelemetry.io/otel/sdk v1.39.0/go.mod h1:vDojkC4/jsTJsE+kh+LXYQlbL8CgrEcwmt1ENZszdJE= +go.opentelemetry.io/otel/sdk/metric v1.39.0 h1:cXMVVFVgsIf2YL6QkRF4Urbr/aMInf+2WKg+sEJTtB8= +go.opentelemetry.io/otel/sdk/metric v1.39.0/go.mod h1:xq9HEVH7qeX69/JnwEfp6fVq5wosJsY1mt4lLfYdVew= +go.opentelemetry.io/otel/trace v1.39.0 h1:2d2vfpEDmCJ5zVYz7ijaJdOF59xLomrvj7bjt6/qCJI= +go.opentelemetry.io/otel/trace v1.39.0/go.mod h1:88w4/PnZSazkGzz/w84VHpQafiU4EtqqlVdxWy+rNOA= +golang.org/x/net v0.49.0 h1:eeHFmOGUTtaaPSGNmjBKpbng9MulQsJURQUAfUwY++o= +golang.org/x/net v0.49.0/go.mod h1:/ysNB2EvaqvesRkuLAyjI1ycPZlQHM3q01F02UY/MV8= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU= -golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ= +golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/text v0.33.0 h1:B3njUFyqtHDUI5jMn1YIr5B0IE2U0qck04r6d4KPAxE= +golang.org/x/text v0.33.0/go.mod h1:LuMebE6+rBincTi9+xWTY8TztLzKHc/9C1uBCG27+q8= +gonum.org/v1/gonum v0.17.0 h1:VbpOemQlsSMrYmn7T2OUvQ4dqxQXU+ouZFQsZOx50z4= +gonum.org/v1/gonum v0.17.0/go.mod h1:El3tOrEuMpv2UdMrbNlKEh9vd86bmQ6vqIcDwxEOc1E= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260120221211-b8f7ae30c516 h1:sNrWoksmOyF5bvJUcnmbeAmQi8baNhqg5IWaI3llQqU= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260120221211-b8f7ae30c516/go.mod h1:j9x/tPzZkyxcgEFkiKEEGxfvyumM01BEtsW8xzOahRQ= +google.golang.org/grpc v1.80.0 h1:Xr6m2WmWZLETvUNvIUmeD5OAagMw3FiKmMlTdViWsHM= +google.golang.org/grpc v1.80.0/go.mod h1:ho/dLnxwi3EDJA4Zghp7k2Ec1+c2jqup0bFkw07bwF4= +google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= +google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/internal/agent/grpc/client.go b/internal/agent/grpc/client.go new file mode 100644 index 0000000..21e034e --- /dev/null +++ b/internal/agent/grpc/client.go @@ -0,0 +1 @@ +package grpc diff --git a/internal/hub/grpc/server.go b/internal/hub/grpc/server.go new file mode 100644 index 0000000..60b2bf3 --- /dev/null +++ b/internal/hub/grpc/server.go @@ -0,0 +1,19 @@ +package grpc + +import ( + "context" + "log" + + "github.com/lorsanstand/HomeOps-Hub/api/gen/homeops" + "google.golang.org/protobuf/types/known/emptypb" +) + +type Server struct { + homeops.UnimplementedHubServer +} + +func (s *Server) Ping(ctx context.Context, _ *emptypb.Empty) (*homeops.PongResponse, error) { + log.Println("Answer") + return &homeops.PongResponse{Pong: "Huiiii"}, nil + +}