- Add Go TUI with bubbletea for WireGuard management - Implement client CRUD operations with QR code generation - Add configuration and validation modules - Install/update scripts for client setup - Update Makefile to build binaries to bin/ directory - Add .gitignore for Go projects
123 lines
3.4 KiB
Go
123 lines
3.4 KiB
Go
package backup
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"os/exec"
|
|
"path/filepath"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
// ValidateBackup checks if a backup exists and is valid
|
|
func ValidateBackup(backupName string) error {
|
|
backupDir := "/etc/wg-admin/backups"
|
|
backupPath := filepath.Join(backupDir, backupName)
|
|
|
|
// Check if backup directory exists
|
|
info, err := os.Stat(backupPath)
|
|
if err != nil {
|
|
if os.IsNotExist(err) {
|
|
return fmt.Errorf("backup '%s' does not exist", backupName)
|
|
}
|
|
return fmt.Errorf("failed to access backup '%s': %w", backupName, err)
|
|
}
|
|
|
|
// Check if it's a directory
|
|
if !info.IsDir() {
|
|
return fmt.Errorf("'%s' is not a valid backup directory", backupName)
|
|
}
|
|
|
|
// Check for required files
|
|
metadataPath := filepath.Join(backupPath, "backup-info.txt")
|
|
if _, err := os.Stat(metadataPath); os.IsNotExist(err) {
|
|
return fmt.Errorf("backup '%s' is missing required metadata", backupName)
|
|
}
|
|
|
|
// Check for wireguard directory
|
|
wgBackupPath := filepath.Join(backupPath, "wireguard")
|
|
if _, err := os.Stat(wgBackupPath); os.IsNotExist(err) {
|
|
return fmt.Errorf("backup '%s' is missing wireguard configuration", backupName)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// ReloadWireGuard reloads the WireGuard interface to apply configuration changes
|
|
func ReloadWireGuard() error {
|
|
interfaceName := "wg0"
|
|
|
|
// Try to down the interface first
|
|
cmdDown := exec.Command("wg-quick", "down", interfaceName)
|
|
_ = cmdDown.Run() // Ignore errors if interface is not up
|
|
|
|
// Bring the interface up
|
|
cmdUp := exec.Command("wg-quick", "up", interfaceName)
|
|
output, err := cmdUp.CombinedOutput()
|
|
if err != nil {
|
|
return fmt.Errorf("failed to reload wireguard interface: %w, output: %s", err, string(output))
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// GetBackupSize calculates the total size of a backup directory
|
|
func GetBackupSize(backupName string) (int64, error) {
|
|
backupDir := "/etc/wg-admin/backups"
|
|
backupPath := filepath.Join(backupDir, backupName)
|
|
|
|
var size int64
|
|
|
|
err := filepath.Walk(backupPath, func(_ string, info os.FileInfo, err error) error {
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if !info.IsDir() {
|
|
size += info.Size()
|
|
}
|
|
return nil
|
|
})
|
|
|
|
return size, err
|
|
}
|
|
|
|
// GetBackupPath returns the full path for a backup name
|
|
func GetBackupPath(backupName string) string {
|
|
return filepath.Join("/etc/wg-admin/backups", backupName)
|
|
}
|
|
|
|
// ParseBackupName extracts operation and timestamp from backup directory name
|
|
// Format: wg-backup-{operation}-{timestamp}
|
|
func ParseBackupName(backupName string) (operation, timestamp string, err error) {
|
|
if !strings.HasPrefix(backupName, "wg-backup-") {
|
|
return "", "", fmt.Errorf("invalid backup name format")
|
|
}
|
|
|
|
nameWithoutPrefix := strings.TrimPrefix(backupName, "wg-backup-")
|
|
|
|
// Timestamp format: 20060102-150405 (15 chars)
|
|
if len(nameWithoutPrefix) < 16 {
|
|
return "", "", fmt.Errorf("backup name too short")
|
|
}
|
|
|
|
// Extract operation (everything before last timestamp)
|
|
timestampLen := 15
|
|
if len(nameWithoutPrefix) > timestampLen+1 {
|
|
operation = nameWithoutPrefix[:len(nameWithoutPrefix)-timestampLen-1]
|
|
// Remove trailing dash if present
|
|
if strings.HasSuffix(operation, "-") {
|
|
operation = operation[:len(operation)-1]
|
|
}
|
|
}
|
|
|
|
// Extract timestamp
|
|
timestamp = nameWithoutPrefix[len(nameWithoutPrefix)-timestampLen:]
|
|
|
|
// Validate timestamp format
|
|
if _, err := time.Parse("20060102-150405", timestamp); err != nil {
|
|
return "", "", fmt.Errorf("invalid timestamp format in backup name: %w", err)
|
|
}
|
|
|
|
return operation, timestamp, nil
|
|
}
|