| // Copyright 2019 The Pigweed Authors |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); you may not |
| // use this file except in compliance with the License. You may obtain a copy of |
| // the License at |
| // |
| // https://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
| // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
| // License for the specific language governing permissions and limitations under |
| // the License. |
| package main |
| |
| import ( |
| "context" |
| "errors" |
| "flag" |
| "fmt" |
| "log" |
| "path/filepath" |
| "time" |
| |
| "google.golang.org/grpc" |
| "google.golang.org/grpc/codes" |
| "google.golang.org/grpc/status" |
| |
| pb "pigweed.dev/proto/pw_target_runner/target_runner_pb" |
| ) |
| |
| // Client is a gRPC client that communicates with a TargetRunner service. |
| type Client struct { |
| conn *grpc.ClientConn |
| } |
| |
| // NewClient creates a gRPC client which connects to a gRPC server hosted at the |
| // specified address. |
| func NewClient(host string, port int) (*Client, error) { |
| // The server currently only supports running locally over an insecure |
| // connection. |
| // TODO(frolv): Investigate adding TLS support to the server and client. |
| opts := []grpc.DialOption{grpc.WithInsecure()} |
| |
| conn, err := grpc.Dial(fmt.Sprintf("%s:%d", host, port), opts...) |
| if err != nil { |
| return nil, err |
| } |
| |
| return &Client{conn}, nil |
| } |
| |
| // RunBinary sends a RunBinary RPC to the target runner service. |
| func (c *Client) RunBinary(path string) error { |
| abspath, err := filepath.Abs(path) |
| if err != nil { |
| return err |
| } |
| |
| client := pb.NewTargetRunnerClient(c.conn) |
| req := &pb.RunBinaryRequest{FilePath: abspath} |
| |
| res, err := client.RunBinary(context.Background(), req) |
| if err != nil { |
| return err |
| } |
| |
| fmt.Printf("%s\n", path) |
| fmt.Printf( |
| "Queued for %v, ran in %v\n\n", |
| time.Duration(res.QueueTimeNs), |
| time.Duration(res.RunTimeNs), |
| ) |
| fmt.Println(string(res.Output)) |
| |
| if res.Result != pb.RunStatus_SUCCESS { |
| return errors.New("Binary run was unsuccessful") |
| } |
| |
| return nil |
| } |
| |
| func main() { |
| hostPtr := flag.String("host", "localhost", "Server host") |
| portPtr := flag.Int("port", 8080, "Server port") |
| pathPtr := flag.String("binary", "", "Path to executable file") |
| |
| flag.Parse() |
| |
| if *pathPtr == "" { |
| log.Fatalf("Must provide -binary option") |
| } |
| |
| cli, err := NewClient(*hostPtr, *portPtr) |
| if err != nil { |
| log.Fatalf("Failed to create gRPC client: %v", err) |
| } |
| |
| if err := cli.RunBinary(*pathPtr); err != nil { |
| log.Println("Failed to run executable on target:") |
| log.Println("") |
| |
| s, _ := status.FromError(err) |
| if s.Code() == codes.Unavailable { |
| log.Println(" No pw_target_runner_server is running.") |
| log.Println(" Check that a server has been started for your target.") |
| } else { |
| log.Printf(" %v\n", err) |
| } |
| |
| log.Fatal("") |
| } |
| } |