Skip to content

Commit

Permalink
Backup and restore PVC (#676)
Browse files Browse the repository at this point in the history
- [x] Merge #674 
- [x] What should be host-name?
- [ ] Set backup/restore session status
  • Loading branch information
Dipta Das authored and tamalsaha committed Mar 20, 2019
1 parent d4a53e2 commit 50bbb0a
Show file tree
Hide file tree
Showing 3 changed files with 172 additions and 0 deletions.
90 changes: 90 additions & 0 deletions backup_pvc.go
@@ -0,0 +1,90 @@
package cmds

import (
"path/filepath"

"github.com/appscode/go/flags"
"github.com/appscode/stash/pkg/restic"
"github.com/spf13/cobra"
"k8s.io/apimachinery/pkg/util/errors"
)

const (
JobPVCBackup = "stash-pvc-backup"
)

func NewCmdBackupPVC() *cobra.Command {
var (
outputDir string
backupOpt restic.BackupOptions
setupOpt = restic.SetupOptions{
ScratchDir: restic.DefaultScratchDir,
EnableCache: false,
}
metrics = restic.MetricsOptions{
JobName: JobPVCBackup,
}
)

cmd := &cobra.Command{
Use: "backup-pvc",
Short: "Takes a backup of Persistent Volume Claim",
DisableAutoGenTag: true,
RunE: func(cmd *cobra.Command, args []string) error {
flags.EnsureRequiredFlags(cmd, "backup-dirs", "provider", "secret-dir")

// init restic wrapper
resticWrapper, err := restic.NewResticWrapper(setupOpt)
if err != nil {
return err
}
// Run backup
backupOutput, backupErr := resticWrapper.RunBackup(&backupOpt)
// If metrics are enabled then generate metrics
if metrics.Enabled {
err := backupOutput.HandleMetrics(&metrics, backupErr)
if err != nil {
return errors.NewAggregate([]error{backupErr, err})
}
}
// If output directory specified, then write the output in "output.json" file in the specified directory
if backupErr == nil && outputDir != "" {
err := backupOutput.WriteOutput(filepath.Join(outputDir, restic.DefaultOutputFileName))
if err != nil {
return err
}
}
return backupErr
},
}

cmd.Flags().StringVar(&setupOpt.Provider, "provider", setupOpt.Provider, "Backend provider (i.e. gcs, s3, azure etc)")
cmd.Flags().StringVar(&setupOpt.Bucket, "bucket", setupOpt.Bucket, "Name of the cloud bucket/container (keep empty for local backend)")
cmd.Flags().StringVar(&setupOpt.Endpoint, "endpoint", setupOpt.Endpoint, "Endpoint for s3/s3 compatible backend")
cmd.Flags().StringVar(&setupOpt.Path, "path", setupOpt.Path, "Directory inside the bucket where backup will be stored")
cmd.Flags().StringVar(&setupOpt.SecretDir, "secret-dir", setupOpt.SecretDir, "Directory where storage secret has been mounted")
cmd.Flags().StringVar(&setupOpt.ScratchDir, "scratch-dir", setupOpt.ScratchDir, "Temporary directory")
cmd.Flags().BoolVar(&setupOpt.EnableCache, "enable-cache", setupOpt.EnableCache, "Specify weather to enable caching for restic")

cmd.Flags().StringVar(&backupOpt.Host, "hostname", backupOpt.Host, "Name of the host machine")
cmd.Flags().StringSliceVar(&backupOpt.BackupDirs, "backup-dirs", backupOpt.BackupDirs, "List of directories to be backed up")

cmd.Flags().IntVar(&backupOpt.RetentionPolicy.KeepLast, "retention-keep-last", backupOpt.RetentionPolicy.KeepLast, "Specify value for retention strategy")
cmd.Flags().IntVar(&backupOpt.RetentionPolicy.KeepHourly, "retention-keep-hourly", backupOpt.RetentionPolicy.KeepHourly, "Specify value for retention strategy")
cmd.Flags().IntVar(&backupOpt.RetentionPolicy.KeepDaily, "retention-keep-daily", backupOpt.RetentionPolicy.KeepDaily, "Specify value for retention strategy")
cmd.Flags().IntVar(&backupOpt.RetentionPolicy.KeepWeekly, "retention-keep-weekly", backupOpt.RetentionPolicy.KeepWeekly, "Specify value for retention strategy")
cmd.Flags().IntVar(&backupOpt.RetentionPolicy.KeepMonthly, "retention-keep-monthly", backupOpt.RetentionPolicy.KeepMonthly, "Specify value for retention strategy")
cmd.Flags().IntVar(&backupOpt.RetentionPolicy.KeepYearly, "retention-keep-yearly", backupOpt.RetentionPolicy.KeepYearly, "Specify value for retention strategy")
cmd.Flags().StringSliceVar(&backupOpt.RetentionPolicy.KeepTags, "retention-keep-tags", backupOpt.RetentionPolicy.KeepTags, "Specify value for retention strategy")
cmd.Flags().BoolVar(&backupOpt.RetentionPolicy.Prune, "retention-prune", backupOpt.RetentionPolicy.Prune, "Specify weather to prune old snapshot data")
cmd.Flags().BoolVar(&backupOpt.RetentionPolicy.DryRun, "retention-dry-run", backupOpt.RetentionPolicy.DryRun, "Specify weather to test retention policy without deleting actual data")

cmd.Flags().StringVar(&outputDir, "output-dir", outputDir, "Directory where output.json file will be written (keep empty if you don't need to write output in file)")

cmd.Flags().BoolVar(&metrics.Enabled, "metrics-enabled", metrics.Enabled, "Specify weather to export Prometheus metrics")
cmd.Flags().StringVar(&metrics.PushgatewayURL, "metrics-pushgateway-url", metrics.PushgatewayURL, "Pushgateway URL where the metrics will be pushed")
cmd.Flags().StringVar(&metrics.MetricFileDir, "metrics-dir", metrics.MetricFileDir, "Directory where to write metric.prom file (keep empty if you don't want to write metric in a text file)")
cmd.Flags().StringSliceVar(&metrics.Labels, "metrics-labels", metrics.Labels, "Labels to apply in exported metrics")

return cmd
}
80 changes: 80 additions & 0 deletions restore_pvc.go
@@ -0,0 +1,80 @@
package cmds

import (
"path/filepath"

"github.com/appscode/go/flags"
"github.com/appscode/stash/pkg/restic"
"github.com/spf13/cobra"
"k8s.io/apimachinery/pkg/util/errors"
)

const (
JobPVCRestore = "stash-pvc-restore"
)

func NewCmdRestorePVC() *cobra.Command {
var (
outputDir string
restoreOpt restic.RestoreOptions
setupOpt = restic.SetupOptions{
ScratchDir: restic.DefaultScratchDir,
EnableCache: false,
}
metrics = restic.MetricsOptions{
JobName: JobPVCRestore,
}
)

cmd := &cobra.Command{
Use: "restore-pvc",
Short: "Takes a restore of Persistent Volume Claim",
DisableAutoGenTag: true,
RunE: func(cmd *cobra.Command, args []string) error {
flags.EnsureRequiredFlags(cmd, "restore-dirs", "provider", "secret-dir")
// init restic wrapper
resticWrapper, err := restic.NewResticWrapper(setupOpt)
if err != nil {
return err
}
// Run restore
restoreOutput, restoreErr := resticWrapper.RunRestore(restoreOpt)
// If metrics are enabled then generate metrics
if metrics.Enabled {
err := restoreOutput.HandleMetrics(&metrics, restoreErr)
if err != nil {
return errors.NewAggregate([]error{restoreErr, err})
}
}
// If output directory specified, then write the output in "output.json" file in the specified directory
if restoreErr == nil && outputDir != "" {
err := restoreOutput.WriteOutput(filepath.Join(outputDir, restic.DefaultOutputFileName))
if err != nil {
return err
}
}
return restoreErr
},
}

cmd.Flags().StringVar(&setupOpt.Provider, "provider", setupOpt.Provider, "Backend provider (i.e. gcs, s3, azure etc)")
cmd.Flags().StringVar(&setupOpt.Bucket, "bucket", setupOpt.Bucket, "Name of the cloud bucket/container (keep empty for local backend)")
cmd.Flags().StringVar(&setupOpt.Endpoint, "endpoint", setupOpt.Endpoint, "Endpoint for s3/s3 compatible backend")
cmd.Flags().StringVar(&setupOpt.Path, "path", setupOpt.Path, "Directory inside the bucket where restore will be stored")
cmd.Flags().StringVar(&setupOpt.SecretDir, "secret-dir", setupOpt.SecretDir, "Directory where storage secret has been mounted")
cmd.Flags().StringVar(&setupOpt.ScratchDir, "scratch-dir", setupOpt.ScratchDir, "Temporary directory")
cmd.Flags().BoolVar(&setupOpt.EnableCache, "enable-cache", setupOpt.EnableCache, "Specify weather to enable caching for restic")

cmd.Flags().StringVar(&restoreOpt.Host, "hostname", restoreOpt.Host, "Name of the host machine")
cmd.Flags().StringSliceVar(&restoreOpt.RestoreDirs, "restore-dirs", restoreOpt.RestoreDirs, "List of directories to be restored")
cmd.Flags().StringSliceVar(&restoreOpt.Snapshots, "snapshots", restoreOpt.Snapshots, "List of snapshots to be restored")

cmd.Flags().StringVar(&outputDir, "output-dir", outputDir, "Directory where output.json file will be written (keep empty if you don't need to write output in file)")

cmd.Flags().BoolVar(&metrics.Enabled, "metrics-enabled", metrics.Enabled, "Specify weather to export Prometheus metrics")
cmd.Flags().StringVar(&metrics.PushgatewayURL, "metrics-pushgateway-url", metrics.PushgatewayURL, "Pushgateway URL where the metrics will be pushed")
cmd.Flags().StringVar(&metrics.MetricFileDir, "metrics-dir", metrics.MetricFileDir, "Directory where to write metric.prom file (keep empty if you don't want to write metric in a text file)")
cmd.Flags().StringSliceVar(&metrics.Labels, "metrics-labels", metrics.Labels, "Labels to apply in exported metrics")

return cmd
}
2 changes: 2 additions & 0 deletions root.go
Expand Up @@ -43,6 +43,8 @@ func NewRootCmd() *cobra.Command {
stopCh := genericapiserver.SetupSignalHandler()
rootCmd.AddCommand(NewCmdRun(os.Stdout, os.Stderr, stopCh))
rootCmd.AddCommand(NewCmdBackup())
rootCmd.AddCommand(NewCmdBackupPVC())
rootCmd.AddCommand(NewCmdRestorePVC())
rootCmd.AddCommand(NewCmdRecover())
rootCmd.AddCommand(NewCmdCheck())
rootCmd.AddCommand(NewCmdScaleDown())
Expand Down

0 comments on commit 50bbb0a

Please sign in to comment.