blob: 8c18912c73fdd8054d27ca25ae9e327a09f56b6a [file] [log] [blame]
// 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 (
"errors"
"flag"
"fmt"
"io/ioutil"
"log"
"github.com/golang/protobuf/proto"
"pigweed.dev/pw_target_runner"
pb "pigweed.dev/proto/pw_target_runner/exec_server_config_pb"
)
// ServerOptions contains command-line options for the server.
type ServerOptions struct {
// Path to a server configuration file.
config string
// Port on which to run.
port int
}
// configureServerFromFile sets up the server with workers specifyed in a
// config file. The file contains a pw.target_runner.ServerConfig protobuf
// message in canonical protobuf text format.
func configureServerFromFile(s *pw_target_runner.Server, filepath string) error {
content, err := ioutil.ReadFile(filepath)
if err != nil {
return err
}
var config pb.ServerConfig
if err := proto.UnmarshalText(string(content), &config); err != nil {
return err
}
log.Printf("Parsed server configuration from %s\n", filepath)
runners := config.GetRunner()
if runners == nil {
return nil
}
// Create an exec worker for each of the runner messages listed in the
// config and register them with the server.
for i, runner := range runners {
// Build the complete command for the worker from its "command"
// and "args" fields in the proto message. The command is
// required; arguments are optional.
cmd := []string{runner.GetCommand()}
if cmd[0] == "" {
msg := fmt.Sprintf(
"ServerConfig.runner[%d] does not specify a command; skipping\n", i)
return errors.New(msg)
}
if args := runner.GetArgs(); args != nil {
cmd = append(cmd, args...)
}
worker := pw_target_runner.NewExecDeviceRunner(i, cmd)
s.RegisterWorker(worker)
log.Printf(
"Registered ExecDeviceRunner %s with args %v\n",
cmd[0],
cmd[1:])
}
return nil
}
func main() {
configPtr := flag.String("config", "", "Path to server configuration file")
portPtr := flag.Int("port", 8080, "Server port")
flag.Parse()
server := pw_target_runner.NewServer()
if *configPtr != "" {
if err := configureServerFromFile(server, *configPtr); err != nil {
log.Fatalf("Failed to parse config file %s: %v", *configPtr, err)
}
}
if err := server.Bind(*portPtr); err != nil {
log.Fatal(err)
}
if err := server.Serve(); err != nil {
log.Fatalf("Failed to start server: %v", err)
}
}