From 30993c0841b00798c9abc9a35cf8dc4267fd1967 Mon Sep 17 00:00:00 2001 From: Dipta Das Date: Wed, 20 Mar 2019 16:05:15 +0600 Subject: [PATCH] Backup and restore PVC (#676) - [x] Merge #674 - [x] What should be host-name? - [ ] Set backup/restore session status --- docs/examples/pvc/backup.yaml | 33 +++++++++ docs/examples/pvc/check.yaml | 20 ++++++ docs/examples/pvc/functions.yaml | 69 +++++++++++++++++++ docs/examples/pvc/pvc.yaml | 37 ++++++++++ docs/examples/pvc/repo.yaml | 11 +++ docs/examples/pvc/restore.yaml | 22 ++++++ docs/examples/pvc/tasks.yaml | 51 ++++++++++++++ docs/examples/pvc/write.yaml | 20 ++++++ docs/guides/backup_restore_pvc.md | 110 ++++++++++++++++++++++++++++++ hack/docker/setup.sh | 2 +- pkg/cmds/backup_pvc.go | 90 ++++++++++++++++++++++++ pkg/cmds/restore_pvc.go | 80 ++++++++++++++++++++++ pkg/cmds/root.go | 2 + pkg/restic/config.go | 5 ++ 14 files changed, 551 insertions(+), 1 deletion(-) create mode 100644 docs/examples/pvc/backup.yaml create mode 100644 docs/examples/pvc/check.yaml create mode 100644 docs/examples/pvc/functions.yaml create mode 100644 docs/examples/pvc/pvc.yaml create mode 100644 docs/examples/pvc/repo.yaml create mode 100644 docs/examples/pvc/restore.yaml create mode 100644 docs/examples/pvc/tasks.yaml create mode 100644 docs/examples/pvc/write.yaml create mode 100644 docs/guides/backup_restore_pvc.md create mode 100644 pkg/cmds/backup_pvc.go create mode 100644 pkg/cmds/restore_pvc.go diff --git a/docs/examples/pvc/backup.yaml b/docs/examples/pvc/backup.yaml new file mode 100644 index 000000000..493e5d665 --- /dev/null +++ b/docs/examples/pvc/backup.yaml @@ -0,0 +1,33 @@ +apiVersion: stash.appscode.com/v1beta1 +kind: BackupConfiguration +metadata: + name: pvc-backup-config + namespace: demo +spec: + task: + name: pvc-backup-task + repository: + name: hello-repo + schedule: "0 * * * *" + target: + ref: + apiVersion: v1 + kind: PersistentVolumeClaim + name: test-pvc-source + mountPath: /etc/target + directories: + - /etc/target/dir-01 + - /etc/target/dir-02 + retentionPolicy: + keepLast: 5 + prune: true + +--- +apiVersion: stash.appscode.com/v1beta1 +kind: BackupSession +metadata: + name: pvc-backup-01 + namespace: demo +spec: + backupConfiguration: + name: pvc-backup-config \ No newline at end of file diff --git a/docs/examples/pvc/check.yaml b/docs/examples/pvc/check.yaml new file mode 100644 index 000000000..6a5a5f3c2 --- /dev/null +++ b/docs/examples/pvc/check.yaml @@ -0,0 +1,20 @@ +kind: Pod +apiVersion: v1 +metadata: + name: test-check-dest + namespace: demo +spec: + containers: + - name: busybox + image: busybox + command: ["/bin/sh","-c"] + args: + - 'set -x; ls /etc/target' + volumeMounts: + - mountPath: /etc/target + name: test-pvc-dest + restartPolicy: Never + volumes: + - name: test-pvc-dest + persistentVolumeClaim: + claimName: test-pvc-dest \ No newline at end of file diff --git a/docs/examples/pvc/functions.yaml b/docs/examples/pvc/functions.yaml new file mode 100644 index 000000000..789098e27 --- /dev/null +++ b/docs/examples/pvc/functions.yaml @@ -0,0 +1,69 @@ +apiVersion: stash.appscode.com/v1beta1 +kind: Function +metadata: + name: pvc-backup +spec: + image: diptadas/stash:pvc + args: + - backup-pvc + - --provider=${REPOSITORY_PROVIDER} + - --bucket=${REPOSITORY_BUCKET=""} + - --endpoint=${REPOSITORY_ENDPOINT=""} + - --path=${REPOSITORY_PREFIX=""} + - --secret-dir=/etc/repository/secret # specified + - --scratch-dir=/tmp/restic/scratch # specified + - --enable-cache=false # specified + - --hostname=${HOSTNAME} + - --backup-dirs=${TARGET_DIRECTORIES} + - --retention-keep-last=${RETENTION_KEEP_LAST=0} + - --retention-keep-hourly=${RETENTION_KEEP_HOURLY=0} + - --retention-keep-daily=${RETENTION_KEEP_DAILY=0} + - --retention-keep-weekly=${RETENTION_KEEP_WEEKLY=0} + - --retention-keep-monthly=${RETENTION_KEEP_MONTHLY=0} + - --retention-keep-yearly=${RETENTION_KEEP_YEARLY=0} + - --retention-keep-tags=${RETENTION_KEEP_TAGS=""} + - --retention-prune=${RETENTION_PRUNE=false} + - --retention-dry-run=${RETENTION_DRY_RUN=false} + - --output-dir=${outputDir} + #- --metrics-enabled + #- --metrics-pushgateway-url + #- --metrics-dir + #- --metrics-labels + volumeMounts: + - name: ${scratchDirVolume} + mountPath: /tmp/restic/scratch + - name: ${targetVolume} + mountPath: ${TARGET_MOUNT_PATH} + - name: ${secretVolume} + mountPath: /etc/repository/secret +--- +apiVersion: stash.appscode.com/v1beta1 +kind: Function +metadata: + name: pvc-restore +spec: + image: diptadas/stash:pvc + args: + - restore-pvc + - --provider=${REPOSITORY_PROVIDER} + - --bucket=${REPOSITORY_BUCKET=""} + - --endpoint=${REPOSITORY_ENDPOINT=""} + - --path=${REPOSITORY_PREFIX=""} + - --secret-dir=/etc/repository/secret # specified + - --scratch-dir=/tmp/restic/scratch # specified + - --enable-cache=false # specified + - --hostname=${HOSTNAME} + - --restore-dirs=${RESTORE_DIRECTORIES} + - --snapshots=${RESTORE_SNAPSHOTS=""} + - --output-dir=${outputDir} + #- --metrics-enabled + #- --metrics-pushgateway-url + #- --metrics-dir + #- --metrics-labels + volumeMounts: + - name: ${scratchDirVolume} + mountPath: /tmp/restic/scratch + - name: ${targetVolume} + mountPath: ${TARGET_MOUNT_PATH} + - name: ${secretVolume} + mountPath: /etc/repository/secret diff --git a/docs/examples/pvc/pvc.yaml b/docs/examples/pvc/pvc.yaml new file mode 100644 index 000000000..13643a35e --- /dev/null +++ b/docs/examples/pvc/pvc.yaml @@ -0,0 +1,37 @@ +kind: PersistentVolume +apiVersion: v1 +metadata: + name: test-pv-volume + labels: + type: local +spec: + capacity: + storage: 1Gi + accessModes: + - ReadWriteOnce + hostPath: + path: "/tmp/data" +--- +kind: PersistentVolumeClaim +apiVersion: v1 +metadata: + name: test-pvc-source + namespace: demo +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 256M +--- +kind: PersistentVolumeClaim +apiVersion: v1 +metadata: + name: test-pvc-dest + namespace: demo +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 256M \ No newline at end of file diff --git a/docs/examples/pvc/repo.yaml b/docs/examples/pvc/repo.yaml new file mode 100644 index 000000000..9182a7b55 --- /dev/null +++ b/docs/examples/pvc/repo.yaml @@ -0,0 +1,11 @@ +apiVersion: stash.appscode.com/v1alpha1 +kind: Repository +metadata: + name: hello-repo + namespace: demo +spec: + backend: + gcs: + bucket: hello-bucket + prefix: hello-prefix + storageSecretName: gcs-secret \ No newline at end of file diff --git a/docs/examples/pvc/restore.yaml b/docs/examples/pvc/restore.yaml new file mode 100644 index 000000000..903aeb538 --- /dev/null +++ b/docs/examples/pvc/restore.yaml @@ -0,0 +1,22 @@ +apiVersion: stash.appscode.com/v1beta1 +kind: RestoreSession +metadata: + name: pvc-restore-01 + namespace: demo +spec: + task: + name: pvc-restore-task + repository: + name: hello-repo + target: + ref: + apiVersion: v1 + kind: PersistentVolumeClaim + name: test-pvc-dest + mountPath: /etc/target + rules: + - hosts: + - host-0 + paths: + - /etc/target/dir-01 + - /etc/target/dir-02 diff --git a/docs/examples/pvc/tasks.yaml b/docs/examples/pvc/tasks.yaml new file mode 100644 index 000000000..854d086e5 --- /dev/null +++ b/docs/examples/pvc/tasks.yaml @@ -0,0 +1,51 @@ +apiVersion: stash.appscode.com/v1beta1 +kind: Task +metadata: + name: pvc-backup-task +spec: + steps: + - name: pvc-backup + params: + - name: outputDir + value: /etc/backup # specified + - name: scratchDirVolume + value: scratch-volume # specified + - name: targetVolume + value: target-volume # specified + - name: secretVolume + value: secret-volume # specified + volumes: + - name: target-volume + persistentVolumeClaim: + claimName: ${TARGET_NAME} + - name: secret-volume + secret: + secretName: ${REPOSITORY_SECRET_NAME} + - name: scratch-volume + emptyDir: {} +--- +apiVersion: stash.appscode.com/v1beta1 +kind: Task +metadata: + name: pvc-restore-task +spec: + steps: + - name: pvc-restore + params: + - name: outputDir + value: /etc/restore # specified + - name: scratchDirVolume + value: scratch-volume # specified + - name: targetVolume + value: target-volume # specified + - name: secretVolume + value: secret-volume # specified + volumes: + - name: target-volume + persistentVolumeClaim: + claimName: ${TARGET_NAME} + - name: secret-volume + secret: + secretName: ${REPOSITORY_SECRET_NAME} + - name: scratch-volume + emptyDir: {} \ No newline at end of file diff --git a/docs/examples/pvc/write.yaml b/docs/examples/pvc/write.yaml new file mode 100644 index 000000000..cb8db48d2 --- /dev/null +++ b/docs/examples/pvc/write.yaml @@ -0,0 +1,20 @@ +kind: Pod +apiVersion: v1 +metadata: + name: test-write-soruce + namespace: demo +spec: + containers: + - name: busybox + image: busybox + command: ["/bin/sh","-c"] + args: + - 'set -x; rm -r /etc/target/*; mkdir /etc/target/dir-01; mkdir /etc/target/dir-02; ls /etc/target' + volumeMounts: + - mountPath: /etc/target + name: test-pvc-source + restartPolicy: Never + volumes: + - name: test-pvc-source + persistentVolumeClaim: + claimName: test-pvc-source diff --git a/docs/guides/backup_restore_pvc.md b/docs/guides/backup_restore_pvc.md new file mode 100644 index 000000000..db9451d7c --- /dev/null +++ b/docs/guides/backup_restore_pvc.md @@ -0,0 +1,110 @@ +--- +title: Backup and Restore PVC | Stash +description: Backup and Restore PVC using Stash +menu: + product_stash_0.8.3: + identifier: backup_restore_pvc + name: Backup and Restore PVC + parent: guides + weight: 15 +product_name: stash +menu_name: product_stash_0.8.3 +section_menu_id: guides +--- + +> New to Stash? Please start [here](/docs/concepts/README.md). + +# Backup and Restore PVC + +In this tutorial we will backup some directories of a persistent volume and restore it in another persistent volume. + +## Before You Begin + +At first, you need to have a Kubernetes cluster, and the `kubectl` command-line tool must be configured to communicate with your cluster. If you do not already have a cluster, you can create one by using [Minikube](https://github.com/kubernetes/minikube). Then install `Stash` in your cluster following the steps [here](/docs/setup/install.md). + +To keep things isolated, we are going to use a separate namespace called `demo` throughout this tutorial. + +```console +$ kubectl create ns demo +namespace/demo created +``` + +>Note: YAML files used in this tutorial are stored in [/docs/examples/pvc](/docs/examples/pvc) directory of [appscode/stash](https://github.com/appscode/stash) repository. + +## Create Functions and Tasks + +```bash +$ kubectl apply -f /docs/examples/pvc/functions.yaml; kubectl apply -f /docs/examples/pvc/tasks.yaml +function.stash.appscode.com/pvc-backup created +task.stash.appscode.com/pvc-backup-task created +function.stash.appscode.com/pvc-restore created +task.stash.appscode.com/pvc-restore-task created +``` + +## Create Repository + +```bash +$ kubectl create secret generic gcs-secret -n demo --from-file=./RESTIC_PASSWORD --from-file=./GOOGLE_PROJECT_ID --from-file=./GOOGLE_SERVICE_ACCOUNT_JSON_KEY +secret/gcs-secret created +``` + +```bash +$ kubectl apply -f /docs/examples/pvc/repo.yaml +repository.stash.appscode.com/hello-repo created +``` + +## Create PVC + +Create Persistent Volume and two separate PVC for source and destination. + +```bash +$ kubectl apply -f /docs/examples/pvc/pvc.yaml +persistentvolume/test-pv-volume created +persistentvolumeclaim/test-pvc-source created +persistentvolumeclaim/test-pvc-dest created +``` + +## Write to Source PVC + +```bash +$ kubectl apply -f /docs/examples/pvc/write.yaml +pod/test-write-soruce created +``` + +## Backup Source PVC + +```bash +$ kubectl apply -f /docs/examples/pvc/backup.yaml +backupconfiguration.stash.appscode.com/pvc-backup-config created +backupsession.stash.appscode.com/pvc-backup-01 created +``` + +## Restore to Destination PVC + +```bash +$ kubectl apply -f /docs/examples/pvc/restore.yaml +restoresession.stash.appscode.com/pvc-restore-01 created +``` + +## Check Destination PVC + +```bash +$ kubectl apply -f /docs/examples/pvc/check.yaml +pod/test-check-dest created +``` + +```bash +$ kc logs -n demo -f test-check-dest ++ ls /etc/target +dir-01 +dir-02 +``` + +## Cleanup + +To cleanup the Kubernetes resources created by this tutorial, run: + +```console +$ kubectl delete -f /docs/examples/pvc +$ kubectl delete namespace demo +``` diff --git a/hack/docker/setup.sh b/hack/docker/setup.sh index 5a77bd8b2..2b9690301 100755 --- a/hack/docker/setup.sh +++ b/hack/docker/setup.sh @@ -14,7 +14,7 @@ source "$REPO_ROOT/hack/libbuild/common/public_image.sh" APPSCODE_ENV=${APPSCODE_ENV:-dev} IMG=stash -RESTIC_VER=${RESTIC_VER:-0.8.3} +RESTIC_VER=${RESTIC_VER:-0.9.4} RESTIC_BRANCH=${RESTIC_BRANCH:-stash-0.4.2} DIST=$REPO_ROOT/dist diff --git a/pkg/cmds/backup_pvc.go b/pkg/cmds/backup_pvc.go new file mode 100644 index 000000000..b2b06e082 --- /dev/null +++ b/pkg/cmds/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 +} diff --git a/pkg/cmds/restore_pvc.go b/pkg/cmds/restore_pvc.go new file mode 100644 index 000000000..c3dcc1d13 --- /dev/null +++ b/pkg/cmds/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 +} diff --git a/pkg/cmds/root.go b/pkg/cmds/root.go index 9b040a793..64c2c64d8 100644 --- a/pkg/cmds/root.go +++ b/pkg/cmds/root.go @@ -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()) diff --git a/pkg/restic/config.go b/pkg/restic/config.go index 6a61992b2..116342a92 100644 --- a/pkg/restic/config.go +++ b/pkg/restic/config.go @@ -5,6 +5,11 @@ import ( shell "github.com/codeskyblue/go-sh" ) +const ( + DefaultOutputFileName = "output.json" + DefaultScratchDir = "/tmp/restic/scratch" +) + type ResticWrapper struct { sh *shell.Session config SetupOptions