package cli import ( "bytes" "os" "path/filepath" "strings" "testing" "git.cloudinit.dev/coreci/orca/internal/paths" "git.cloudinit.dev/coreci/orca/internal/secrets" ) func setupBackupTestEnv(t *testing.T) string { t.Helper() dir := t.TempDir() t.Setenv("ORCA_HOME", dir) mk, err := secrets.GenerateMasterKey() if err != nil { t.Fatalf("GenerateMasterKey: %v", err) } if err := os.MkdirAll(paths.ClusterDir(), 0o755); err != nil { t.Fatalf("mkdir cluster dir: %v", err) } if err := secrets.SaveMasterKey(paths.MasterKeyPath(), mk); err != nil { t.Fatalf("SaveMasterKey: %v", err) } return dir } func TestBackupCmdRegistered(t *testing.T) { found := false for _, cmd := range rootCmd.Commands() { if cmd.Name() == "backup" { found = true break } } if !found { t.Fatal("backup command not registered on root") } } func TestRestoreCmdRegistered(t *testing.T) { found := false for _, cmd := range rootCmd.Commands() { if cmd.Name() == "restore" { found = true break } } if !found { t.Fatal("restore command not registered on root") } } func TestBackupRestoreCmdRoundTrip(t *testing.T) { home := setupBackupTestEnv(t) if err := os.WriteFile(filepath.Join(home, "keep.txt"), []byte("payload"), 0o644); err != nil { t.Fatalf("write keep.txt: %v", err) } outDir := t.TempDir() out := filepath.Join(outDir, "orca-backup.tar.gz") var buf bytes.Buffer resetRootFlags(t) rootCmd.SetOut(&buf) rootCmd.SetErr(&buf) rootCmd.SetArgs([]string{"backup", "--out", out}) if err := rootCmd.Execute(); err != nil { t.Fatalf("orca backup: %v", err) } if _, err := os.Stat(out + ".sig"); err != nil { t.Fatalf("sig missing: %v", err) } target := filepath.Join(t.TempDir(), "restored") var buf2 bytes.Buffer resetRootFlags(t) rootCmd.SetOut(&buf2) rootCmd.SetErr(&buf2) rootCmd.SetArgs([]string{"restore", "--in", out, "--target", target}) if err := rootCmd.Execute(); err != nil { t.Fatalf("orca restore: %v", err) } got, err := os.ReadFile(filepath.Join(target, "keep.txt")) if err != nil { t.Fatalf("restored keep.txt missing: %v", err) } if string(got) != "payload" { t.Errorf("restored keep.txt = %q, want %q", string(got), "payload") } } func TestRestoreCmdBadSignature(t *testing.T) { setupBackupTestEnv(t) outDir := t.TempDir() out := filepath.Join(outDir, "orca-backup.tar.gz") body := []byte("not a real tarball") if err := os.WriteFile(out, body, 0o644); err != nil { t.Fatalf("write fake tarball: %v", err) } if err := os.WriteFile(out+".sig", []byte("deadbeef"), 0o644); err != nil { t.Fatalf("write fake sig: %v", err) } target := filepath.Join(t.TempDir(), "restored") var buf bytes.Buffer resetRootFlags(t) rootCmd.SetOut(&buf) rootCmd.SetErr(&buf) rootCmd.SetArgs([]string{"restore", "--in", out, "--target", target}) err := rootCmd.Execute() if err == nil { t.Fatal("restore with bad signature should fail") } } func TestRestoreCmdRequiresInFlag(t *testing.T) { setupBackupTestEnv(t) var buf bytes.Buffer resetRootFlags(t) rootCmd.SetOut(&buf) rootCmd.SetErr(&buf) rootCmd.SetArgs([]string{"restore"}) err := rootCmd.Execute() if err == nil { t.Fatal("restore without --in should fail") } } func TestBackupCmdDefaultOut(t *testing.T) { home := setupBackupTestEnv(t) if err := os.WriteFile(filepath.Join(home, "f.txt"), []byte("x"), 0o644); err != nil { t.Fatalf("write f.txt: %v", err) } work := t.TempDir() orig, _ := os.Getwd() if err := os.Chdir(work); err != nil { t.Fatalf("chdir: %v", err) } defer os.Chdir(orig) var buf bytes.Buffer resetRootFlags(t) rootCmd.SetOut(&buf) rootCmd.SetErr(&buf) rootCmd.SetArgs([]string{"backup"}) if err := rootCmd.Execute(); err != nil { t.Fatalf("orca backup default out: %v", err) } entries, err := os.ReadDir(work) if err != nil { t.Fatalf("read work: %v", err) } var foundTar, foundSig bool for _, e := range entries { if e.Name() == "orca-backup" || strings.HasPrefix(e.Name(), "orca-backup-") && strings.HasSuffix(e.Name(), ".tar.gz") { foundTar = true } if strings.HasSuffix(e.Name(), ".tar.gz.sig") { foundSig = true } } if !foundTar { t.Errorf("default backup tarball not created in CWD (entries: %d)", len(entries)) } if !foundSig { t.Errorf("default backup sig not created in CWD (entries: %d)", len(entries)) } }