func main() { kingpin.Parse() fmtlog.SetFlags(fmtlog.Lshortfile | fmtlog.LstdFlags) var srv *graceful.Server var configurationRouter *mux.Router var configurationChan = make(chan *Configuration, 10) defer close(configurationChan) var providers = []Provider{} var format = logging.MustStringFormatter("%{color}%{time:15:04:05.000} %{shortfile:20.20s} %{level:8.8s} %{id:03x} ▶%{color:reset} %{message}") var sigs = make(chan os.Signal, 1) signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM) // load global configuration gloablConfiguration := LoadFileConfig(*globalConfigFile) loggerMiddleware := middlewares.NewLogger(gloablConfiguration.AccessLogsFile) defer loggerMiddleware.Close() // logging backends := []logging.Backend{} level, err := logging.LogLevel(gloablConfiguration.LogLevel) if err != nil { log.Fatal("Error getting level", err) } if len(gloablConfiguration.TraefikLogsFile) > 0 { fi, err := os.OpenFile(gloablConfiguration.TraefikLogsFile, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666) defer fi.Close() if err != nil { log.Fatal("Error opening file", err) } else { logBackend := logging.NewLogBackend(fi, "", 0) logBackendFormatter := logging.NewBackendFormatter(logBackend, logging.GlogFormatter) backends = append(backends, logBackendFormatter) } } if gloablConfiguration.TraefikLogsStdout { logBackend := logging.NewLogBackend(os.Stdout, "", 0) logBackendFormatter := logging.NewBackendFormatter(logBackend, format) backends = append(backends, logBackendFormatter) } logging.SetBackend(backends...) logging.SetLevel(level, "traefik") configurationRouter = LoadDefaultConfig(gloablConfiguration) // listen new configurations from providers go func() { for { configuration := <-configurationChan log.Info("Configuration receveived %+v", configuration) if configuration == nil { log.Info("Skipping empty configuration") } else if reflect.DeepEqual(currentConfiguration, configuration) { log.Info("Skipping same configuration") } else { newConfigurationRouter, err := LoadConfig(configuration, gloablConfiguration) if err == nil { currentConfiguration = configuration configurationRouter = newConfigurationRouter srv.Stop(time.Duration(gloablConfiguration.GraceTimeOut) * time.Second) time.Sleep(3 * time.Second) } else { log.Error("Error loading new configuration, aborted ", err) } } } }() // configure providers if gloablConfiguration.Docker != nil { providers = append(providers, gloablConfiguration.Docker) } if gloablConfiguration.Marathon != nil { providers = append(providers, gloablConfiguration.Marathon) } if gloablConfiguration.File != nil { if len(gloablConfiguration.File.Filename) == 0 { // no filename, setting to global config file gloablConfiguration.File.Filename = *globalConfigFile } providers = append(providers, gloablConfiguration.File) } if gloablConfiguration.Web != nil { providers = append(providers, gloablConfiguration.Web) } if gloablConfiguration.Consul != nil { providers = append(providers, gloablConfiguration.Consul) } // start providers for _, provider := range providers { log.Notice("Starting provider %v %+v", reflect.TypeOf(provider), provider) currentProvider := provider go func() { currentProvider.Provide(configurationChan) }() } goAway := false go func() { sig := <-sigs log.Notice("I have to go... %+v", sig) goAway = true srv.Stop(time.Duration(gloablConfiguration.GraceTimeOut) * time.Second) }() for { if goAway { break } // middlewares var negroni = negroni.New() negroni.Use(metrics) negroni.Use(loggerMiddleware) //negroni.Use(middlewares.NewCircuitBreaker(oxyLogger)) //negroni.Use(middlewares.NewRoutes(configurationRouter)) negroni.UseHandler(configurationRouter) srv = &graceful.Server{ Timeout: time.Duration(gloablConfiguration.GraceTimeOut) * time.Second, NoSignalHandling: true, Server: &http.Server{ Addr: gloablConfiguration.Port, Handler: negroni, }, } go func() { if len(gloablConfiguration.CertFile) > 0 && len(gloablConfiguration.KeyFile) > 0 { srv.ListenAndServeTLS(gloablConfiguration.CertFile, gloablConfiguration.KeyFile) } else { srv.ListenAndServe() } }() log.Notice("Started") <-srv.StopChan() log.Notice("Stopped") } }
func main() { kingpin.Parse() fmtlog.SetFlags(fmtlog.Lshortfile | fmtlog.LstdFlags) var srv *graceful.Server var configurationRouter *mux.Router var configurationChan = make(chan *Configuration, 10) defer close(configurationChan) var providers = []Provider{} var sigs = make(chan os.Signal, 1) signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM) // load global configuration gloablConfiguration := LoadFileConfig(*globalConfigFile) loggerMiddleware := middlewares.NewLogger(gloablConfiguration.AccessLogsFile) defer loggerMiddleware.Close() // logging level, err := log.ParseLevel(strings.ToLower(gloablConfiguration.LogLevel)) if err != nil { log.Fatal("Error getting level", err) } log.SetLevel(level) if len(gloablConfiguration.TraefikLogsFile) > 0 { fi, err := os.OpenFile(gloablConfiguration.TraefikLogsFile, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666) defer fi.Close() if err != nil { log.Fatal("Error opening file", err) } else { log.SetOutput(fi) log.SetFormatter(&log.TextFormatter{DisableColors: true, FullTimestamp: true, DisableSorting: true}) } } else { log.SetFormatter(&log.TextFormatter{FullTimestamp: true, DisableSorting: true}) } configurationRouter = LoadDefaultConfig(gloablConfiguration) // listen new configurations from providers go func() { for { configuration := <-configurationChan log.Infof("Configuration receveived %+v", configuration) if configuration == nil { log.Info("Skipping empty configuration") } else if reflect.DeepEqual(currentConfiguration, configuration) { log.Info("Skipping same configuration") } else { newConfigurationRouter, err := LoadConfig(configuration, gloablConfiguration) if err == nil { currentConfiguration = configuration configurationRouter = newConfigurationRouter srv.Stop(time.Duration(gloablConfiguration.GraceTimeOut) * time.Second) time.Sleep(3 * time.Second) } else { log.Error("Error loading new configuration, aborted ", err) } } } }() // configure providers if gloablConfiguration.Docker != nil { providers = append(providers, gloablConfiguration.Docker) } if gloablConfiguration.Marathon != nil { providers = append(providers, gloablConfiguration.Marathon) } if gloablConfiguration.File != nil { if len(gloablConfiguration.File.Filename) == 0 { // no filename, setting to global config file gloablConfiguration.File.Filename = *globalConfigFile } providers = append(providers, gloablConfiguration.File) } if gloablConfiguration.Web != nil { providers = append(providers, gloablConfiguration.Web) } if gloablConfiguration.Consul != nil { providers = append(providers, gloablConfiguration.Consul) } // start providers for _, provider := range providers { log.Infof("Starting provider %v %+v", reflect.TypeOf(provider), provider) currentProvider := provider go func() { currentProvider.Provide(configurationChan) }() } goAway := false go func() { sig := <-sigs log.Infof("I have to go... %+v", sig) goAway = true srv.Stop(time.Duration(gloablConfiguration.GraceTimeOut) * time.Second) }() for { if goAway { break } // middlewares var negroni = negroni.New() negroni.Use(metrics) negroni.Use(loggerMiddleware) //negroni.Use(middlewares.NewCircuitBreaker(oxyLogger)) //negroni.Use(middlewares.NewRoutes(configurationRouter)) negroni.UseHandler(configurationRouter) srv = &graceful.Server{ Timeout: time.Duration(gloablConfiguration.GraceTimeOut) * time.Second, NoSignalHandling: true, Server: &http.Server{ Addr: gloablConfiguration.Port, Handler: negroni, }, } go func() { if len(gloablConfiguration.CertFile) > 0 && len(gloablConfiguration.KeyFile) > 0 { err := srv.ListenAndServeTLS(gloablConfiguration.CertFile, gloablConfiguration.KeyFile) if err != nil { netOpError, ok := err.(*net.OpError) if ok && netOpError.Err.Error() != "use of closed network connection" { log.Fatal("Error creating server: ", err) } } } else { err := srv.ListenAndServe() if err != nil { netOpError, ok := err.(*net.OpError) if ok && netOpError.Err.Error() != "use of closed network connection" { log.Fatal("Error creating server: ", err) } } } }() log.Info("Started") <-srv.StopChan() log.Info("Stopped") } }