Skip to content

Commit 4a75689

Browse files
Dipta Dastamalsaha
authored andcommitted
Implement Recovery for Restic Backup (#202)
1 parent 78b3942 commit 4a75689

File tree

3 files changed

+57
-54
lines changed

3 files changed

+57
-54
lines changed

recover.go

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
package cmds
2+
3+
import (
4+
"github.com/appscode/go/log"
5+
"github.com/appscode/kutil"
6+
"github.com/appscode/stash/client/typed/stash/v1alpha1"
7+
"github.com/appscode/stash/pkg/eventer"
8+
"github.com/appscode/stash/pkg/recovery"
9+
"github.com/spf13/cobra"
10+
"k8s.io/client-go/kubernetes"
11+
"k8s.io/client-go/tools/clientcmd"
12+
)
13+
14+
func NewCmdRecover() *cobra.Command {
15+
var (
16+
masterURL string
17+
kubeconfigPath string
18+
recoveryName string
19+
)
20+
21+
cmd := &cobra.Command{
22+
Use: "recover",
23+
Short: "Recover restic backup",
24+
DisableAutoGenTag: true,
25+
Run: func(cmd *cobra.Command, args []string) {
26+
config, err := clientcmd.BuildConfigFromFlags(masterURL, kubeconfigPath)
27+
if err != nil {
28+
log.Fatalln(err)
29+
}
30+
opt := &recovery.RecoveryOpt{
31+
Namespace: kutil.Namespace(),
32+
KubeClient: kubernetes.NewForConfigOrDie(config),
33+
StashClient: v1alpha1.NewForConfigOrDie(config),
34+
RecoveryName: recoveryName,
35+
}
36+
opt.Recorder = eventer.NewEventRecorder(opt.KubeClient, "stash-recovery")
37+
opt.RunRecovery()
38+
},
39+
}
40+
cmd.Flags().StringVar(&masterURL, "master", masterURL, "The address of the Kubernetes API server (overrides any value in kubeconfig)")
41+
cmd.Flags().StringVar(&kubeconfigPath, "kubeconfig", kubeconfigPath, "Path to kubeconfig file with authorization information (the master location is set by the master flag).")
42+
cmd.Flags().StringVar(&recoveryName, "recovery-name", recoveryName, "Name of the Recovery CRD.")
43+
44+
return cmd
45+
}

root.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,5 +47,6 @@ func NewCmdStash(version string) *cobra.Command {
4747
rootCmd.AddCommand(v.NewCmdVersion())
4848
rootCmd.AddCommand(NewCmdRun(version))
4949
rootCmd.AddCommand(NewCmdSchedule())
50+
rootCmd.AddCommand(NewCmdRecover())
5051
return rootCmd
5152
}

schedule.go

Lines changed: 11 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ import (
1010
"github.com/appscode/kutil"
1111
cs "github.com/appscode/stash/client/typed/stash/v1alpha1"
1212
"github.com/appscode/stash/pkg/scheduler"
13+
"github.com/appscode/stash/pkg/util"
1314
"github.com/spf13/cobra"
14-
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
1515
"k8s.io/client-go/kubernetes"
1616
"k8s.io/client-go/tools/clientcmd"
1717
)
@@ -20,8 +20,7 @@ func NewCmdSchedule() *cobra.Command {
2020
var (
2121
masterURL string
2222
kubeconfigPath string
23-
workload string
24-
opt scheduler.Options = scheduler.Options{
23+
opt = scheduler.Options{
2524
Namespace: kutil.Namespace(),
2625
ResticName: "",
2726
ScratchDir: "/tmp",
@@ -53,57 +52,14 @@ func NewCmdSchedule() *cobra.Command {
5352
log.Fatalln(`Missing ENV var "POD_NAME"`)
5453
}
5554

56-
app := strings.SplitN(workload, "/", 2)
57-
if len(app) != 2 {
58-
log.Fatalf(`--workload flag must be in the format "Kind/Name", but found %v`, workload)
55+
if err := opt.Workload.Canonicalize(); err != nil {
56+
log.Fatalf(err.Error())
5957
}
60-
opt.AppName = app[1]
61-
switch app[0] {
62-
case "Deployments", "Deployment", "deployments", "deployment":
63-
opt.AppKind = "Deployment"
64-
opt.SmartPrefix = ""
65-
opt.SnapshotHostname = opt.AppName
66-
_, err := kubeClient.AppsV1beta1().Deployments(opt.Namespace).Get(opt.AppName, metav1.GetOptions{})
67-
if err != nil {
68-
_, err := kubeClient.ExtensionsV1beta1().Deployments(opt.Namespace).Get(opt.AppName, metav1.GetOptions{})
69-
if err != nil {
70-
log.Fatalf(`Unknown Deployment %s/%s`, opt.Namespace, opt.AppName)
71-
}
72-
}
73-
case "ReplicaSets", "ReplicaSet", "replicasets", "replicaset", "rs":
74-
opt.AppKind = "ReplicaSet"
75-
opt.SmartPrefix = ""
76-
opt.SnapshotHostname = opt.AppName
77-
_, err := kubeClient.ExtensionsV1beta1().ReplicaSets(opt.Namespace).Get(opt.AppName, metav1.GetOptions{})
78-
if err != nil {
79-
log.Fatalf(`Unknown ReplicaSet %s/%s`, opt.Namespace, opt.AppName)
80-
}
81-
case "ReplicationControllers", "ReplicationController", "replicationcontrollers", "replicationcontroller", "rc":
82-
opt.AppKind = "ReplicationController"
83-
opt.SmartPrefix = ""
84-
opt.SnapshotHostname = opt.AppName
85-
_, err := kubeClient.CoreV1().ReplicationControllers(opt.Namespace).Get(opt.AppName, metav1.GetOptions{})
86-
if err != nil {
87-
log.Fatalf(`Unknown ReplicationController %s/%s`, opt.Namespace, opt.AppName)
88-
}
89-
case "StatefulSets", "StatefulSet":
90-
opt.AppKind = "StatefulSet"
91-
opt.SmartPrefix = opt.PodName
92-
opt.SnapshotHostname = opt.PodName
93-
_, err := kubeClient.AppsV1beta1().StatefulSets(opt.Namespace).Get(opt.AppName, metav1.GetOptions{})
94-
if err != nil {
95-
log.Fatalf(`Unknown StatefulSet %s/%s`, opt.Namespace, opt.AppName)
96-
}
97-
case "DaemonSets", "DaemonSet", "daemonsets", "daemonset":
98-
opt.AppKind = "DaemonSet"
99-
opt.SmartPrefix = opt.NodeName
100-
opt.SnapshotHostname = opt.NodeName
101-
_, err := kubeClient.ExtensionsV1beta1().DaemonSets(opt.Namespace).Get(opt.AppName, metav1.GetOptions{})
102-
if err != nil {
103-
log.Fatalf(`Unknown DaemonSet %s/%s`, opt.Namespace, opt.AppName)
104-
}
105-
default:
106-
log.Fatalf(`Unrecognized workload "Kind" %v`, opt.AppKind)
58+
if opt.SnapshotHostname, opt.SmartPrefix, err = opt.Workload.HostnamePrefix(opt.PodName, opt.NodeName); err != nil {
59+
log.Fatalf(err.Error())
60+
}
61+
if err = util.CheckWorkloadExists(kubeClient, opt.Namespace, opt.Workload); err != nil {
62+
log.Fatalf(err.Error())
10763
}
10864

10965
opt.ScratchDir = strings.TrimSuffix(opt.ScratchDir, "/")
@@ -131,7 +87,8 @@ func NewCmdSchedule() *cobra.Command {
13187
}
13288
cmd.Flags().StringVar(&masterURL, "master", masterURL, "The address of the Kubernetes API server (overrides any value in kubeconfig)")
13389
cmd.Flags().StringVar(&kubeconfigPath, "kubeconfig", kubeconfigPath, "Path to kubeconfig file with authorization information (the master location is set by the master flag).")
134-
cmd.Flags().StringVar(&workload, "workload", workload, `"Kind/Name" of workload where sidecar pod is added (eg, Deployment/apiserver)`)
90+
cmd.Flags().StringVar(&opt.Workload.Kind, "workload-kind", opt.Workload.Kind, "Kind of workload where sidecar pod is added.")
91+
cmd.Flags().StringVar(&opt.Workload.Name, "workload-name", opt.Workload.Name, "Name of workload where sidecar pod is added.")
13592
cmd.Flags().StringVar(&opt.ResticName, "restic-name", opt.ResticName, "Name of the Restic used as configuration.")
13693
cmd.Flags().StringVar(&opt.ScratchDir, "scratch-dir", opt.ScratchDir, "Directory used to store temporary files. Use an `emptyDir` in Kubernetes.")
13794
cmd.Flags().StringVar(&opt.PushgatewayURL, "pushgateway-url", opt.PushgatewayURL, "URL of Prometheus pushgateway used to cache backup metrics")

0 commit comments

Comments
 (0)