148 lines
4 KiB
Go
148 lines
4 KiB
Go
|
|
package main
|
||
|
|
|
||
|
|
import (
|
||
|
|
"context"
|
||
|
|
"flag"
|
||
|
|
"fmt"
|
||
|
|
"os"
|
||
|
|
"os/signal"
|
||
|
|
"syscall"
|
||
|
|
"time"
|
||
|
|
|
||
|
|
"veza-backend-api/internal/services"
|
||
|
|
|
||
|
|
"go.uber.org/zap"
|
||
|
|
)
|
||
|
|
|
||
|
|
func main() {
|
||
|
|
// Parse command line flags
|
||
|
|
backupDir := flag.String("backup-dir", "/backups/postgres", "Directory to store backups")
|
||
|
|
retentionDays := flag.Int("retention-days", 30, "Number of days to retain backups")
|
||
|
|
createBackup := flag.Bool("create", false, "Create a new backup")
|
||
|
|
cleanup := flag.Bool("cleanup", false, "Cleanup old backups")
|
||
|
|
list := flag.Bool("list", false, "List all backups")
|
||
|
|
flag.Parse()
|
||
|
|
|
||
|
|
// Initialize logger
|
||
|
|
logger, err := zap.NewProduction()
|
||
|
|
if err != nil {
|
||
|
|
fmt.Fprintf(os.Stderr, "Failed to initialize logger: %v\n", err)
|
||
|
|
os.Exit(1)
|
||
|
|
}
|
||
|
|
defer logger.Sync()
|
||
|
|
|
||
|
|
// Get database connection details from environment variables
|
||
|
|
databaseURL := os.Getenv("DATABASE_URL")
|
||
|
|
databaseName := os.Getenv("DB_NAME")
|
||
|
|
if databaseName == "" {
|
||
|
|
databaseName = "veza_db" // Default
|
||
|
|
}
|
||
|
|
databaseUser := os.Getenv("DB_USER")
|
||
|
|
if databaseUser == "" {
|
||
|
|
databaseUser = "veza_user" // Default
|
||
|
|
}
|
||
|
|
databaseHost := os.Getenv("DB_HOST")
|
||
|
|
if databaseHost == "" {
|
||
|
|
databaseHost = "localhost" // Default
|
||
|
|
}
|
||
|
|
databasePort := os.Getenv("DB_PORT")
|
||
|
|
if databasePort == "" {
|
||
|
|
databasePort = "5432" // Default
|
||
|
|
}
|
||
|
|
|
||
|
|
// If DATABASE_URL is not set, try to construct it from individual components
|
||
|
|
if databaseURL == "" {
|
||
|
|
// Use individual components for pg_dump
|
||
|
|
}
|
||
|
|
|
||
|
|
// Create backup service
|
||
|
|
backupConfig := services.BackupConfig{
|
||
|
|
BackupDir: *backupDir,
|
||
|
|
RetentionDays: *retentionDays,
|
||
|
|
DatabaseURL: databaseURL,
|
||
|
|
DatabaseName: databaseName,
|
||
|
|
DatabaseUser: databaseUser,
|
||
|
|
DatabaseHost: databaseHost,
|
||
|
|
DatabasePort: databasePort,
|
||
|
|
}
|
||
|
|
|
||
|
|
backupService, err := services.NewBackupService(backupConfig, logger)
|
||
|
|
if err != nil {
|
||
|
|
logger.Fatal("Failed to create backup service", zap.Error(err))
|
||
|
|
}
|
||
|
|
|
||
|
|
// Create context with timeout
|
||
|
|
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Minute)
|
||
|
|
defer cancel()
|
||
|
|
|
||
|
|
// Handle signals for graceful shutdown
|
||
|
|
sigChan := make(chan os.Signal, 1)
|
||
|
|
signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM)
|
||
|
|
|
||
|
|
go func() {
|
||
|
|
<-sigChan
|
||
|
|
logger.Info("Received shutdown signal, cancelling backup operation")
|
||
|
|
cancel()
|
||
|
|
}()
|
||
|
|
|
||
|
|
// Execute requested action
|
||
|
|
if *createBackup {
|
||
|
|
logger.Info("Creating database backup")
|
||
|
|
result, err := backupService.CreateBackup(ctx)
|
||
|
|
if err != nil {
|
||
|
|
logger.Fatal("Backup failed", zap.Error(err))
|
||
|
|
}
|
||
|
|
|
||
|
|
if result.Success {
|
||
|
|
logger.Info("Backup completed successfully",
|
||
|
|
zap.String("backup_path", result.BackupPath),
|
||
|
|
zap.Int64("backup_size", result.BackupSize),
|
||
|
|
zap.Duration("duration", result.Duration))
|
||
|
|
} else {
|
||
|
|
logger.Fatal("Backup failed", zap.String("error", result.ErrorMessage))
|
||
|
|
}
|
||
|
|
} else if *cleanup {
|
||
|
|
logger.Info("Cleaning up old backups")
|
||
|
|
if err := backupService.CleanupOldBackups(ctx); err != nil {
|
||
|
|
logger.Fatal("Cleanup failed", zap.Error(err))
|
||
|
|
}
|
||
|
|
logger.Info("Cleanup completed successfully")
|
||
|
|
} else if *list {
|
||
|
|
logger.Info("Listing backups")
|
||
|
|
backups, err := backupService.ListBackups(ctx)
|
||
|
|
if err != nil {
|
||
|
|
logger.Fatal("Failed to list backups", zap.Error(err))
|
||
|
|
}
|
||
|
|
|
||
|
|
fmt.Printf("\nFound %d backups:\n\n", len(backups))
|
||
|
|
for _, backup := range backups {
|
||
|
|
sizeMB := float64(backup.Size) / (1024 * 1024)
|
||
|
|
fmt.Printf(" %s\n", backup.FileName)
|
||
|
|
fmt.Printf(" Path: %s\n", backup.FilePath)
|
||
|
|
fmt.Printf(" Size: %.2f MB\n", sizeMB)
|
||
|
|
fmt.Printf(" Created: %s\n\n", backup.CreatedAt.Format(time.RFC3339))
|
||
|
|
}
|
||
|
|
} else {
|
||
|
|
// Default: create backup and cleanup
|
||
|
|
logger.Info("Creating backup and cleaning up old backups")
|
||
|
|
|
||
|
|
result, err := backupService.CreateBackup(ctx)
|
||
|
|
if err != nil {
|
||
|
|
logger.Fatal("Backup failed", zap.Error(err))
|
||
|
|
}
|
||
|
|
|
||
|
|
if result.Success {
|
||
|
|
logger.Info("Backup completed successfully",
|
||
|
|
zap.String("backup_path", result.BackupPath),
|
||
|
|
zap.Int64("backup_size", result.BackupSize),
|
||
|
|
zap.Duration("duration", result.Duration))
|
||
|
|
}
|
||
|
|
|
||
|
|
// Cleanup old backups
|
||
|
|
if err := backupService.CleanupOldBackups(ctx); err != nil {
|
||
|
|
logger.Warn("Cleanup failed", zap.Error(err))
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|