162 lines
4.5 KiB
Go
162 lines
4.5 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, snapshots); err != nil {
|
|
fmt.Printf("Error: %v\n", err)
|
|
os.Exit(1)
|
|
}
|
|
|
|
case "mount":
|
|
// Mount a restored dataset to access files
|
|
if len(os.Args) < 3 {
|
|
fmt.Println("Usage: zfs-restore mount <dataset> [mountpoint]")
|
|
fmt.Println("\nExamples:")
|
|
fmt.Println(" zfs-restore mount tank/restored /mnt/recover")
|
|
fmt.Println(" zfs-restore mount tank/restored # interactive")
|
|
os.Exit(1)
|
|
}
|
|
|
|
dataset := os.Args[2]
|
|
mountpoint := ""
|
|
|
|
if len(os.Args) > 3 {
|
|
mountpoint = os.Args[3]
|
|
} else {
|
|
fmt.Printf("Mountpoint [/mnt/recover]: ")
|
|
fmt.Scanln(&mountpoint)
|
|
if mountpoint == "" {
|
|
mountpoint = "/mnt/recover"
|
|
}
|
|
}
|
|
|
|
if err := client.MountDataset(dataset, mountpoint); 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(" mount <dataset> [mountpoint] - Mount dataset to recover files")
|
|
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(" zfs-restore mount tank/restored /mnt - Mount to recover files")
|
|
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)")
|
|
}
|