This commit is contained in:
209
main.go
209
main.go
@@ -2,8 +2,8 @@ package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"os"
|
||||
"runtime"
|
||||
"strings"
|
||||
@@ -19,7 +19,6 @@ import (
|
||||
"vctp/server/router"
|
||||
|
||||
"github.com/go-co-op/gocron/v2"
|
||||
"github.com/joho/godotenv"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -34,22 +33,29 @@ var (
|
||||
)
|
||||
|
||||
func main() {
|
||||
// Load data from environment file
|
||||
envFilename := utils.GetFilePath(".env")
|
||||
err := godotenv.Load(envFilename)
|
||||
if err != nil {
|
||||
panic("Error loading .env file")
|
||||
}
|
||||
settingsPath := flag.String("settings", "/etc/dtms/vctp.yml", "Path to settings YAML")
|
||||
flag.Parse()
|
||||
|
||||
logger := log.New(
|
||||
log.GetLevel(),
|
||||
log.GetOutput(),
|
||||
)
|
||||
bootstrapLogger := log.New(log.LevelInfo, log.OutputText)
|
||||
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
|
||||
// Load settings from yaml
|
||||
s := settings.New(bootstrapLogger, *settingsPath)
|
||||
err := s.ReadYMLSettings()
|
||||
if err != nil {
|
||||
bootstrapLogger.Error("failed to open yaml settings file", "error", err, "filename", *settingsPath)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
logger := log.New(
|
||||
log.ToLevel(strings.ToLower(strings.TrimSpace(s.Values.Settings.LogLevel))),
|
||||
log.ToOutput(strings.ToLower(strings.TrimSpace(s.Values.Settings.LogOutput))),
|
||||
)
|
||||
s.Logger = logger
|
||||
|
||||
// Configure database
|
||||
dbDriver := os.Getenv("DB_DRIVER")
|
||||
dbDriver := strings.TrimSpace(s.Values.Settings.DatabaseDriver)
|
||||
if dbDriver == "" {
|
||||
dbDriver = "sqlite"
|
||||
}
|
||||
@@ -57,12 +63,12 @@ func main() {
|
||||
if normalizedDriver == "" || normalizedDriver == "sqlite3" {
|
||||
normalizedDriver = "sqlite"
|
||||
}
|
||||
dbURL := os.Getenv("DB_URL")
|
||||
dbURL := strings.TrimSpace(s.Values.Settings.DatabaseURL)
|
||||
if dbURL == "" && normalizedDriver == "sqlite" {
|
||||
dbURL = utils.GetFilePath("db.sqlite3")
|
||||
}
|
||||
|
||||
database, err := db.New(logger, db.Config{Driver: dbDriver, DSN: dbURL})
|
||||
database, err := db.New(logger, db.Config{Driver: normalizedDriver, DSN: dbURL})
|
||||
if err != nil {
|
||||
logger.Error("Failed to create database", "error", err)
|
||||
os.Exit(1)
|
||||
@@ -70,56 +76,36 @@ func main() {
|
||||
defer database.Close()
|
||||
//defer database.DB().Close()
|
||||
|
||||
if err = db.Migrate(database, dbDriver); err != nil {
|
||||
if err = db.Migrate(database, normalizedDriver); 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")
|
||||
bindIP := strings.TrimSpace(s.Values.Settings.BindIP)
|
||||
if bindIP == "" {
|
||||
bindIP = utils.GetOutboundIP().String()
|
||||
}
|
||||
// Determine bind port
|
||||
bindPort := os.Getenv("BIND_PORT")
|
||||
if bindPort == "" {
|
||||
bindPort = "9443"
|
||||
bindPort := s.Values.Settings.BindPort
|
||||
if bindPort == 0 {
|
||||
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
|
||||
}
|
||||
bindDisableTls = s.Values.Settings.BindDisableTLS
|
||||
|
||||
// Get file names for TLS cert/key
|
||||
tlsCertFilename := os.Getenv("TLS_CERT_FILE")
|
||||
tlsCertFilename := strings.TrimSpace(s.Values.Settings.TLSCertFilename)
|
||||
if tlsCertFilename != "" {
|
||||
tlsCertFilename = utils.GetFilePath(tlsCertFilename)
|
||||
} else {
|
||||
tlsCertFilename = "./cert.pem"
|
||||
}
|
||||
|
||||
tlsKeyFilename := os.Getenv("TLS_KEY_FILE")
|
||||
tlsKeyFilename := strings.TrimSpace(s.Values.Settings.TLSKeyFilename)
|
||||
if tlsKeyFilename != "" {
|
||||
tlsKeyFilename = utils.GetFilePath(tlsKeyFilename)
|
||||
} else {
|
||||
@@ -132,9 +118,9 @@ func main() {
|
||||
utils.GenerateCerts(tlsCertFilename, tlsKeyFilename)
|
||||
}
|
||||
|
||||
// Load vcenter credentials from .env
|
||||
// Load vcenter credentials from serttings, decrypt if required
|
||||
a := secrets.New(logger, encryptionKey)
|
||||
vcEp := os.Getenv("VCENTER_PASSWORD")
|
||||
vcEp := strings.TrimSpace(s.Values.Settings.VcenterPassword)
|
||||
if len(vcEp) == 0 {
|
||||
logger.Error("No vcenter password configured")
|
||||
os.Exit(1)
|
||||
@@ -143,13 +129,27 @@ func main() {
|
||||
if err != nil {
|
||||
logger.Error("failed to decrypt vcenter credentials. Assuming un-encrypted", "error", err)
|
||||
vcPass = []byte(vcEp)
|
||||
if cipherText, encErr := a.Encrypt([]byte(vcEp)); encErr != nil {
|
||||
logger.Warn("failed to encrypt vcenter credentials", "error", encErr)
|
||||
} else {
|
||||
s.Values.Settings.VcenterPassword = cipherText
|
||||
if err := s.WriteYMLSettings(); err != nil {
|
||||
logger.Warn("failed to update settings with encrypted vcenter password", "error", err)
|
||||
} else {
|
||||
logger.Info("encrypted vcenter password stored in settings file")
|
||||
}
|
||||
}
|
||||
//os.Exit(1)
|
||||
}
|
||||
|
||||
creds := vcenter.VcenterLogin{
|
||||
//insecureString := os.Getenv("VCENTER_INSECURE")
|
||||
Username: os.Getenv("VCENTER_USERNAME"),
|
||||
Username: strings.TrimSpace(s.Values.Settings.VcenterUsername),
|
||||
Password: string(vcPass),
|
||||
Insecure: s.Values.Settings.VcenterInsecure,
|
||||
}
|
||||
if creds.Username == "" {
|
||||
logger.Error("No vcenter username configured")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Prepare the task scheduler
|
||||
@@ -167,83 +167,51 @@ func main() {
|
||||
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
|
||||
}
|
||||
cronFrequency = durationFromSeconds(s.Values.Settings.VcenterEventPollingSeconds, 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
|
||||
}
|
||||
cronInvFrequency = durationFromSeconds(s.Values.Settings.VcenterInventoryPollingSeconds, 7200)
|
||||
logger.Debug("Setting VM inventory polling cronjob frequency to", "frequency", cronInvFrequency)
|
||||
|
||||
cronSnapshotFrequencyString := os.Getenv("VCENTER_INVENTORY_SNAPSHOT_SECONDS")
|
||||
if cronSnapshotFrequencyString != "" {
|
||||
cronSnapshotFrequency, err = time.ParseDuration(cronSnapshotFrequencyString)
|
||||
if err != nil {
|
||||
slog.Error("Can't convert VCENTER_INVENTORY_SNAPSHOT_SECONDS value to time duration. Defaulting to 3600", "value", cronSnapshotFrequencyString, "error", err)
|
||||
cronSnapshotFrequency = time.Hour
|
||||
}
|
||||
} else {
|
||||
cronSnapshotFrequency = time.Hour
|
||||
}
|
||||
cronSnapshotFrequency = durationFromSeconds(s.Values.Settings.VcenterInventorySnapshotSeconds, 3600)
|
||||
logger.Debug("Setting VM inventory snapshot cronjob frequency to", "frequency", cronSnapshotFrequency)
|
||||
|
||||
cronAggregateFrequencyString := os.Getenv("VCENTER_INVENTORY_AGGREGATE_SECONDS")
|
||||
if cronAggregateFrequencyString != "" {
|
||||
cronAggregateFrequency, err = time.ParseDuration(cronAggregateFrequencyString)
|
||||
if err != nil {
|
||||
slog.Error("Can't convert VCENTER_INVENTORY_AGGREGATE_SECONDS value to time duration. Defaulting to 86400", "value", cronAggregateFrequencyString, "error", err)
|
||||
cronAggregateFrequency = time.Hour * 24
|
||||
}
|
||||
} else {
|
||||
cronAggregateFrequency = time.Hour * 24
|
||||
}
|
||||
cronAggregateFrequency = durationFromSeconds(s.Values.Settings.VcenterInventoryAggregateSeconds, 86400)
|
||||
logger.Debug("Setting VM inventory aggregation cronjob frequency to", "frequency", cronAggregateFrequency)
|
||||
|
||||
// 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(), "starting_at", startsAt)
|
||||
/*
|
||||
// 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(), "starting_at", startsAt)
|
||||
*/
|
||||
|
||||
// start background checks of vcenter inventory
|
||||
startsAt2 := time.Now().Add(cronInvFrequency)
|
||||
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(), "starting_at", startsAt2)
|
||||
/*
|
||||
startsAt2 := time.Now().Add(cronInvFrequency)
|
||||
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(), "starting_at", startsAt2)
|
||||
*/
|
||||
|
||||
startsAt3 := time.Now().Add(cronSnapshotFrequency)
|
||||
if cronSnapshotFrequency == time.Hour {
|
||||
@@ -292,8 +260,12 @@ func main() {
|
||||
}
|
||||
logger.Debug("Created vcenter monthly aggregation cron job", "job", job5.ID())
|
||||
|
||||
snapshotCleanupCron := strings.TrimSpace(s.Values.Settings.SnapshotCleanupCron)
|
||||
if snapshotCleanupCron == "" {
|
||||
snapshotCleanupCron = "30 2 * * *"
|
||||
}
|
||||
job6, err := c.NewJob(
|
||||
gocron.CronJob("0 30 2 * *", false),
|
||||
gocron.CronJob(snapshotCleanupCron, false),
|
||||
gocron.NewTask(func() {
|
||||
ct.RunSnapshotCleanup(ctx, logger)
|
||||
}), gocron.WithSingletonMode(gocron.LimitModeReschedule),
|
||||
@@ -325,3 +297,10 @@ func main() {
|
||||
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
func durationFromSeconds(value int, fallback int) time.Duration {
|
||||
if value <= 0 {
|
||||
return time.Second * time.Duration(fallback)
|
||||
}
|
||||
return time.Second * time.Duration(value)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user