From 3e274741d4d26d9265e2e86799f56f01962820c6 Mon Sep 17 00:00:00 2001 From: "Alex Ellis (OpenFaaS Ltd)" Date: Sun, 22 Sep 2019 09:12:28 +0100 Subject: [PATCH] Add support for namespace to commands This is being added for #511, so that the list, update, delete and read endpoints all can take an optional namespace override. Tested with k3s 1.15 and two namespaces. Also tested that kube- system is blocked for those commands. Signed-off-by: Alex Ellis (OpenFaaS Ltd) --- handlers/delete.go | 19 ++++++++++++++++--- handlers/reader.go | 16 ++++++++++++++-- handlers/update.go | 20 ++++++++++++++++---- 3 files changed, 46 insertions(+), 9 deletions(-) diff --git a/handlers/delete.go b/handlers/delete.go index a174f2ebe..aa8591f86 100644 --- a/handlers/delete.go +++ b/handlers/delete.go @@ -16,10 +16,23 @@ import ( ) // MakeDeleteHandler delete a function -func MakeDeleteHandler(functionNamespace string, clientset *kubernetes.Clientset) http.HandlerFunc { +func MakeDeleteHandler(defaultNamespace string, clientset *kubernetes.Clientset) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { defer r.Body.Close() + q := r.URL.Query() + namespace := q.Get("namespace") + + lookupNamespace := defaultNamespace + + if len(namespace) > 0 { + lookupNamespace = namespace + } + + if lookupNamespace == "kube-system" { + http.Error(w, "unable to list within the kube-system namespace", http.StatusUnauthorized) + } + body, _ := ioutil.ReadAll(r.Body) request := requests.DeleteFunctionRequest{} @@ -37,7 +50,7 @@ func MakeDeleteHandler(functionNamespace string, clientset *kubernetes.Clientset // This makes sure we don't delete non-labelled deployments deployment, findDeployErr := clientset.AppsV1(). - Deployments(functionNamespace). + Deployments(lookupNamespace). Get(request.FunctionName, getOpts) if findDeployErr != nil { @@ -52,7 +65,7 @@ func MakeDeleteHandler(functionNamespace string, clientset *kubernetes.Clientset } if isFunction(deployment) { - deleteFunction(functionNamespace, clientset, request, w) + deleteFunction(lookupNamespace, clientset, request, w) } else { w.WriteHeader(http.StatusBadRequest) diff --git a/handlers/reader.go b/handlers/reader.go index 5bdb04cfa..59b450be9 100644 --- a/handlers/reader.go +++ b/handlers/reader.go @@ -17,10 +17,22 @@ import ( ) // MakeFunctionReader handler for reading functions deployed in the cluster as deployments. -func MakeFunctionReader(functionNamespace string, clientset *kubernetes.Clientset) http.HandlerFunc { +func MakeFunctionReader(defaultNamespace string, clientset *kubernetes.Clientset) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { + q := r.URL.Query() + namespace := q.Get("namespace") - functions, err := getServiceList(functionNamespace, clientset) + lookupNamespace := defaultNamespace + + if len(namespace) > 0 { + lookupNamespace = namespace + } + + if lookupNamespace == "kube-system" { + http.Error(w, "unable to list within the kube-system namespace", http.StatusUnauthorized) + } + + functions, err := getServiceList(lookupNamespace, clientset) if err != nil { log.Println(err) w.WriteHeader(http.StatusInternalServerError) diff --git a/handlers/update.go b/handlers/update.go index cc20f0073..baf1542f5 100644 --- a/handlers/update.go +++ b/handlers/update.go @@ -18,11 +18,23 @@ import ( ) // MakeUpdateHandler update specified function -func MakeUpdateHandler(functionNamespace string, factory k8s.FunctionFactory) http.HandlerFunc { +func MakeUpdateHandler(defaultNamespace string, factory k8s.FunctionFactory) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { - defer r.Body.Close() + q := r.URL.Query() + namespace := q.Get("namespace") + + lookupNamespace := defaultNamespace + + if len(namespace) > 0 { + lookupNamespace = namespace + } + + if lookupNamespace == "kube-system" { + http.Error(w, "unable to list within the kube-system namespace", http.StatusUnauthorized) + } + body, _ := ioutil.ReadAll(r.Body) request := types.FunctionDeployment{} @@ -33,12 +45,12 @@ func MakeUpdateHandler(functionNamespace string, factory k8s.FunctionFactory) ht } annotations := buildAnnotations(request) - if err, status := updateDeploymentSpec(functionNamespace, factory, request, annotations); err != nil { + if err, status := updateDeploymentSpec(lookupNamespace, factory, request, annotations); err != nil { w.WriteHeader(status) w.Write([]byte(err.Error())) } - if err, status := updateService(functionNamespace, factory, request, annotations); err != nil { + if err, status := updateService(lookupNamespace, factory, request, annotations); err != nil { w.WriteHeader(status) w.Write([]byte(err.Error())) }