229 lines
6.3 KiB
Go
229 lines
6.3 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"log/slog"
|
|
"os"
|
|
"runtime"
|
|
"time"
|
|
"vctp/db"
|
|
"vctp/internal/secrets"
|
|
"vctp/internal/settings"
|
|
"vctp/internal/tasks"
|
|
utils "vctp/internal/utils"
|
|
"vctp/internal/vcenter"
|
|
"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
|
|
cronInvFrequency time.Duration
|
|
encryptionKey = []byte("5L1l3B5KvwOCzUHMAlCgsgUTRAYMfSpa")
|
|
)
|
|
|
|
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)
|
|
}
|
|
|
|
// Load settings from yaml
|
|
settingsFile := os.Getenv("SETTINGS_FILE")
|
|
if settingsFile == "" {
|
|
settingsFile = "settings.yaml"
|
|
}
|
|
|
|
// TODO - how to pass this to the other packages that will need this info?
|
|
s := settings.New(logger, settingsFile)
|
|
err = s.ReadYMLSettings()
|
|
//s, err := settings.ReadYMLSettings(logger, settingsFile)
|
|
if err != nil {
|
|
logger.Error("failed to open yaml settings file", "error", err, "filename", settingsFile)
|
|
//os.Exit(1)
|
|
} else {
|
|
logger.Debug("Loaded yaml settings", "contents", s)
|
|
}
|
|
|
|
// 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)
|
|
}
|
|
|
|
// Load vcenter credentials from .env
|
|
a := secrets.New(logger, encryptionKey)
|
|
vcEp := os.Getenv("VCENTER_PASSWORD")
|
|
if len(vcEp) == 0 {
|
|
logger.Error("No vcenter password configured")
|
|
os.Exit(1)
|
|
}
|
|
vcPass, err := a.Decrypt(vcEp)
|
|
if err != nil {
|
|
logger.Error("failed to decrypt vcenter credentials. Assuming un-encrypted", "error", err)
|
|
vcPass = []byte(vcEp)
|
|
//os.Exit(1)
|
|
}
|
|
|
|
creds := vcenter.VcenterLogin{
|
|
//insecureString := os.Getenv("VCENTER_INSECURE")
|
|
Username: os.Getenv("VCENTER_USERNAME"),
|
|
Password: string(vcPass),
|
|
}
|
|
|
|
// Prepare the task scheduler
|
|
c, err := gocron.NewScheduler()
|
|
if err != nil {
|
|
logger.Error("failed to create scheduler", "error", err)
|
|
os.Exit(1)
|
|
}
|
|
|
|
// Pass useful information to the cron jobs
|
|
ct := &tasks.CronTask{
|
|
Logger: logger,
|
|
Database: database,
|
|
Settings: s,
|
|
VcCreds: &creds,
|
|
}
|
|
|
|
cronFrequencyString := os.Getenv("VCENTER_EVENT_POLLING_SECONDS")
|
|
if cronFrequencyString != "" {
|
|
cronFrequency, err = time.ParseDuration(cronFrequencyString)
|
|
if err != nil {
|
|
slog.Error("Can't convert VCENTER_EVENT_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 event polling cronjob frequency to", "frequency", cronFrequency)
|
|
|
|
cronInventoryFrequencyString := os.Getenv("VCENTER_INVENTORY_POLLING_SECONDS")
|
|
if cronInventoryFrequencyString != "" {
|
|
cronInvFrequency, err = time.ParseDuration(cronInventoryFrequencyString)
|
|
if err != nil {
|
|
slog.Error("Can't convert VCENTER_INVENTORY_POLLING_SECONDS value to time duration. Defaulting to 7200", "value", cronInventoryFrequencyString, "error", err)
|
|
cronInvFrequency = time.Second * 7200
|
|
}
|
|
} else {
|
|
cronInvFrequency = time.Second * 7200
|
|
}
|
|
logger.Debug("Setting VM inventory polling cronjob frequency to", "frequency", cronInvFrequency)
|
|
|
|
// start background processing for events stored in events table
|
|
startsAt := time.Now().Add(time.Second * 10)
|
|
job, err := c.NewJob(
|
|
gocron.DurationJob(cronFrequency),
|
|
gocron.NewTask(func() {
|
|
ct.RunVmCheck(ctx, logger)
|
|
}), gocron.WithSingletonMode(gocron.LimitModeReschedule),
|
|
gocron.WithStartAt(gocron.WithStartDateTime(startsAt)),
|
|
)
|
|
if err != nil {
|
|
logger.Error("failed to start event processing cron job", "error", err)
|
|
os.Exit(1)
|
|
}
|
|
logger.Debug("Created event processing cron job", "job", job.ID())
|
|
|
|
// start background checks of vcenter inventory
|
|
startsAt2 := time.Now().Add(time.Second * 30)
|
|
job2, err := c.NewJob(
|
|
gocron.DurationJob(cronInvFrequency),
|
|
gocron.NewTask(func() {
|
|
ct.RunVcenterPoll(ctx, logger)
|
|
}), gocron.WithSingletonMode(gocron.LimitModeReschedule),
|
|
gocron.WithStartAt(gocron.WithStartDateTime(startsAt2)),
|
|
)
|
|
if err != nil {
|
|
logger.Error("failed to start vcenter inventory cron job", "error", err)
|
|
os.Exit(1)
|
|
}
|
|
logger.Debug("Created vcenter inventory cron job", "job", job2.ID())
|
|
|
|
// start cron scheduler
|
|
c.Start()
|
|
|
|
// Start server
|
|
r := router.New(logger, database, buildTime, sha1ver, runtime.Version(), &creds, a, s)
|
|
svr := server.New(
|
|
logger,
|
|
c,
|
|
cancel,
|
|
bindAddress,
|
|
server.WithRouter(r),
|
|
server.SetTls(bindDisableTls),
|
|
server.SetCertificate(tlsCertFilename),
|
|
server.SetPrivateKey(tlsKeyFilename),
|
|
)
|
|
//logger.Debug("Server configured", "object", svr)
|
|
|
|
svr.StartAndWait()
|
|
|
|
os.Exit(0)
|
|
}
|