// Command zfs-restore is a CLI tool for restoring ZFS snapshots from a backup server. // It provides commands for listing, restoring, and mounting snapshots. package main import ( "fmt" "os" "sort" "git.ma-al.com/goc_marek/zfs/internal/restore" ) func main() { if len(os.Args) < 2 { printUsage() os.Exit(1) } // Load configuration from environment and .env file cfg := restore.LoadConfig() client := restore.New(cfg.ClientID, cfg.APIKey, cfg.ServerURL) command := os.Args[1] switch command { case "list": snapshots, err := client.ListSnapshots() if err != nil { fmt.Printf("Error: %v\n", err) os.Exit(1) } client.DisplaySnapshots(snapshots) case "restore": if len(os.Args) < 4 { fmt.Println("Usage: zfs-restore restore [--force]") os.Exit(1) } snapshots, err := client.ListSnapshots() if err != nil { fmt.Printf("Error: %v\n", err) os.Exit(1) } // Sort by timestamp (newest first) sort.Slice(snapshots, func(i, j int) bool { return snapshots[i].Timestamp.After(snapshots[j].Timestamp) }) // Parse snapshot number var snapNum int fmt.Sscanf(os.Args[2], "%d", &snapNum) if snapNum < 1 || snapNum > len(snapshots) { fmt.Printf("Invalid snapshot number. Use 'list' to see available snapshots.\n") os.Exit(1) } snapshot := snapshots[snapNum-1] targetDataset := os.Args[3] force := len(os.Args) > 4 && os.Args[4] == "--force" if err := client.RestoreSnapshot(snapshot, targetDataset, force); err != nil { fmt.Printf("Error: %v\n", err) os.Exit(1) } case "save": if len(os.Args) < 4 { fmt.Println("Usage: zfs-restore save ") os.Exit(1) } snapshots, err := client.ListSnapshots() if err != nil { fmt.Printf("Error: %v\n", err) os.Exit(1) } sort.Slice(snapshots, func(i, j int) bool { return snapshots[i].Timestamp.After(snapshots[j].Timestamp) }) var snapNum int fmt.Sscanf(os.Args[2], "%d", &snapNum) if snapNum < 1 || snapNum > len(snapshots) { fmt.Printf("Invalid snapshot number.\n") os.Exit(1) } snapshot := snapshots[snapNum-1] outputFile := os.Args[3] if err := client.RestoreToFile(snapshot, outputFile); err != nil { fmt.Printf("Error: %v\n", err) os.Exit(1) } case "mount": if len(os.Args) < 4 { fmt.Println("Usage: zfs-restore mount ") os.Exit(1) } dataset := os.Args[2] mountpoint := os.Args[3] if err := client.MountSnapshot(dataset, mountpoint); err != nil { fmt.Printf("Error: %v\n", err) os.Exit(1) } case "latest": if len(os.Args) < 3 { fmt.Println("Usage: zfs-restore latest [--force]") os.Exit(1) } snapshots, err := client.ListSnapshots() if err != nil { fmt.Printf("Error: %v\n", err) os.Exit(1) } if len(snapshots) == 0 { fmt.Println("No snapshots available") os.Exit(1) } // Sort and get latest sort.Slice(snapshots, func(i, j int) bool { return snapshots[i].Timestamp.After(snapshots[j].Timestamp) }) latest := snapshots[0] targetDataset := os.Args[2] force := len(os.Args) > 3 && os.Args[3] == "--force" fmt.Printf("Restoring latest snapshot from %s\n", latest.Timestamp.Format("2006-01-02 15:04:05")) if err := client.RestoreSnapshot(latest, targetDataset, force); err != nil { fmt.Printf("Error: %v\n", err) os.Exit(1) } case "help", "-h", "--help": printUsage() default: fmt.Printf("Unknown command: %s\n", command) printUsage() os.Exit(1) } } func printUsage() { fmt.Println("ZFS Snapshot Restore Tool") fmt.Println("\nUsage: zfs-restore [command] [options]") fmt.Println("\nCommands:") fmt.Println(" list - List available snapshots") fmt.Println(" restore <#> [--force] - Restore snapshot to ZFS dataset") fmt.Println(" latest [--force] - Restore most recent snapshot") fmt.Println(" save <#> - Save snapshot to file") fmt.Println(" mount - Mount restored dataset") fmt.Println(" help - Show this help message") fmt.Println("\nExamples:") fmt.Println(" zfs-restore list") fmt.Println(" zfs-restore restore 1 tank/restored") fmt.Println(" zfs-restore latest tank/restored --force") fmt.Println(" zfs-restore save 2 backup.zfs.lz4") fmt.Println(" zfs-restore mount tank/restored /mnt/restore") fmt.Println("\nEnvironment Variables (can be set in .env file):") fmt.Println(" CLIENT_ID - Client identifier (default: client1)") fmt.Println(" API_KEY - API key for authentication (default: secret123)") fmt.Println(" SERVER_URL - Backup server URL (default: http://localhost:8080)") }