diff --git a/pkg/restic/backup.go b/pkg/restic/backup.go index b327ff13d..4896ae4b1 100644 --- a/pkg/restic/backup.go +++ b/pkg/restic/backup.go @@ -16,7 +16,7 @@ func (w *ResticWrapper) RunBackup(backupOption *BackupOptions) (*BackupOutput, e // Backup all target directories for _, dir := range backupOption.BackupDirs { - out, err := w.backup(dir, nil) + out, err := w.backup(dir, backupOption.Host, nil) if err != nil { return nil, err } diff --git a/pkg/restic/commands.go b/pkg/restic/commands.go index 9d9e7c6cf..0b2699517 100644 --- a/pkg/restic/commands.go +++ b/pkg/restic/commands.go @@ -60,12 +60,12 @@ func (w *ResticWrapper) initRepositoryIfAbsent() ([]byte, error) { return nil, nil } -func (w *ResticWrapper) backup(path string, tags []string) ([]byte, error) { +func (w *ResticWrapper) backup(path, host string, tags []string) ([]byte, error) { log.Infoln("Backing up target data") args := []interface{}{"backup", path} - if w.config.Hostname != "" { + if host != "" { args = append(args, "--host") - args = append(args, w.config.Hostname) + args = append(args, host) } // add tags if any for _, tag := range tags { @@ -123,8 +123,8 @@ func (w *ResticWrapper) restore(path, host, snapshotID string) ([]byte, error) { // Remove last part from the path. // https://github.com/appscode/stash/issues/392 - args = append(args, "--target") - args = append(args, filepath.Dir(path)) + args = append(args, "--target", "/") + // args = append(args, filepath.Dir(path)) args = w.appendCacheDirFlag(args) args = w.appendCaCertFlag(args) diff --git a/pkg/restic/config.go b/pkg/restic/config.go index 4cf2d1b07..2bce8f122 100644 --- a/pkg/restic/config.go +++ b/pkg/restic/config.go @@ -1,7 +1,6 @@ package restic import ( - v1beta1_api "github.com/appscode/stash/apis/stash/v1beta1" shell "github.com/codeskyblue/go-sh" ) @@ -11,12 +10,15 @@ type ResticWrapper struct { } type BackupOptions struct { + Host string BackupDirs []string Cleanup CleanupOptions } type RestoreOptions struct { - Rules []v1beta1_api.Rule + Host string + RestoreDirs []string + Snapshots []string // when Snapshots are specified Host and RestoreDirs will not be used } type SetupOptions struct { @@ -28,7 +30,6 @@ type SetupOptions struct { CacertFile string ScratchDir string EnableCache bool - Hostname string } type CleanupOptions struct { diff --git a/pkg/restic/output.go b/pkg/restic/output.go index fc6791916..87e655d32 100644 --- a/pkg/restic/output.go +++ b/pkg/restic/output.go @@ -67,14 +67,14 @@ type RestoreOutput struct { // WriteOutput write output of backup process into output.json file in the directory // specified by outputDir parameter func (out *BackupOutput) WriteOutput(fileName string) error { - jsonOuput, err := json.MarshalIndent(out, "", " ") + jsonOutput, err := json.MarshalIndent(out, "", " ") if err != nil { return err } - if err := os.MkdirAll(filepath.Base(fileName), 0755); err != nil { + if err := os.MkdirAll(filepath.Dir(fileName), 0755); err != nil { return err } - if err := ioutil.WriteFile(fileName, jsonOuput, 0755); err != nil { + if err := ioutil.WriteFile(fileName, jsonOutput, 0755); err != nil { return err } return nil @@ -85,7 +85,7 @@ func (out *RestoreOutput) WriteOutput(fileName string) error { if err != nil { return err } - if err := os.MkdirAll(filepath.Base(fileName), 0755); err != nil { + if err := os.MkdirAll(filepath.Dir(fileName), 0755); err != nil { return err } if err := ioutil.WriteFile(fileName, jsonOuput, 0755); err != nil { diff --git a/pkg/restic/restore.go b/pkg/restic/restore.go index 6f3557cef..f5208f780 100644 --- a/pkg/restic/restore.go +++ b/pkg/restic/restore.go @@ -4,40 +4,26 @@ import ( "time" "github.com/appscode/go/strings" + "github.com/appscode/stash/apis/stash/v1beta1" ) func (w *ResticWrapper) RunRestore(restoreOptions RestoreOptions) (*RestoreOutput, error) { // Start clock to measure total restore duration startTime := time.Now() - restoreOutput := &RestoreOutput{} - // Restore data according to rules. Restore will proceed only for first matching rule. - for _, rule := range restoreOptions.Rules { - // Check if Hosts field is empty. Empty Hosts filed will match any host. - if len(rule.Hosts) == 0 || strings.Contains(rule.Hosts, w.config.Hostname) { - if len(rule.Snapshots) != 0 { - for _, snapshot := range rule.Snapshots { - // if snapshot is specified then host and path does not matter. - _, err := w.restore("", "", snapshot) - if err != nil { - return nil, err - } - } - } else if len(rule.Paths) != 0 { - host := "" - if len(rule.Hosts) != 0 { - host = w.config.Hostname - } - for _, path := range rule.Paths { - _, err := w.restore(path, host, "") - if err != nil { - return nil, err - } - } + if len(restoreOptions.Snapshots) != 0 { + for _, snapshot := range restoreOptions.Snapshots { + // if snapshot is specified then host and path does not matter. + if _, err := w.restore("", "", snapshot); err != nil { + return nil, err + } + } + } else if len(restoreOptions.RestoreDirs) != 0 { + for _, path := range restoreOptions.RestoreDirs { + if _, err := w.restore(path, restoreOptions.Host, ""); err != nil { + return nil, err } - // one rule is matched. so, stop rule matching. - break } } @@ -47,3 +33,25 @@ func (w *ResticWrapper) RunRestore(restoreOptions RestoreOptions) (*RestoreOutpu return restoreOutput, nil } + +// return first matching rule +// if hosts is empty for any rule, it will match any hostname +func RestoreOptionsForHost(hostname string, rules []v1beta1.Rule) RestoreOptions { + for _, rule := range rules { + if len(rule.Hosts) == 0 { + return RestoreOptions{ + Host: "", + RestoreDirs: rule.Paths, + Snapshots: rule.Snapshots, + } + } + if strings.Contains(rule.Hosts, hostname) { + return RestoreOptions{ + Host: hostname, + RestoreDirs: rule.Paths, + Snapshots: rule.Snapshots, + } + } + } + return RestoreOptions{} +}