Files
zfs/cmd/zfs-restore/main.go
2026-02-15 12:58:05 +01:00

132 lines
3.7 KiB
Go

// Command zfs-restore is a simple CLI tool for restoring ZFS snapshots from a backup server.
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", "ls":
// List available snapshots
snapshots, err := client.ListSnapshots()
if err != nil {
fmt.Printf("Error: %v\n", err)
os.Exit(1)
}
client.DisplaySnapshots(snapshots)
case "restore":
// Restore snapshot - can use number or "latest" keyword
if len(os.Args) < 3 {
fmt.Println("Usage: zfs-restore restore <snapshot-number-or-latest> <target-dataset> [--force]")
fmt.Println("\nExamples:")
fmt.Println(" zfs-restore restore 1 tank/restored")
fmt.Println(" zfs-restore restore latest tank/restored")
fmt.Println(" zfs-restore restore latest tank/restored --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)
})
if len(snapshots) == 0 {
fmt.Println("No snapshots available. Run 'zfs-restore list' first.")
os.Exit(1)
}
snapshotArg := os.Args[2]
var snapshot *restore.SnapshotMetadata
if snapshotArg == "latest" {
snapshot = snapshots[0]
fmt.Printf("→ Restoring latest snapshot from %s\n", snapshot.Timestamp.Format("2006-01-02 15:04:05"))
} else {
var snapNum int
fmt.Sscanf(snapshotArg, "%d", &snapNum)
if snapNum < 1 || snapNum > len(snapshots) {
fmt.Printf("Invalid snapshot number. Use 'zfs-restore list' to see available snapshots.\n")
os.Exit(1)
}
snapshot = snapshots[snapNum-1]
}
// Get target dataset (either from args or prompt)
targetDataset := ""
force := false
for i, arg := range os.Args {
if arg == "--force" {
force = true
}
if arg != "restore" && arg != snapshotArg && arg != "--force" && targetDataset == "" && i > 2 && arg != os.Args[0] {
targetDataset = arg
}
}
if targetDataset == "" {
fmt.Printf("Target dataset: ")
fmt.Scanln(&targetDataset)
}
if targetDataset == "" {
fmt.Println("Error: target dataset is required")
os.Exit(1)
}
if err := client.RestoreSnapshot(snapshot, 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 - Simple Version")
fmt.Println("\nUsage: zfs-restore [command]")
fmt.Println("\nCommands:")
fmt.Println(" list - List available snapshots")
fmt.Println(" restore <#|latest> <dataset> [--force] - Restore snapshot to ZFS")
fmt.Println(" help - Show this help message")
fmt.Println("\nQuick Examples:")
fmt.Println(" zfs-restore list - See available backups")
fmt.Println(" zfs-restore restore latest tank/data - Restore most recent backup")
fmt.Println(" zfs-restore restore 1 tank/restored - Restore snapshot #1")
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)")
}