// LaunchHTTP starts an HTTP server for the Resolver, returning a error channel // to which errors are asynchronously sent. func (res *Resolver) LaunchHTTP() <-chan error { defer util.HandleCrash() res.configureHTTP() listenAddress := net.JoinHostPort(res.config.HTTPListener, strconv.Itoa(res.config.HTTPPort)) errCh := make(chan error, 1) go func() { var err error defer func() { errCh <- err }() if err = http.ListenAndServe(listenAddress, nil); err != nil { err = fmt.Errorf("Failed to setup http server: %v", err) } else { logging.Error.Println("Not serving http requests any more.") } }() return errCh }
// Serve starts a DNS server for net protocol (tcp/udp), returns immediately. // the returned signal chan is closed upon the server successfully entering the listening phase. // if the server aborts then an error is sent on the error chan. func (res *Resolver) Serve(proto string) (<-chan struct{}, <-chan error) { defer util.HandleCrash() ch := make(chan struct{}) server := &dns.Server{ Addr: net.JoinHostPort(res.config.Listener, strconv.Itoa(res.config.Port)), Net: proto, TsigSecret: nil, NotifyStartedFunc: func() { close(ch) }, } errCh := make(chan error, 1) go func() { defer close(errCh) err := server.ListenAndServe() if err != nil { errCh <- fmt.Errorf("Failed to setup %q server: %v", proto, err) } else { logging.Error.Printf("Not listening/serving any more requests.") } }() return ch, errCh }
// launches Zookeeper detector, returns immediately two chans: the first fires an empty // struct whenever there's a new (non-nil) mesos leader, the second if there's an unrecoverable // error in the master detector. func (res *Resolver) LaunchZK(initialDetectionTimeout time.Duration) (<-chan struct{}, <-chan error) { var startedOnce sync.Once startedCh := make(chan struct{}) errCh := make(chan error, 1) leaderCh := make(chan struct{}, 1) // the first write never blocks listenerFunc := func(newLeader string) { defer func() { if newLeader != "" { leaderCh <- struct{}{} startedOnce.Do(func() { close(startedCh) }) } }() res.leaderLock.Lock() defer res.leaderLock.Unlock() res.leader = newLeader } go func() { defer util.HandleCrash() err := res.startZKdetection(res.config.Zk, listenerFunc) if err != nil { errCh <- err return } logging.VeryVerbose.Println("Warning: waiting for initial information from Zookeper.") select { case <-startedCh: logging.VeryVerbose.Println("Info: got initial information from Zookeper.") case <-time.After(initialDetectionTimeout): errCh <- fmt.Errorf("timed out waiting for initial ZK detection, exiting") } }() return leaderCh, errCh }
func main() { util.PanicHandlers = append(util.PanicHandlers, func(_ interface{}) { // by default the handler already logs the panic os.Exit(1) }) var versionFlag bool // parse flags cjson := flag.String("config", "config.json", "path to config file (json)") flag.BoolVar(&versionFlag, "version", false, "output the version") flag.Parse() // -version if versionFlag { fmt.Println(Version) os.Exit(0) } // initialize logging logging.SetupLogs() // initialize resolver config := records.SetConfig(*cjson) res := resolver.New(Version, config) errch := make(chan error) // launch DNS server if config.DNSOn { go func() { errch <- <-res.LaunchDNS() }() } // launch HTTP server if config.HTTPOn { go func() { errch <- <-res.LaunchHTTP() }() } changed := detectMasters(config.Zk, config.Masters) reload := time.NewTicker(time.Second * time.Duration(config.RefreshSeconds)) zkTimeout := time.Second * time.Duration(config.ZkDetectionTimeout) timeout := time.AfterFunc(zkTimeout, func() { if zkTimeout > 0 { errch <- fmt.Errorf("master detection timed out after %s", zkTimeout) } }) defer reload.Stop() defer util.HandleCrash() for { select { case <-reload.C: res.Reload() case masters := <-changed: if len(masters) == 0 || masters[0] == "" { // no leader timeout.Reset(zkTimeout) } else { timeout.Stop() } logging.VeryVerbose.Printf("new masters detected: %v", masters) res.SetMasters(masters) res.Reload() case err := <-errch: logging.Error.Fatal(err) } } }
func main() { util.PanicHandlers = append(util.PanicHandlers, func(_ interface{}) { // by default the handler already logs the panic os.Exit(1) }) var versionFlag bool // parse flags cjson := flag.String("config", "config.json", "path to config file (json)") flag.BoolVar(&versionFlag, "version", false, "output the version") flag.Parse() // -version if versionFlag { fmt.Println(version) os.Exit(0) } // initialize logging logging.SetupLogs() // initialize resolver config := records.SetConfig(*cjson) res := resolver.New(version, config) errch := make(chan error) // launch DNS server if config.DNSOn { go func() { errch <- <-res.LaunchDNS() }() } // launch HTTP server if config.HTTPOn { go func() { errch <- <-res.LaunchHTTP() }() } changed := make(chan []string, 1) if config.Zk != "" { logging.Verbose.Println("Starting master detector for ZK ", config.Zk) if md, err := detector.New(config.Zk); err != nil { log.Fatalf("failed to create master detector: %v", err) } else if err := md.Detect(detect.NewMasters(config.Masters, changed)); err != nil { log.Fatalf("failed to initialize master detector: %v", err) } } else { changed <- config.Masters } reload := time.NewTicker(time.Second * time.Duration(config.RefreshSeconds)) timeout := time.AfterFunc(zkInitialDetectionTimeout, func() { errch <- fmt.Errorf("master detection timed out after %s", zkInitialDetectionTimeout) }) defer reload.Stop() defer util.HandleCrash() for { select { case <-reload.C: res.Reload() case masters := <-changed: timeout.Stop() logging.VeryVerbose.Printf("new masters detected: %v", masters) res.SetMasters(masters) res.Reload() case err := <-errch: logging.Error.Fatal(err) } } }
// Provide allows the provider to provide configurations to traefik // using the given configuration channel. func (provider *Mesos) Provide(configurationChan chan<- types.ConfigMessage, pool *safe.Pool, constraints types.Constraints) error { operation := func() error { // initialize logging logging.SetupLogs() log.Debugf("%s", provider.IPSources) var zk string var masters []string if strings.HasPrefix(provider.Endpoint, "zk://") { zk = provider.Endpoint } else { masters = strings.Split(provider.Endpoint, ",") } errch := make(chan error) changed := detectMasters(zk, masters) reload := time.NewTicker(time.Second * time.Duration(provider.RefreshSeconds)) zkTimeout := time.Second * time.Duration(provider.ZkDetectionTimeout) timeout := time.AfterFunc(zkTimeout, func() { if zkTimeout > 0 { errch <- fmt.Errorf("master detection timed out after %s", zkTimeout) } }) defer reload.Stop() defer util.HandleCrash() if !provider.Watch { reload.Stop() timeout.Stop() } for { select { case <-reload.C: configuration := provider.loadMesosConfig() if configuration != nil { configurationChan <- types.ConfigMessage{ ProviderName: "mesos", Configuration: configuration, } } case masters := <-changed: if len(masters) == 0 || masters[0] == "" { // no leader timeout.Reset(zkTimeout) } else { timeout.Stop() } log.Debugf("new masters detected: %v", masters) provider.Masters = masters configuration := provider.loadMesosConfig() if configuration != nil { configurationChan <- types.ConfigMessage{ ProviderName: "mesos", Configuration: configuration, } } case err := <-errch: log.Errorf("%s", err) } } } notify := func(err error, time time.Duration) { log.Errorf("mesos connection error %+v, retrying in %s", err, time) } err := backoff.RetryNotify(operation, job.NewBackOff(backoff.NewExponentialBackOff()), notify) if err != nil { log.Errorf("Cannot connect to mesos server %+v", err) } return nil }
func main() { util.PanicHandlers = append(util.PanicHandlers, func(_ interface{}) { // by default the handler already logs the panic os.Exit(1) }) var versionFlag bool // parse flags cjson := flag.String("config", "config.json", "path to config file (json)") flag.BoolVar(&versionFlag, "version", false, "output the version") flag.Parse() // -version if versionFlag { fmt.Println(version) os.Exit(0) } // initialize logging logging.SetupLogs() // initialize resolver config := records.SetConfig(*cjson) resolver := resolver.New(version, config) var dnsErr, httpErr, zkErr <-chan error var newLeader <-chan struct{} // launch DNS server if config.DNSOn { dnsErr = resolver.LaunchDNS() } // launch HTTP server if config.HTTPOn { httpErr = resolver.LaunchHTTP() } // launch Zookeeper listener if config.Zk != "" { newLeader, zkErr = resolver.LaunchZK(zkInitialDetectionTimeout) } else { // uniform behavior when new leader from masters field leader := make(chan struct{}, 1) leader <- struct{}{} newLeader = leader } // print error and terminate handleServerErr := func(name string, err error) { if err != nil { logging.Error.Fatalf("%s failed: %v", name, err) } else { logging.Error.Fatalf("%s stopped unexpectedly", name) } } // generate reload signal; up to 1 reload pending at any time reloadSignal := make(chan struct{}, 1) tryReload := func() { // non-blocking, attempt to queue a reload select { case reloadSignal <- struct{}{}: default: } } // periodic loading of DNS state (pull from Master) go func() { defer util.HandleCrash() reloadTimeout := time.Second * time.Duration(config.RefreshSeconds) reloadTimer := time.AfterFunc(reloadTimeout, tryReload) for _ = range reloadSignal { resolver.Reload() logging.PrintCurLog() reloadTimer.Reset(reloadTimeout) } }() // infinite loop until there is fatal error for { select { case <-newLeader: tryReload() case err := <-dnsErr: handleServerErr("DNS server", err) case err := <-httpErr: handleServerErr("HTTP server", err) case err := <-zkErr: handleServerErr("ZK watcher", err) } } }