From a15689d15d9d4653c6630dc6e7afede4d5c343ea Mon Sep 17 00:00:00 2001 From: Tamal Saha Date: Thu, 29 Jun 2017 13:38:48 -0700 Subject: [PATCH] Various bug fixes (#118) --- schedule.go | 103 +++++++++++++++++++++++++++++++++++++------- snapshot_handler.go | 11 +++-- 2 files changed, 93 insertions(+), 21 deletions(-) diff --git a/schedule.go b/schedule.go index f9c58f50f..bde608cfd 100644 --- a/schedule.go +++ b/schedule.go @@ -9,8 +9,11 @@ import ( rcs "github.com/appscode/stash/client/clientset" "github.com/appscode/stash/pkg/analytics" "github.com/appscode/stash/pkg/scheduler" + "github.com/appscode/stash/pkg/util" "github.com/spf13/cobra" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" clientset "k8s.io/client-go/kubernetes" + apps "k8s.io/client-go/pkg/apis/apps/v1beta1" "k8s.io/client-go/tools/clientcmd" ) @@ -18,13 +21,13 @@ func NewCmdSchedule(version string) *cobra.Command { var ( masterURL string kubeconfigPath string + workload string opt scheduler.Options = scheduler.Options{ - ResourceNamespace: "", - ResourceName: "", - PrefixHostname: true, - ScratchDir: "/tmp", - PushgatewayURL: "http://stash-operator.kube-system.svc:56789", - PodLabelsPath: "/etc/labels", + Namespace: namespace(), + ResticName: "", + ScratchDir: "/tmp", + PushgatewayURL: "http://stash-operator.kube-system.svc:56789", + PodLabelsPath: "/etc/labels", } enableAnalytics bool = true ) @@ -49,6 +52,70 @@ func NewCmdSchedule(version string) *cobra.Command { kubeClient = clientset.NewForConfigOrDie(config) stashClient = rcs.NewForConfigOrDie(config) + opt.NodeName = os.Getenv("NODE_NAME") + if opt.NodeName == "" { + log.Fatalln(`Missing ENV var "NODE_NAME"`) + } + opt.PodName = os.Getenv("POD_NAME") + if opt.PodName == "" { + log.Fatalln(`Missing ENV var "POD_NAME"`) + } + + app := strings.SplitN(workload, "/", 2) + if len(app) != 2 { + log.Fatalf(`--workload flag must be in the format "Kind/Name", but found %v`, workload) + } + opt.AppName = app[1] + switch app[0] { + case "Deployments", "Deployment", "deployments", "deployment": + opt.AppKind = "Deployment" + opt.SmartPrefix = "" + if util.IsPreferredAPIResource(kubeClient, apps.GroupName, opt.AppKind) { + _, err := kubeClient.AppsV1beta1().Deployments(opt.Namespace).Get(opt.AppName, metav1.GetOptions{}) + if err != nil { + _, err := kubeClient.ExtensionsV1beta1().Deployments(opt.Namespace).Get(opt.AppName, metav1.GetOptions{}) + if err != nil { + log.Fatalf(`Unknown Deployment %s@%s`, opt.AppName, opt.Namespace) + } + } + } else { + _, err := kubeClient.ExtensionsV1beta1().Deployments(opt.Namespace).Get(opt.AppName, metav1.GetOptions{}) + if err != nil { + log.Fatalf(`Unknown Deployment %s@%s`, opt.AppName, opt.Namespace) + } + } + case "ReplicaSets", "ReplicaSet", "replicasets", "replicaset", "rs": + opt.AppKind = "ReplicaSet" + opt.SmartPrefix = "" + _, err := kubeClient.ExtensionsV1beta1().ReplicaSets(opt.Namespace).Get(opt.AppName, metav1.GetOptions{}) + if err != nil { + log.Fatalf(`Unknown ReplicaSet %s@%s`, opt.AppName, opt.Namespace) + } + case "ReplicationControllers", "ReplicationController", "replicationcontrollers", "replicationcontroller", "rc": + opt.AppKind = "ReplicationController" + opt.SmartPrefix = "" + _, err := kubeClient.CoreV1().ReplicationControllers(opt.Namespace).Get(opt.AppName, metav1.GetOptions{}) + if err != nil { + log.Fatalf(`Unknown ReplicationController %s@%s`, opt.AppName, opt.Namespace) + } + case "StatefulSets", "StatefulSet", "ss": + opt.AppKind = "StatefulSet" + opt.SmartPrefix = opt.PodName + _, err := kubeClient.AppsV1beta1().StatefulSets(opt.Namespace).Get(opt.AppName, metav1.GetOptions{}) + if err != nil { + log.Fatalf(`Unknown StatefulSet %s@%s`, opt.AppName, opt.Namespace) + } + case "DaemonSets", "DaemonSet", "daemonsets", "daemonset": + opt.AppKind = "DaemonSet" + opt.SmartPrefix = opt.NodeName + _, err := kubeClient.ExtensionsV1beta1().DaemonSets(opt.Namespace).Get(opt.AppName, metav1.GetOptions{}) + if err != nil { + log.Fatalf(`Unknown DaemonSet %s@%s`, opt.AppName, opt.Namespace) + } + default: + log.Fatalf(`Unrecognized workload "Kind" %v`, opt.AppKind) + } + opt.ScratchDir = strings.TrimSuffix(opt.ScratchDir, "/") err = os.MkdirAll(opt.ScratchDir, 0755) if err != nil { @@ -59,10 +126,7 @@ func NewCmdSchedule(version string) *cobra.Command { log.Fatalf("No write access in scratch dir: %s", err) } - ctrl, err := scheduler.New(kubeClient, stashClient, opt) - if err != nil { - log.Fatalf("Failed to create scheduler: %s", err) - } + ctrl := scheduler.New(kubeClient, stashClient, opt) err = ctrl.Setup() if err != nil { log.Fatalf("Failed to setup scheduler: %s", err) @@ -72,15 +136,24 @@ func NewCmdSchedule(version string) *cobra.Command { } cmd.Flags().StringVar(&masterURL, "master", masterURL, "The address of the Kubernetes API server (overrides any value in kubeconfig)") cmd.Flags().StringVar(&kubeconfigPath, "kubeconfig", kubeconfigPath, "Path to kubeconfig file with authorization information (the master location is set by the master flag).") - cmd.Flags().StringVar(&opt.App, "app", opt.App, "Name of app where sidecar pod is added") - cmd.Flags().StringVar(&opt.ResourceNamespace, "namespace", opt.ResourceNamespace, "The address of the Kubernetes API server (overrides any value in kubeconfig)") - cmd.Flags().StringVar(&opt.ResourceName, "name", opt.ResourceName, "Path to kubeconfig file with authorization information (the master location is set by the master flag).") - cmd.Flags().BoolVar(&opt.PrefixHostname, "prefix-hostname", opt.PrefixHostname, "If set, adds Hostname as prefix to repository. This should be true for StatefulSets & DaemonSets. This should be false in all other cases.") + cmd.Flags().StringVar(&workload, "workload", workload, `"Kind/Name" of workload where sidecar pod is added (eg, Deployment/apiserver)`) + cmd.Flags().StringVar(&opt.ResticName, "restic-name", opt.ResticName, "Path to kubeconfig file with authorization information (the master location is set by the master flag).") cmd.Flags().StringVar(&opt.ScratchDir, "scratch-dir", opt.ScratchDir, "Directory used to store temporary files. Use an `emptyDir` in Kubernetes.") cmd.Flags().StringVar(&opt.PushgatewayURL, "pushgateway-url", opt.PushgatewayURL, "URL of Prometheus pushgateway used to cache backup metrics") - cmd.Flags().StringVar(&opt.PodLabelsPath, "pod-labels-path", opt.PodLabelsPath, "Path to pod labels file mounted via Kubernetes Downward api") // Analytics flags cmd.Flags().BoolVar(&enableAnalytics, "analytics", enableAnalytics, "Send analytical events to Google Analytics") return cmd } + +func namespace() string { + if ns := os.Getenv("OPERATOR_NAMESPACE"); ns != "" { + return ns + } + if data, err := ioutil.ReadFile("/var/run/secrets/kubernetes.io/serviceaccount/namespace"); err == nil { + if ns := strings.TrimSpace(string(data)); len(ns) > 0 { + return ns + } + } + return metav1.NamespaceDefault +} diff --git a/snapshot_handler.go b/snapshot_handler.go index 5045d1760..5c1cb1831 100644 --- a/snapshot_handler.go +++ b/snapshot_handler.go @@ -14,9 +14,9 @@ import ( ) const ( - PathParamNamespace = ":namespace" - PathParamName = ":name" - QueryParamHostname = "hostname" + PathParamNamespace = ":namespace" + PathParamName = ":name" + QueryParamAutoPrefix = "autoPrefix" ) func ExportSnapshots(w http.ResponseWriter, r *http.Request) { @@ -35,8 +35,7 @@ func ExportSnapshots(w http.ResponseWriter, r *http.Request) { http.Error(w, "Missing parameter:"+PathParamName, http.StatusBadRequest) return } - hostname := r.URL.Query().Get(QueryParamHostname) - resticCLI := cli.New(scratchDir, hostname) + resticCLI := cli.New(scratchDir) var resource *sapi.Restic resource, err := stashClient.Restics(namespace).Get(name) @@ -61,7 +60,7 @@ func ExportSnapshots(w http.ResponseWriter, r *http.Request) { http.Error(w, err.Error(), http.StatusInternalServerError) return } - err = resticCLI.SetupEnv(resource, secret) + err = resticCLI.SetupEnv(resource, secret, r.URL.Query().Get(QueryParamAutoPrefix)) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return