package feta import "os" import "time" import "github.com/jinzhu/gorm" import _ "github.com/jinzhu/gorm/dialects/sqlite" import "github.com/rs/zerolog" import "github.com/rs/zerolog/log" import "golang.org/x/crypto/ssh/terminal" type InstanceHostname string func CLIEntry(version string, buildtime string, buildarch string, builduser string) int { f := new(FetaProcess) f.version = version f.buildtime = buildtime f.buildarch = buildarch f.builduser = builduser f.setupLogging() return f.RunForever() } // FetaProcess is the main structure/process of this app type FetaProcess struct { version string buildtime string buildarch string builduser string locator *InstanceLocator manager *InstanceManager api *FetaAPIServer db *gorm.DB startup time.Time } func (f *FetaProcess) identify() { log.Info(). Str("version", f.version). Str("buildtime", f.buildtime). Str("buildarch", f.buildarch). Str("builduser", f.builduser). Msg("starting") } func (f *FetaProcess) setupLogging() { log.Logger = log.With().Caller().Logger() if terminal.IsTerminal(int(os.Stdout.Fd())) { out := zerolog.NewConsoleWriter( func(w *zerolog.ConsoleWriter) { // Customize time format w.TimeFormat = time.RFC3339 }, ) log.Logger = log.Output(out) } // always log in UTC zerolog.TimestampFunc = func() time.Time { return time.Now().UTC() } zerolog.SetGlobalLevel(zerolog.InfoLevel) if os.Getenv("DEBUG") != "" { zerolog.SetGlobalLevel(zerolog.DebugLevel) } f.identify() } func (f *FetaProcess) Uptime() time.Duration { return time.Since(f.startup) } func (f *FetaProcess) setupDatabase() { var err error f.db, err = gorm.Open("sqlite3", "feta.sqlite") if err != nil { panic(err) } f.databaseMigrations() } func (f *FetaProcess) RunForever() int { f.startup = time.Now() f.setupDatabase() newInstanceHostnameNotifications := make(chan InstanceHostname) f.locator = NewInstanceLocator() f.manager = NewInstanceManager() f.api = new(FetaAPIServer) f.api.feta = f // api needs to get to us to access data f.locator.AddInstanceNotificationChannel(newInstanceHostnameNotifications) f.manager.AddInstanceNotificationChannel(newInstanceHostnameNotifications) // locator goroutine: go f.locator.Locate() // manager goroutine: go f.manager.Manage() go f.api.Serve() // this goroutine (main) does nothing until we handle signals // FIXME(sneak) for { time.Sleep(1 * time.Second) } return 0 }