func Run(name string, args []string) error { argv := make([]string, 1, 1+len(args)) argv[0] = name argv = append(argv, args...) cmd, ok := commands[name] if !ok { return fmt.Errorf("%s is not a valid command", name) } parsedArgs, err := docopt.Parse(cmd.usage, argv, true, "", false) if err != nil { return err } switch f := cmd.f.(type) { case func(*docopt.Args, cluster.Host) error: rc, err := rpcplus.DialHTTPPath("tcp", localAddr, rpcplus.DefaultRPCPath, nil) if err != nil { return errors.New("error connecting to local flynn-host, is it running?") } client := cluster.NewHostClient(localAddr, rc, nil) return f(parsedArgs, client) case func(*docopt.Args): f(parsedArgs) return nil } return fmt.Errorf("unexpected command type %T", cmd.f) }
func (c *Client) DialHost(id string) (Host, error) { // TODO: reuse connection if leader id == id services := c.service.Select(map[string]string{"id": id}) if len(services) == 0 { return nil, ErrNoServers } rc, err := rpcplus.DialHTTPPath("tcp", services[0].Addr, rpcplus.DefaultRPCPath, c.dial) return newHostClient(c.service, rc, c.dial), err }
func (c *Client) followLeader(firstErr chan<- error) { for update := range c.service.Leaders() { if update == nil { if firstErr != nil { firstErr <- ErrNoServers c.Close() return } continue } c.mtx.Lock() if c.c != nil { c.c.Close() c.c = nil } c.leaderID = update.Attrs["id"] if c.leaderID != c.selfID { c.err = Attempts.Run(func() (err error) { c.c, err = rpcplus.DialHTTPPath("tcp", update.Addr, rpcplus.DefaultRPCPath, c.dial) return }) } if c.err == nil { close(c.leaderChange) c.leaderChange = make(chan struct{}) } c.mtx.Unlock() if firstErr != nil { firstErr <- c.err if c.err != nil { c.c = nil c.Close() return } firstErr = nil } } // TODO: reconnect to discoverd here }