Skip to content

Commit

Permalink
Support wildcard namespace selection
Browse files Browse the repository at this point in the history
  • Loading branch information
mhindery committed May 22, 2020
1 parent 6ae8f75 commit 2b266bf
Showing 1 changed file with 37 additions and 9 deletions.
46 changes: 37 additions & 9 deletions cmd/kubefwd/services/services.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package services
import (
"fmt"
"strconv"
"strings"
"sync"
"time"

Expand Down Expand Up @@ -60,7 +61,7 @@ func init() {

Cmd.Flags().StringP("kubeconfig", "c", "", "absolute path to a kubectl config file")
Cmd.Flags().StringSliceVarP(&contexts, "context", "x", []string{}, "specify a context to override the current context")
Cmd.Flags().StringSliceVarP(&namespaces, "namespace", "n", []string{}, "Specify a namespace. Specify multiple namespaces by duplicating this argument.")
Cmd.Flags().StringSliceVarP(&namespaces, "namespace", "n", []string{}, "Specify a namespace. Specify multiple namespaces by duplicating this argument. Use \"*\" (including the quotes) to use all-but-system (e.g. kube-system) namespaces.")
Cmd.Flags().StringP("selector", "l", "", "Selector (label query) to filter on; supports '=', '==', and '!=' (e.g. -l key1=value1,key2=value2).")
Cmd.Flags().BoolVarP(&exitOnFail, "exitonfailure", "", false, "Exit(1) on failure. Useful for forcing a container restart.")
Cmd.Flags().BoolVarP(&verbose, "verbose", "v", false, "Verbose output.")
Expand All @@ -81,15 +82,18 @@ var Cmd = &cobra.Command{
Run: runCmd,
}

// checkConnection tests if you can connect to the cluster in your config,
// and if you have the necessary permissions to use kubefwd.
func checkConnection(clientSet *kubernetes.Clientset, namespaces []string) error {
// Check simple connectivity: can you connect to the api server
// checkConnection tests if you can connect to the cluster in your config
func checkConnectivity(clientSet *kubernetes.Clientset) error {
_, err := clientSet.Discovery().ServerVersion()
if err != nil {
return err
}

return nil
}

// checkNamespacePermissions tests if you have the necessary permissions to use kubefwd.
func checkNamespacePermissions(clientSet *kubernetes.Clientset, namespaces []string) error {
// Check RBAC permissions for each of the requested namespaces
requiredPermissions := []authorizationv1.ResourceAttributes{
{Verb: "list", Resource: "pods"}, {Verb: "get", Resource: "pods"}, {Verb: "watch", Resource: "pods"},
Expand All @@ -103,7 +107,7 @@ func checkConnection(clientSet *kubernetes.Clientset, namespaces []string) error
ResourceAttributes: &perm,
},
}
ssar, err = clientSet.AuthorizationV1().SelfSubjectAccessReviews().Create(ssar)
ssar, err := clientSet.AuthorizationV1().SelfSubjectAccessReviews().Create(ssar)
if err != nil {
return err
}
Expand Down Expand Up @@ -192,8 +196,8 @@ Try:
listOptions.LabelSelector = selector
}

// if no namespaces were specified, check config then
// explicitly set one to "default"
// if no namespaces were specified via the flags, check config from the k8s context
// then explicitly set one to "default"
if len(namespaces) < 1 {
namespaces = []string{"default"}
x := rawConfig.CurrentContext
Expand Down Expand Up @@ -244,12 +248,36 @@ Try:
}

// check connectivity
err = checkConnection(clientSet, namespaces)
err = checkConnectivity(clientSet)
if err != nil {
log.Fatalf("Error connecting to k8s cluster: %s\n", err.Error())
}
log.Infof("Succesfully connected context: %v", ctx)

// If a wildcard namespace selector was given, query for all the namespaces and use all non-kube-internal ones
if len(namespaces) == 1 && namespaces[0] == "*" {
// Query for the names of all namespaces
namespacesList, err := clientSet.CoreV1().Namespaces().List(metav1.ListOptions{})
if err != nil {
log.Fatalf("Error obtaining namespaces from cluster: %s\n", err.Error())
}

// Construct list of the ones to use
namespaces = nil
for _, ns := range namespacesList.Items {
if !strings.HasPrefix(ns.Name, "kube-") {
namespaces = append(namespaces, ns.Name)
}
}
log.Infof("Namespaces to forward (via wildcard): %s", namespaces)
}

// Permission check on all the namespaces
err = checkNamespacePermissions(clientSet, namespaces)
if err != nil {
log.Fatalf("Failed RBAC permission check: %s\n", err.Error())
}

// create the k8s RESTclient
restClient, err := configGetter.GetRESTClient()
if err != nil {
Expand Down

0 comments on commit 2b266bf

Please sign in to comment.