├── .gitignore ├── README.md ├── agentgo-agent ├── cmd │ └── agentgo-agent │ │ └── main.go └── internal │ ├── api │ └── server.go │ └── app │ ├── base.go │ └── linux.go ├── agentgo-server ├── cmd │ └── agentgo-server │ │ └── main.go └── internal │ └── config │ └── opts.go ├── command.proto ├── go.mod ├── go.sum └── pb ├── command.pb.go └── command_grpc.pb.go /.gitignore: -------------------------------------------------------------------------------- 1 | # Binaries for programs and plugins 2 | .DS_Store 3 | *.exe 4 | *.exe~ 5 | *.dll 6 | *.so 7 | *.dylib 8 | 9 | # Test binary, built with `go test -c` 10 | *.test 11 | 12 | # Output of the go coverage tool, specifically when used with LiteIDE 13 | *.out 14 | 15 | # Dependency directories (remove the comment below to include it) 16 | .vscode/ 17 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Welcome to Agentgo! 2 | 3 | Hi! Agentgo is a tool for making remote command executions with **golang**, **protocol buffers (protobuf)** and **grpc**. This is good way to do some operations at agents (let's say clients). This is why it is called **Agentgo**. 4 | 5 | ### Demo 6 | You can watch a demo about how agentgo works. 7 | [![DEMO](https://img.youtube.com/vi/kuIA8ic2cf8/0.jpg)](https://www.youtube.com/watch?v=kuIA8ic2cf8) 8 | 9 | 10 | ### Proto File Update 11 | If you change anything in **command.proto** file, then you need to update auto generated codes with protobuf. To do this, you can use the command below just after you update **command.proto**. 12 | 13 | protoc --go_out=pb --go_opt=paths=source_relative \ 14 | --go-grpc_out=pb --go-grpc_opt=paths=source_relative \ 15 | ./command.proto 16 | 17 | If everything works fine, then you will have two files in **pb** folder. 18 | **person.pb.go** // protobuf 19 | **person_grpc.pb.go** // grpc client and server functions 20 | 21 | ### Resources 22 | https://grpc.io/docs/languages/go/quickstart/ 23 | https://developers.google.com/protocol-buffers/docs/overview 24 | -------------------------------------------------------------------------------- /agentgo-agent/cmd/agentgo-agent/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "log" 5 | "net" 6 | 7 | "github.com/yakuter/agentgo/agentgo-agent/internal/api" 8 | "github.com/yakuter/agentgo/pb" 9 | 10 | "google.golang.org/grpc" 11 | ) 12 | 13 | const ( 14 | port = ":50051" 15 | ) 16 | 17 | func main() { 18 | 19 | // Define listener 20 | lis, err := net.Listen("tcp", port) 21 | if err != nil { 22 | log.Fatalf("failed to listen: %v", err) 23 | } 24 | 25 | // Create grpc server 26 | s := grpc.NewServer() 27 | 28 | // Register server struct to grpc server 29 | api := &api.Server{} 30 | pb.RegisterCommandServiceServer(s, api) 31 | 32 | // Start grpc server 33 | log.Printf("Agent started listening localhost%s", port) 34 | if err := s.Serve(lis); err != nil { 35 | log.Fatalf("failed to serve: %v", err) 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /agentgo-agent/internal/api/server.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "context" 5 | "log" 6 | 7 | "github.com/yakuter/agentgo/agentgo-agent/internal/app" 8 | "github.com/yakuter/agentgo/pb" 9 | ) 10 | 11 | // server is used to implement helloworld.GreeterServer. 12 | type Server struct { 13 | pb.UnimplementedCommandServiceServer 14 | } 15 | 16 | // SayHello implements helloworld.GreeterServer 17 | func (s *Server) Send(ctx context.Context, in *pb.CommandRequest) (*pb.CommandResponse, error) { 18 | 19 | // Log incoming command 20 | log.Printf("\nApplication: %v\nArguments: %v", in.GetApp(), in.GetArgs()) 21 | 22 | // Define Executer interface 23 | var e app.Executer 24 | 25 | // Assign a Linux command to Executer 26 | e = &app.Linux{in.GetApp(), in.GetArgs()} 27 | 28 | // Execute command and retrieve result 29 | result, err := e.Execute() 30 | if err != nil { 31 | log.Println(err) 32 | } 33 | 34 | // Generate grpc response 35 | response := &pb.CommandResponse{ 36 | Result: result, 37 | } 38 | 39 | return response, err 40 | } 41 | -------------------------------------------------------------------------------- /agentgo-agent/internal/app/base.go: -------------------------------------------------------------------------------- 1 | package app 2 | 3 | type Executer interface { 4 | Execute() (string, error) 5 | } 6 | -------------------------------------------------------------------------------- /agentgo-agent/internal/app/linux.go: -------------------------------------------------------------------------------- 1 | package app 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | "os/exec" 7 | ) 8 | 9 | type Linux struct { 10 | App string 11 | Args []string 12 | } 13 | 14 | func (l *Linux) Execute() (string, error) { 15 | var stdout, stderr bytes.Buffer 16 | 17 | cmd := exec.Command(l.App, l.Args...) 18 | cmd.Stdout = &stdout 19 | cmd.Stderr = &stderr 20 | 21 | err := cmd.Run() 22 | outStr, errStr := string(stdout.Bytes()), string(stderr.Bytes()) 23 | if err != nil { 24 | return outStr, fmt.Errorf(errStr) 25 | } 26 | 27 | return outStr, nil 28 | } 29 | -------------------------------------------------------------------------------- /agentgo-server/cmd/agentgo-server/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "flag" 6 | "log" 7 | "os" 8 | "path/filepath" 9 | "time" 10 | 11 | "github.com/yakuter/agentgo/agentgo-server/internal/config" 12 | "github.com/yakuter/agentgo/pb" 13 | 14 | "google.golang.org/grpc" 15 | ) 16 | 17 | const ( 18 | address = "localhost:50051" 19 | ) 20 | 21 | func main() { 22 | 23 | // Create a FlagSet and sets the usage 24 | fs := flag.NewFlagSet(filepath.Base(os.Args[0]), flag.ExitOnError) 25 | 26 | // Configure the options from the flags/config file 27 | opts, err := config.ConfigureOptions(fs, os.Args[1:]) 28 | if err != nil { 29 | config.PrintUsageErrorAndDie(err) 30 | } 31 | 32 | // If -help flag is defined, print help 33 | if opts.ShowHelp { 34 | config.PrintHelpAndDie() 35 | } 36 | 37 | // Set up a connection to the server. 38 | conn, err := grpc.Dial(address, grpc.WithInsecure(), grpc.WithBlock()) 39 | if err != nil { 40 | log.Fatalf("did not connect: %v", err) 41 | } 42 | defer conn.Close() 43 | 44 | // Create and register a new client 45 | c := pb.NewCommandServiceClient(conn) 46 | 47 | // Create the context 48 | ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) 49 | defer cancel() 50 | 51 | // Generate app and arguments to send 52 | command := pb.CommandRequest{ 53 | App: opts.App, 54 | Args: opts.Args, 55 | } 56 | 57 | // Send command 58 | r, err := c.Send(ctx, &command) 59 | if err != nil { 60 | log.Fatalf("could not greet: %v", err) 61 | } 62 | log.Printf("Command Result:\n%s", r.GetResult()) 63 | } 64 | -------------------------------------------------------------------------------- /agentgo-server/internal/config/opts.go: -------------------------------------------------------------------------------- 1 | package config 2 | 3 | import ( 4 | "errors" 5 | "flag" 6 | "fmt" 7 | "log" 8 | "os" 9 | ) 10 | 11 | type arrayFlags []string 12 | 13 | func (i *arrayFlags) String() string { 14 | return "my string representation" 15 | } 16 | 17 | func (i *arrayFlags) Set(value string) error { 18 | *i = append(*i, value) 19 | return nil 20 | } 21 | 22 | var usageStr = ` 23 | Usage: agentgo-server [options] 24 | Server Options: 25 | -app Application to execute command 26 | -arg Arguments for application 27 | 28 | Common Options: 29 | -help Show this message 30 | ` 31 | 32 | func PrintUsageErrorAndDie(err error) { 33 | log.Println(err) 34 | fmt.Println(usageStr) 35 | os.Exit(1) 36 | } 37 | 38 | func PrintHelpAndDie() { 39 | fmt.Println(usageStr) 40 | os.Exit(0) 41 | } 42 | 43 | // Options is main value holder agentgo-server flags. 44 | type Options struct { 45 | App string `json:"app"` 46 | Args arrayFlags `json:"args"` 47 | ShowHelp bool `json:"show_help"` 48 | } 49 | 50 | // ConfigureOptions accepts a flag set and augments it with agentgo-server 51 | // specific flags. On success, an options structure is returned configured 52 | // based on the selected flags. 53 | func ConfigureOptions(fs *flag.FlagSet, args []string) (*Options, error) { 54 | 55 | // Create empty options 56 | opts := &Options{} 57 | 58 | // Define flags 59 | fs.BoolVar(&opts.ShowHelp, "help", false, "Show help message") 60 | fs.StringVar(&opts.App, "app", "", "Application to execute command: ls") 61 | fs.Var(&opts.Args, "arg", "Arguments for application: -lah") 62 | 63 | // Parse arguments and check for errors 64 | if err := fs.Parse(args); err != nil { 65 | return nil, err 66 | } 67 | 68 | // If it is not help and app is empty, return error 69 | if opts.ShowHelp == false && opts.App == "" { 70 | err := errors.New("application argument (-app ) is empty") 71 | return nil, err 72 | } 73 | 74 | return opts, nil 75 | } 76 | -------------------------------------------------------------------------------- /command.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | option go_package = ".;pb"; 4 | 5 | message Command { 6 | string app = 1 [json_name="App"]; 7 | string args = 2 [json_name="Args"]; 8 | string result = 3 [json_name="Result"]; 9 | } 10 | 11 | service CommandService { 12 | rpc Send (CommandRequest) returns (CommandResponse); 13 | } 14 | 15 | // The request message containing the user's name. 16 | message CommandRequest { 17 | string app = 1; 18 | repeated string args = 2; 19 | } 20 | 21 | // The response message containing the greetings 22 | message CommandResponse { 23 | string result = 1; 24 | } -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/yakuter/agentgo 2 | 3 | go 1.15 4 | 5 | require ( 6 | github.com/golang/protobuf v1.4.3 7 | github.com/nats-io/gnatsd v1.4.1 // indirect 8 | github.com/nats-io/nats-server v1.4.1 9 | github.com/nats-io/nuid v1.0.1 // indirect 10 | google.golang.org/grpc v1.33.2 11 | google.golang.org/protobuf v1.25.0 12 | ) 13 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= 2 | github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= 3 | github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= 4 | github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= 5 | github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= 6 | github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= 7 | github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= 8 | github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= 9 | github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= 10 | github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= 11 | github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= 12 | github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 13 | github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 14 | github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= 15 | github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= 16 | github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= 17 | github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= 18 | github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= 19 | github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= 20 | github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM= 21 | github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= 22 | github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= 23 | github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= 24 | github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= 25 | github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 26 | github.com/google/go-cmp v0.5.0 h1:/QaMHBdZ26BB3SSst0Iwl10Epc+xhTquomWX0oZEB6w= 27 | github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 28 | github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 29 | github.com/nats-io/gnatsd v1.4.1 h1:RconcfDeWpKCD6QIIwiVFcvForlXpWeJP7i5/lDLy44= 30 | github.com/nats-io/gnatsd v1.4.1/go.mod h1:nqco77VO78hLCJpIcVfygDP2rPGfsEHkGTUk94uh5DQ= 31 | github.com/nats-io/nats-server v1.4.1 h1:Ul1oSOGNV/L8kjr4v6l2f9Yet6WY+LevH1/7cRZ/qyA= 32 | github.com/nats-io/nats-server v1.4.1/go.mod h1:c8f/fHd2B6Hgms3LtCaI7y6pC4WD1f4SUxcCud5vhBc= 33 | github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw= 34 | github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= 35 | github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= 36 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M= 37 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 38 | golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= 39 | golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= 40 | golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= 41 | golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 42 | golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 43 | golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 44 | golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 45 | golang.org/x/net v0.0.0-20190311183353-d8887717615a h1:oWX7TPOiFAMXLq8o0ikBYfCJVlRHBcsciT5bXOrH628= 46 | golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 47 | golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= 48 | golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 49 | golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 50 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 51 | golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 52 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU= 53 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 54 | golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= 55 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 56 | golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 57 | golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= 58 | golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 59 | golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= 60 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= 61 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 62 | google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= 63 | google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= 64 | google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= 65 | google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= 66 | google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 h1:+kGHl1aib/qcwaRi1CbqBZ1rk19r85MNUf8HaBghugY= 67 | google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= 68 | google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= 69 | google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= 70 | google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= 71 | google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= 72 | google.golang.org/grpc v1.33.2 h1:EQyQC3sa8M+p6Ulc8yy9SWSS2GVwyRc83gAbG8lrl4o= 73 | google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= 74 | google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= 75 | google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= 76 | google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= 77 | google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= 78 | google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= 79 | google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= 80 | google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= 81 | google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= 82 | google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c= 83 | google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= 84 | honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 85 | honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 86 | -------------------------------------------------------------------------------- /pb/command.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-go. DO NOT EDIT. 2 | // versions: 3 | // protoc-gen-go v1.25.0 4 | // protoc v3.13.0 5 | // source: command.proto 6 | 7 | package pb 8 | 9 | import ( 10 | proto "github.com/golang/protobuf/proto" 11 | protoreflect "google.golang.org/protobuf/reflect/protoreflect" 12 | protoimpl "google.golang.org/protobuf/runtime/protoimpl" 13 | reflect "reflect" 14 | sync "sync" 15 | ) 16 | 17 | const ( 18 | // Verify that this generated code is sufficiently up-to-date. 19 | _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) 20 | // Verify that runtime/protoimpl is sufficiently up-to-date. 21 | _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) 22 | ) 23 | 24 | // This is a compile-time assertion that a sufficiently up-to-date version 25 | // of the legacy proto package is being used. 26 | const _ = proto.ProtoPackageIsVersion4 27 | 28 | type Command struct { 29 | state protoimpl.MessageState 30 | sizeCache protoimpl.SizeCache 31 | unknownFields protoimpl.UnknownFields 32 | 33 | App string `protobuf:"bytes,1,opt,name=app,json=App,proto3" json:"app,omitempty"` 34 | Args string `protobuf:"bytes,2,opt,name=args,json=Args,proto3" json:"args,omitempty"` 35 | Result string `protobuf:"bytes,3,opt,name=result,json=Result,proto3" json:"result,omitempty"` 36 | } 37 | 38 | func (x *Command) Reset() { 39 | *x = Command{} 40 | if protoimpl.UnsafeEnabled { 41 | mi := &file_command_proto_msgTypes[0] 42 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 43 | ms.StoreMessageInfo(mi) 44 | } 45 | } 46 | 47 | func (x *Command) String() string { 48 | return protoimpl.X.MessageStringOf(x) 49 | } 50 | 51 | func (*Command) ProtoMessage() {} 52 | 53 | func (x *Command) ProtoReflect() protoreflect.Message { 54 | mi := &file_command_proto_msgTypes[0] 55 | if protoimpl.UnsafeEnabled && x != nil { 56 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 57 | if ms.LoadMessageInfo() == nil { 58 | ms.StoreMessageInfo(mi) 59 | } 60 | return ms 61 | } 62 | return mi.MessageOf(x) 63 | } 64 | 65 | // Deprecated: Use Command.ProtoReflect.Descriptor instead. 66 | func (*Command) Descriptor() ([]byte, []int) { 67 | return file_command_proto_rawDescGZIP(), []int{0} 68 | } 69 | 70 | func (x *Command) GetApp() string { 71 | if x != nil { 72 | return x.App 73 | } 74 | return "" 75 | } 76 | 77 | func (x *Command) GetArgs() string { 78 | if x != nil { 79 | return x.Args 80 | } 81 | return "" 82 | } 83 | 84 | func (x *Command) GetResult() string { 85 | if x != nil { 86 | return x.Result 87 | } 88 | return "" 89 | } 90 | 91 | // The request message containing the user's name. 92 | type CommandRequest struct { 93 | state protoimpl.MessageState 94 | sizeCache protoimpl.SizeCache 95 | unknownFields protoimpl.UnknownFields 96 | 97 | App string `protobuf:"bytes,1,opt,name=app,proto3" json:"app,omitempty"` 98 | Args []string `protobuf:"bytes,2,rep,name=args,proto3" json:"args,omitempty"` 99 | } 100 | 101 | func (x *CommandRequest) Reset() { 102 | *x = CommandRequest{} 103 | if protoimpl.UnsafeEnabled { 104 | mi := &file_command_proto_msgTypes[1] 105 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 106 | ms.StoreMessageInfo(mi) 107 | } 108 | } 109 | 110 | func (x *CommandRequest) String() string { 111 | return protoimpl.X.MessageStringOf(x) 112 | } 113 | 114 | func (*CommandRequest) ProtoMessage() {} 115 | 116 | func (x *CommandRequest) ProtoReflect() protoreflect.Message { 117 | mi := &file_command_proto_msgTypes[1] 118 | if protoimpl.UnsafeEnabled && x != nil { 119 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 120 | if ms.LoadMessageInfo() == nil { 121 | ms.StoreMessageInfo(mi) 122 | } 123 | return ms 124 | } 125 | return mi.MessageOf(x) 126 | } 127 | 128 | // Deprecated: Use CommandRequest.ProtoReflect.Descriptor instead. 129 | func (*CommandRequest) Descriptor() ([]byte, []int) { 130 | return file_command_proto_rawDescGZIP(), []int{1} 131 | } 132 | 133 | func (x *CommandRequest) GetApp() string { 134 | if x != nil { 135 | return x.App 136 | } 137 | return "" 138 | } 139 | 140 | func (x *CommandRequest) GetArgs() []string { 141 | if x != nil { 142 | return x.Args 143 | } 144 | return nil 145 | } 146 | 147 | // The response message containing the greetings 148 | type CommandResponse struct { 149 | state protoimpl.MessageState 150 | sizeCache protoimpl.SizeCache 151 | unknownFields protoimpl.UnknownFields 152 | 153 | Result string `protobuf:"bytes,1,opt,name=result,proto3" json:"result,omitempty"` 154 | } 155 | 156 | func (x *CommandResponse) Reset() { 157 | *x = CommandResponse{} 158 | if protoimpl.UnsafeEnabled { 159 | mi := &file_command_proto_msgTypes[2] 160 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 161 | ms.StoreMessageInfo(mi) 162 | } 163 | } 164 | 165 | func (x *CommandResponse) String() string { 166 | return protoimpl.X.MessageStringOf(x) 167 | } 168 | 169 | func (*CommandResponse) ProtoMessage() {} 170 | 171 | func (x *CommandResponse) ProtoReflect() protoreflect.Message { 172 | mi := &file_command_proto_msgTypes[2] 173 | if protoimpl.UnsafeEnabled && x != nil { 174 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 175 | if ms.LoadMessageInfo() == nil { 176 | ms.StoreMessageInfo(mi) 177 | } 178 | return ms 179 | } 180 | return mi.MessageOf(x) 181 | } 182 | 183 | // Deprecated: Use CommandResponse.ProtoReflect.Descriptor instead. 184 | func (*CommandResponse) Descriptor() ([]byte, []int) { 185 | return file_command_proto_rawDescGZIP(), []int{2} 186 | } 187 | 188 | func (x *CommandResponse) GetResult() string { 189 | if x != nil { 190 | return x.Result 191 | } 192 | return "" 193 | } 194 | 195 | var File_command_proto protoreflect.FileDescriptor 196 | 197 | var file_command_proto_rawDesc = []byte{ 198 | 0x0a, 0x0d, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 199 | 0x47, 0x0a, 0x07, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x61, 0x70, 200 | 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x41, 0x70, 0x70, 0x12, 0x12, 0x0a, 0x04, 201 | 0x61, 0x72, 0x67, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x41, 0x72, 0x67, 0x73, 202 | 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 203 | 0x52, 0x06, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x22, 0x36, 0x0a, 0x0e, 0x43, 0x6f, 0x6d, 0x6d, 204 | 0x61, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x61, 0x70, 205 | 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x61, 0x70, 0x70, 0x12, 0x12, 0x0a, 0x04, 206 | 0x61, 0x72, 0x67, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x04, 0x61, 0x72, 0x67, 0x73, 207 | 0x22, 0x29, 0x0a, 0x0f, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 208 | 0x6e, 0x73, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x01, 0x20, 209 | 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x32, 0x3b, 0x0a, 0x0e, 0x43, 210 | 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x29, 0x0a, 211 | 0x04, 0x53, 0x65, 0x6e, 0x64, 0x12, 0x0f, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x52, 212 | 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x10, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 213 | 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x06, 0x5a, 0x04, 0x2e, 0x3b, 0x70, 0x62, 214 | 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, 215 | } 216 | 217 | var ( 218 | file_command_proto_rawDescOnce sync.Once 219 | file_command_proto_rawDescData = file_command_proto_rawDesc 220 | ) 221 | 222 | func file_command_proto_rawDescGZIP() []byte { 223 | file_command_proto_rawDescOnce.Do(func() { 224 | file_command_proto_rawDescData = protoimpl.X.CompressGZIP(file_command_proto_rawDescData) 225 | }) 226 | return file_command_proto_rawDescData 227 | } 228 | 229 | var file_command_proto_msgTypes = make([]protoimpl.MessageInfo, 3) 230 | var file_command_proto_goTypes = []interface{}{ 231 | (*Command)(nil), // 0: Command 232 | (*CommandRequest)(nil), // 1: CommandRequest 233 | (*CommandResponse)(nil), // 2: CommandResponse 234 | } 235 | var file_command_proto_depIdxs = []int32{ 236 | 1, // 0: CommandService.Send:input_type -> CommandRequest 237 | 2, // 1: CommandService.Send:output_type -> CommandResponse 238 | 1, // [1:2] is the sub-list for method output_type 239 | 0, // [0:1] is the sub-list for method input_type 240 | 0, // [0:0] is the sub-list for extension type_name 241 | 0, // [0:0] is the sub-list for extension extendee 242 | 0, // [0:0] is the sub-list for field type_name 243 | } 244 | 245 | func init() { file_command_proto_init() } 246 | func file_command_proto_init() { 247 | if File_command_proto != nil { 248 | return 249 | } 250 | if !protoimpl.UnsafeEnabled { 251 | file_command_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { 252 | switch v := v.(*Command); i { 253 | case 0: 254 | return &v.state 255 | case 1: 256 | return &v.sizeCache 257 | case 2: 258 | return &v.unknownFields 259 | default: 260 | return nil 261 | } 262 | } 263 | file_command_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { 264 | switch v := v.(*CommandRequest); i { 265 | case 0: 266 | return &v.state 267 | case 1: 268 | return &v.sizeCache 269 | case 2: 270 | return &v.unknownFields 271 | default: 272 | return nil 273 | } 274 | } 275 | file_command_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { 276 | switch v := v.(*CommandResponse); i { 277 | case 0: 278 | return &v.state 279 | case 1: 280 | return &v.sizeCache 281 | case 2: 282 | return &v.unknownFields 283 | default: 284 | return nil 285 | } 286 | } 287 | } 288 | type x struct{} 289 | out := protoimpl.TypeBuilder{ 290 | File: protoimpl.DescBuilder{ 291 | GoPackagePath: reflect.TypeOf(x{}).PkgPath(), 292 | RawDescriptor: file_command_proto_rawDesc, 293 | NumEnums: 0, 294 | NumMessages: 3, 295 | NumExtensions: 0, 296 | NumServices: 1, 297 | }, 298 | GoTypes: file_command_proto_goTypes, 299 | DependencyIndexes: file_command_proto_depIdxs, 300 | MessageInfos: file_command_proto_msgTypes, 301 | }.Build() 302 | File_command_proto = out.File 303 | file_command_proto_rawDesc = nil 304 | file_command_proto_goTypes = nil 305 | file_command_proto_depIdxs = nil 306 | } 307 | -------------------------------------------------------------------------------- /pb/command_grpc.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-go-grpc. DO NOT EDIT. 2 | 3 | package pb 4 | 5 | import ( 6 | context "context" 7 | grpc "google.golang.org/grpc" 8 | codes "google.golang.org/grpc/codes" 9 | status "google.golang.org/grpc/status" 10 | ) 11 | 12 | // This is a compile-time assertion to ensure that this generated file 13 | // is compatible with the grpc package it is being compiled against. 14 | const _ = grpc.SupportPackageIsVersion7 15 | 16 | // CommandServiceClient is the client API for CommandService service. 17 | // 18 | // 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. 19 | type CommandServiceClient interface { 20 | Send(ctx context.Context, in *CommandRequest, opts ...grpc.CallOption) (*CommandResponse, error) 21 | } 22 | 23 | type commandServiceClient struct { 24 | cc grpc.ClientConnInterface 25 | } 26 | 27 | func NewCommandServiceClient(cc grpc.ClientConnInterface) CommandServiceClient { 28 | return &commandServiceClient{cc} 29 | } 30 | 31 | func (c *commandServiceClient) Send(ctx context.Context, in *CommandRequest, opts ...grpc.CallOption) (*CommandResponse, error) { 32 | out := new(CommandResponse) 33 | err := c.cc.Invoke(ctx, "/CommandService/Send", in, out, opts...) 34 | if err != nil { 35 | return nil, err 36 | } 37 | return out, nil 38 | } 39 | 40 | // CommandServiceServer is the server API for CommandService service. 41 | // All implementations must embed UnimplementedCommandServiceServer 42 | // for forward compatibility 43 | type CommandServiceServer interface { 44 | Send(context.Context, *CommandRequest) (*CommandResponse, error) 45 | mustEmbedUnimplementedCommandServiceServer() 46 | } 47 | 48 | // UnimplementedCommandServiceServer must be embedded to have forward compatible implementations. 49 | type UnimplementedCommandServiceServer struct { 50 | } 51 | 52 | func (UnimplementedCommandServiceServer) Send(context.Context, *CommandRequest) (*CommandResponse, error) { 53 | return nil, status.Errorf(codes.Unimplemented, "method Send not implemented") 54 | } 55 | func (UnimplementedCommandServiceServer) mustEmbedUnimplementedCommandServiceServer() {} 56 | 57 | // UnsafeCommandServiceServer may be embedded to opt out of forward compatibility for this service. 58 | // Use of this interface is not recommended, as added methods to CommandServiceServer will 59 | // result in compilation errors. 60 | type UnsafeCommandServiceServer interface { 61 | mustEmbedUnimplementedCommandServiceServer() 62 | } 63 | 64 | func RegisterCommandServiceServer(s grpc.ServiceRegistrar, srv CommandServiceServer) { 65 | s.RegisterService(&_CommandService_serviceDesc, srv) 66 | } 67 | 68 | func _CommandService_Send_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { 69 | in := new(CommandRequest) 70 | if err := dec(in); err != nil { 71 | return nil, err 72 | } 73 | if interceptor == nil { 74 | return srv.(CommandServiceServer).Send(ctx, in) 75 | } 76 | info := &grpc.UnaryServerInfo{ 77 | Server: srv, 78 | FullMethod: "/CommandService/Send", 79 | } 80 | handler := func(ctx context.Context, req interface{}) (interface{}, error) { 81 | return srv.(CommandServiceServer).Send(ctx, req.(*CommandRequest)) 82 | } 83 | return interceptor(ctx, in, info, handler) 84 | } 85 | 86 | var _CommandService_serviceDesc = grpc.ServiceDesc{ 87 | ServiceName: "CommandService", 88 | HandlerType: (*CommandServiceServer)(nil), 89 | Methods: []grpc.MethodDesc{ 90 | { 91 | MethodName: "Send", 92 | Handler: _CommandService_Send_Handler, 93 | }, 94 | }, 95 | Streams: []grpc.StreamDesc{}, 96 | Metadata: "command.proto", 97 | } 98 | --------------------------------------------------------------------------------