289 lines
5.6 KiB
Go
289 lines
5.6 KiB
Go
package external
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"os"
|
|
"strings"
|
|
)
|
|
|
|
// ResticTool wraps restic backup operations
|
|
type ResticTool struct {
|
|
*BaseTool
|
|
repository string
|
|
password string
|
|
}
|
|
|
|
// NewResticTool creates a new restic tool wrapper
|
|
func NewResticTool() *ResticTool {
|
|
return &ResticTool{
|
|
BaseTool: NewBaseTool("restic", "restic"),
|
|
}
|
|
}
|
|
|
|
// SetRepository sets the restic repository
|
|
func (r *ResticTool) SetRepository(repo string) {
|
|
r.repository = repo
|
|
}
|
|
|
|
// SetPassword sets the restic password
|
|
func (r *ResticTool) SetPassword(password string) {
|
|
r.password = password
|
|
}
|
|
|
|
// InitRepository initializes a new restic repository
|
|
func (r *ResticTool) InitRepository(ctx context.Context) error {
|
|
env := r.getEnvironment()
|
|
|
|
cmd := r.BaseTool
|
|
originalEnv := os.Environ()
|
|
defer func() {
|
|
os.Clearenv()
|
|
for _, kv := range originalEnv {
|
|
if k, v, found := strings.Cut(kv, "="); found {
|
|
_ = os.Setenv(k, v)
|
|
}
|
|
}
|
|
}()
|
|
|
|
// Set environment variables
|
|
for k, v := range env {
|
|
_ = os.Setenv(k, v)
|
|
}
|
|
|
|
args := []string{"init"}
|
|
if r.repository != "" {
|
|
args = append(args, "--repo", r.repository)
|
|
}
|
|
|
|
_, err := cmd.Execute(ctx, args...)
|
|
if err != nil {
|
|
return fmt.Errorf("initializing repository: %w", err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// Backup creates a backup
|
|
func (r *ResticTool) Backup(ctx context.Context, paths []string, excludes []string, tags []string) error {
|
|
env := r.getEnvironment()
|
|
|
|
cmd := r.BaseTool
|
|
originalEnv := os.Environ()
|
|
defer func() {
|
|
os.Clearenv()
|
|
for _, kv := range originalEnv {
|
|
if k, v, found := strings.Cut(kv, "="); found {
|
|
_ = os.Setenv(k, v)
|
|
}
|
|
}
|
|
}()
|
|
|
|
// Set environment variables
|
|
for k, v := range env {
|
|
_ = os.Setenv(k, v)
|
|
}
|
|
|
|
args := []string{"backup"}
|
|
|
|
if r.repository != "" {
|
|
args = append(args, "--repo", r.repository)
|
|
}
|
|
|
|
// Add paths
|
|
args = append(args, paths...)
|
|
|
|
// Add excludes
|
|
for _, exclude := range excludes {
|
|
args = append(args, "--exclude", exclude)
|
|
}
|
|
|
|
// Add tags
|
|
for _, tag := range tags {
|
|
args = append(args, "--tag", tag)
|
|
}
|
|
|
|
_, err := cmd.Execute(ctx, args...)
|
|
if err != nil {
|
|
return fmt.Errorf("creating backup: %w", err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// Restore restores from backup
|
|
func (r *ResticTool) Restore(ctx context.Context, snapshotID, target string) error {
|
|
env := r.getEnvironment()
|
|
|
|
cmd := r.BaseTool
|
|
originalEnv := os.Environ()
|
|
defer func() {
|
|
os.Clearenv()
|
|
for _, kv := range originalEnv {
|
|
if k, v, found := strings.Cut(kv, "="); found {
|
|
_ = os.Setenv(k, v)
|
|
}
|
|
}
|
|
}()
|
|
|
|
// Set environment variables
|
|
for k, v := range env {
|
|
_ = os.Setenv(k, v)
|
|
}
|
|
|
|
args := []string{"restore", snapshotID, "--target", target}
|
|
|
|
if r.repository != "" {
|
|
args = append(args, "--repo", r.repository)
|
|
}
|
|
|
|
_, err := cmd.Execute(ctx, args...)
|
|
if err != nil {
|
|
return fmt.Errorf("restoring backup: %w", err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// ListSnapshots lists available snapshots
|
|
func (r *ResticTool) ListSnapshots(ctx context.Context, tags []string) ([]byte, error) {
|
|
env := r.getEnvironment()
|
|
|
|
cmd := r.BaseTool
|
|
originalEnv := os.Environ()
|
|
defer func() {
|
|
os.Clearenv()
|
|
for _, kv := range originalEnv {
|
|
if k, v, found := strings.Cut(kv, "="); found {
|
|
_ = os.Setenv(k, v)
|
|
}
|
|
}
|
|
}()
|
|
|
|
// Set environment variables
|
|
for k, v := range env {
|
|
_ = os.Setenv(k, v)
|
|
}
|
|
|
|
args := []string{"snapshots", "--json"}
|
|
|
|
if r.repository != "" {
|
|
args = append(args, "--repo", r.repository)
|
|
}
|
|
|
|
// Add tag filters
|
|
for _, tag := range tags {
|
|
args = append(args, "--tag", tag)
|
|
}
|
|
|
|
output, err := cmd.Execute(ctx, args...)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("listing snapshots: %w", err)
|
|
}
|
|
|
|
return output, nil
|
|
}
|
|
|
|
// Check verifies repository integrity
|
|
func (r *ResticTool) Check(ctx context.Context) error {
|
|
env := r.getEnvironment()
|
|
|
|
cmd := r.BaseTool
|
|
originalEnv := os.Environ()
|
|
defer func() {
|
|
os.Clearenv()
|
|
for _, kv := range originalEnv {
|
|
if k, v, found := strings.Cut(kv, "="); found {
|
|
_ = os.Setenv(k, v)
|
|
}
|
|
}
|
|
}()
|
|
|
|
// Set environment variables
|
|
for k, v := range env {
|
|
_ = os.Setenv(k, v)
|
|
}
|
|
|
|
args := []string{"check"}
|
|
|
|
if r.repository != "" {
|
|
args = append(args, "--repo", r.repository)
|
|
}
|
|
|
|
_, err := cmd.Execute(ctx, args...)
|
|
if err != nil {
|
|
return fmt.Errorf("checking repository: %w", err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// Forget removes snapshots
|
|
func (r *ResticTool) Forget(ctx context.Context, keepLast int, keepDaily int, keepWeekly int, keepMonthly int, prune bool) error {
|
|
env := r.getEnvironment()
|
|
|
|
cmd := r.BaseTool
|
|
originalEnv := os.Environ()
|
|
defer func() {
|
|
os.Clearenv()
|
|
for _, kv := range originalEnv {
|
|
if k, v, found := strings.Cut(kv, "="); found {
|
|
_ = os.Setenv(k, v)
|
|
}
|
|
}
|
|
}()
|
|
|
|
// Set environment variables
|
|
for k, v := range env {
|
|
_ = os.Setenv(k, v)
|
|
}
|
|
|
|
args := []string{"forget"}
|
|
|
|
if r.repository != "" {
|
|
args = append(args, "--repo", r.repository)
|
|
}
|
|
|
|
if keepLast > 0 {
|
|
args = append(args, "--keep-last", fmt.Sprintf("%d", keepLast))
|
|
}
|
|
|
|
if keepDaily > 0 {
|
|
args = append(args, "--keep-daily", fmt.Sprintf("%d", keepDaily))
|
|
}
|
|
|
|
if keepWeekly > 0 {
|
|
args = append(args, "--keep-weekly", fmt.Sprintf("%d", keepWeekly))
|
|
}
|
|
|
|
if keepMonthly > 0 {
|
|
args = append(args, "--keep-monthly", fmt.Sprintf("%d", keepMonthly))
|
|
}
|
|
|
|
if prune {
|
|
args = append(args, "--prune")
|
|
}
|
|
|
|
_, err := cmd.Execute(ctx, args...)
|
|
if err != nil {
|
|
return fmt.Errorf("forgetting snapshots: %w", err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// getEnvironment returns environment variables for restic
|
|
func (r *ResticTool) getEnvironment() map[string]string {
|
|
env := make(map[string]string)
|
|
|
|
if r.repository != "" {
|
|
env["RESTIC_REPOSITORY"] = r.repository
|
|
}
|
|
|
|
if r.password != "" {
|
|
env["RESTIC_PASSWORD"] = r.password
|
|
}
|
|
|
|
return env
|
|
}
|