// setUpIntermediate sets up a test intermediate server. func setUpIntermediate(name string, addr string) (fixture, error) { var ( fix fixture err error ) fix.server, err = MakeTestIntermediateServer( name, addr, &pb.ResourceTemplate{ IdentifierGlob: proto.String("*"), Capacity: proto.Float64(100), SafeCapacity: proto.Float64(2), Algorithm: &pb.Algorithm{ Kind: pb.Algorithm_PROPORTIONAL_SHARE.Enum(), RefreshInterval: proto.Int64(1), LeaseLength: proto.Int64(2), }, }) if err != nil { return fixture{}, err } lis, err := net.Listen("tcp", ":0") if err != nil { return fixture{}, err } fix.lis = lis fix.rpcServer = rpc.NewServer() pb.RegisterCapacityServer(fix.rpcServer, fix.server) go fix.rpcServer.Serve(lis) conn, err := rpc.Dial(fix.Addr(), rpc.WithInsecure()) if err != nil { return fixture{}, err } fix.client = pb.NewCapacityClient(conn) return fix, nil }
func main() { flag.Parse() if err := flagenv.Populate(flag.CommandLine, "DOORMAN"); err != nil { log.Exit(err) } if *config == "" { log.Exit("--config cannot be empty") } var ( etcdEndpointsSlice = strings.Split(*etcdEndpoints, ",") masterElection election.Election ) if *masterElectionLock != "" { if len(etcdEndpointsSlice) == 1 && etcdEndpointsSlice[0] == "" { log.Exit("-etcd_endpoints cannot be empty if -master_election_lock is provided") } masterElection = election.Etcd(etcdEndpointsSlice, *masterElectionLock, *masterDelay) } else { masterElection = election.Trivial() } dm, err := doorman.New(context.Background(), getServerID(*port), *parent, masterElection, connection.MinimumRefreshInterval(*minimumRefreshInterval), connection.DialOpts( rpc.WithTimeout(*rpcDialTimeout))) if err != nil { log.Exitf("doorman.NewIntermediate: %v", err) } var opts []rpc.ServerOption if *tls { log.Infof("Loading credentials from %v and %v.", *certFile, *keyFile) creds, err := credentials.NewServerTLSFromFile(*certFile, *keyFile) if err != nil { log.Exitf("Failed to generate credentials %v", err) } opts = []rpc.ServerOption{rpc.Creds(creds)} } server := rpc.NewServer(opts...) pb.RegisterCapacityServer(server, dm) if *config == "" { log.Exit("-config cannot be empty") } var cfg configuration.Source kind, path := configuration.ParseSource(*config) switch { case kind == "file": cfg = configuration.LocalFile(path) case kind == "etcd": if len(etcdEndpointsSlice) == 1 && etcdEndpointsSlice[0] == "" { log.Exit("-etcd_endpoints cannot be empty if a config source etcd is provided") } cfg = configuration.Etcd(path, etcdEndpointsSlice) default: panic("unreachable") } // Try to load the background. If there's a problem with loading // the server for the first time, the server will keep running, // but will not serve traffic. go func() { for { data, err := cfg(context.Background()) if err != nil { log.Errorf("cannot load config data: %v", err) continue } cfg := new(pb.ResourceRepository) if err := yaml.Unmarshal(data, cfg); err != nil { log.Errorf("cannot unmarshal config data: %q", data) continue } if err := dm.LoadConfig(context.Background(), cfg, map[string]*time.Time{}); err != nil { log.Errorf("cannot load config: %v", err) } } }() status.AddStatusPart("Doorman", statusz, func(context.Context) interface{} { return dm.Status() }) // Redirect form / to /debug/status. http.Handle("/", http.RedirectHandler("/debug/status", http.StatusMovedPermanently)) AddServer(dm) http.Handle("/metrics", prometheus.Handler()) go http.ListenAndServe(fmt.Sprintf(":%v", *debugPort), nil) // Waits for the server to get its initial configuration. This guarantees that // the server will never run without a valid configuration. log.Info("Waiting for the server to be configured...") dm.WaitUntilConfigured() // Runs the server. log.Info("Server is configured, ready to go!") lis, err := net.Listen("tcp", fmt.Sprintf(":%d", *port)) if err != nil { log.Exit(err) } server.Serve(lis) }