package main import ( "context" "fmt" "log/slog" "os" "runtime" "time" "vctp/db" "vctp/internal/tasks" utils "vctp/internal/utils" "vctp/log" "vctp/server" "vctp/server/router" "github.com/go-co-op/gocron/v2" "github.com/joho/godotenv" ) var ( bindDisableTls bool sha1ver string // sha1 revision used to build the program buildTime string // when the executable was built cronFrequency time.Duration ) func main() { // Load data from environment file envFilename := utils.GetFilePath(".env") err := godotenv.Load(envFilename) if err != nil { panic("Error loading .env file") } logger := log.New( log.GetLevel(), log.GetOutput(), ) ctx, cancel := context.WithCancel(context.Background()) // Configure database database, err := db.New(logger, utils.GetFilePath("db.sqlite3")) if err != nil { logger.Error("Failed to create database", "error", err) os.Exit(1) } defer database.Close() //defer database.DB().Close() if err = db.Migrate(database); err != nil { logger.Error("failed to migrate database", "error", err) os.Exit(1) } // Prepare the task scheduler s, err := gocron.NewScheduler() if err != nil { logger.Error("failed to create scheduler", "error", err) os.Exit(1) } // Pass useful information to the cron jobs c := &tasks.CronTask{ Logger: logger, Database: database, } // Determine bind IP bindIP := os.Getenv("BIND_IP") if bindIP == "" { bindIP = utils.GetOutboundIP().String() } // Determine bind port bindPort := os.Getenv("BIND_PORT") if bindPort == "" { bindPort = "9443" } bindAddress := fmt.Sprint(bindIP, ":", bindPort) //logger.Info("Will listen on address", "ip", bindIP, "port", bindPort) // Determine bind disable TLS bindDisableTlsEnv := os.Getenv("BIND_DISABLE_TLS") if bindDisableTlsEnv == "true" { bindDisableTls = true } // Get file names for TLS cert/key tlsCertFilename := os.Getenv("TLS_CERT_FILE") if tlsCertFilename != "" { tlsCertFilename = utils.GetFilePath(tlsCertFilename) } else { tlsCertFilename = "./cert.pem" } tlsKeyFilename := os.Getenv("TLS_KEY_FILE") if tlsKeyFilename != "" { tlsKeyFilename = utils.GetFilePath(tlsKeyFilename) } else { tlsKeyFilename = "./privkey.pem" } // Generate certificate if required if !(utils.FileExists(tlsCertFilename) && utils.FileExists(tlsKeyFilename)) { logger.Warn("Specified TLS certificate or private key do not exist", "certificate", tlsCertFilename, "tls-key", tlsKeyFilename) utils.GenerateCerts(tlsCertFilename, tlsKeyFilename) } cronFrequencyString := os.Getenv("VCENTER_POLLING_SECONDS") if cronFrequencyString != "" { cronFrequency, err = time.ParseDuration(cronFrequencyString) if err != nil { slog.Error("Can't convert VCENTER_POLLING_SECONDS value to time duration. Defaulting to 60s", "value", cronFrequencyString, "error", err) cronFrequency = time.Second * 60 } } else { cronFrequency = time.Second * 60 } logger.Debug("Setting VM polling cronjob frequency to", "frequency", cronFrequency) // start background processing for events stored in events table startsAt := time.Now().Add(time.Second * 10) job, err := s.NewJob( gocron.DurationJob(cronFrequency), gocron.NewTask(func() { c.RunVmCheck(ctx, logger) }), gocron.WithSingletonMode(gocron.LimitModeReschedule), gocron.WithStartAt(gocron.WithStartDateTime(startsAt)), ) if err != nil { logger.Error("failed to start cron jobs", "error", err) os.Exit(1) } logger.Debug("Created event processing cron job", "job", job.ID()) startsAt2 := time.Now().Add(time.Second * 10) job2, err := s.NewJob( gocron.DurationJob(cronFrequency), gocron.NewTask(func() { c.RunVcenterPoll(ctx, logger) }), gocron.WithSingletonMode(gocron.LimitModeReschedule), gocron.WithStartAt(gocron.WithStartDateTime(startsAt2)), ) if err != nil { logger.Error("failed to start cron jobs", "error", err) os.Exit(1) } logger.Debug("Created vcenter polling cron job", "job", job2.ID()) // start cron scheduler s.Start() // Start server svr := server.New( logger, s, cancel, bindAddress, server.WithRouter(router.New(logger, database, buildTime, sha1ver, runtime.Version())), ) svr.DisableTls(bindDisableTls) svr.SetCertificate(tlsCertFilename) svr.SetPrivateKey(tlsKeyFilename) svr.StartAndWait() os.Exit(0) }