feat: docker compose backup

This commit is contained in:
2026-07-04 17:20:28 +08:00
commit 5c8944fd58
27 changed files with 2070 additions and 0 deletions
+119
View File
@@ -0,0 +1,119 @@
package config
import (
"os"
"path/filepath"
"strings"
"testing"
)
func TestLoadValid(t *testing.T) {
yaml := `
global:
backup_dir: /tmp/backups
projects:
- name: testapp
path: /opt/testapp
`
dir := t.TempDir()
path := filepath.Join(dir, "config.yaml")
if err := os.WriteFile(path, []byte(yaml), 0644); err != nil {
t.Fatal(err)
}
cfg, err := Load(path)
if err != nil {
t.Fatalf("Load: %v", err)
}
if cfg.Global.BackupDir != "/tmp/backups" {
t.Errorf("backup_dir = %q", cfg.Global.BackupDir)
}
if len(cfg.Projects) != 1 {
t.Fatalf("expected 1 project, got %d", len(cfg.Projects))
}
p := cfg.Projects[0]
if p.Name != "testapp" {
t.Errorf("name = %q", p.Name)
}
if p.ComposeFile != "docker-compose.yml" {
t.Errorf("compose_file default = %q", p.ComposeFile)
}
if p.Retention.Count != DefaultRetentionCount {
t.Errorf("retention count default = %d", p.Retention.Count)
}
if cfg.HasRemote() {
t.Error("HasRemote should be false")
}
}
func TestLoadMissingBackupDir(t *testing.T) {
yaml := `
projects:
- name: x
path: /x
`
dir := t.TempDir()
path := filepath.Join(dir, "config.yaml")
os.WriteFile(path, []byte(yaml), 0644)
_, err := Load(path)
if err == nil {
t.Fatal("expected error for missing backup_dir")
}
}
func TestLoadNoProjects(t *testing.T) {
yaml := `
global:
backup_dir: /tmp
`
dir := t.TempDir()
path := filepath.Join(dir, "config.yaml")
os.WriteFile(path, []byte(yaml), 0644)
_, err := Load(path)
if err == nil {
t.Fatal("expected error for no projects")
}
}
func TestHasCron(t *testing.T) {
cfg := &Config{
Projects: []ProjectConfig{
{Name: "a", Cron: ""},
{Name: "b", Cron: "0 3 * * *"},
},
}
if !cfg.HasCron() {
t.Error("HasCron should be true")
}
cfg2 := &Config{
Projects: []ProjectConfig{
{Name: "a", Cron: ""},
},
}
if cfg2.HasCron() {
t.Error("HasCron should be false")
}
}
func TestValidateWebDAVRequiresURL(t *testing.T) {
cfg := &Config{
Global: GlobalConfig{BackupDir: "/tmp/backups"},
Projects: []ProjectConfig{{Name: "app", Path: "/tmp/app"}},
Remote: &RemoteConfig{WebDAV: &WebDAVConfig{}},
}
err := cfg.Validate()
if err == nil || !strings.Contains(err.Error(), "remote.webdav.url is required") {
t.Fatalf("expected webdav url error, got %v", err)
}
}
func TestValidateS3RequiresFields(t *testing.T) {
cfg := &Config{
Global: GlobalConfig{BackupDir: "/tmp/backups"},
Projects: []ProjectConfig{{Name: "app", Path: "/tmp/app"}},
Remote: &RemoteConfig{S3: &S3Config{}},
}
err := cfg.Validate()
if err == nil || !strings.Contains(err.Error(), "remote.s3.bucket is required") {
t.Fatalf("expected s3 bucket error, got %v", err)
}
}