diff --git a/.tool-versions b/.tool-versions index e2e8ceb..009efa3 100644 --- a/.tool-versions +++ b/.tool-versions @@ -1 +1 @@ -golang 1.17.3 +golang 1.22.5 diff --git a/README.md b/README.md index e884394..64433c2 100644 --- a/README.md +++ b/README.md @@ -42,7 +42,7 @@ ### Source install #### Requirements -* A working [Go](https://golang.org/) install (tested only with 1.17) +* A working [Go](https://golang.org/) install (tested only with 1.22) A particular release: ``` @@ -144,7 +144,7 @@ golangci-list run ## TODO - [x] Automated (binary) builds. - [ ] Tests. -- [ ] Limit by namespace. +- [x] Limit by namespace. - [ ] Separate scanning from reporting. * Save scans for later? * Save whole scan? Doing so would mean not using built-in k8s selector support if we want to be diff --git a/go.mod b/go.mod index 7f0681b..89c6964 100644 --- a/go.mod +++ b/go.mod @@ -44,4 +44,4 @@ require ( sigs.k8s.io/yaml v1.3.0 // indirect ) -go 1.17 +go 1.22 diff --git a/go.sum b/go.sum index 1ab491a..da906b0 100644 --- a/go.sum +++ b/go.sum @@ -350,7 +350,6 @@ golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210910150752-751e447fb3d0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211124211545-fe61309f8881 h1:TyHqChC80pFkXWraUUf6RuB5IqFdQieMLwwCJokV2pc= diff --git a/main.go b/main.go index 4e52d56..62f535c 100644 --- a/main.go +++ b/main.go @@ -27,7 +27,7 @@ import ( var logger = log.New() var summaryOnly, includePods bool -var kubeconfig, kubecontext, nodeLabelSelector, podLabelSelector *string +var kubeconfig, kubecontext, nodeLabelSelector, podLabelSelector, nodeFieldSelector, podFieldSelector *string var clusterStats = clusterResourceUsage{} @@ -39,7 +39,9 @@ func init() { kubeconfig = flag.String("kubeconfig", "", "Absolute path to a kubeconfig file. Uses ~/.kube/config by default.") kubecontext = flag.String("context", "", "The name of the kubeconfig context to use") nodeLabelSelector = flag.StringP("node-selector", "N", "", "Label selector for nodes to include") + nodeFieldSelector = flag.StringP("node-field-selector", "", "", "Node FieldSelector - only supports 'spec.unschedulable'. See: https://kubernetes.io/docs/concepts/overview/working-with-objects/field-selectors/") podLabelSelector = flag.StringP("pod-selector", "P", "", "Label selector for pods to include") + podFieldSelector = flag.StringP("pod-field-selector", "", "", "Pod FieldSelector - useful for Namespace selection. See: https://kubernetes.io/docs/concepts/overview/working-with-objects/field-selectors/") flag.BoolVarP(&includePods, "include-pods", "p", false, "Include Pod resource data in output") flag.BoolVarP(&summaryOnly, "summary", "s", false, "Show only the cumulative cluster summary") help := flag.BoolP("help", "h", false, "Show help") @@ -72,6 +74,7 @@ func main() { ctx := context.Background() nodeList, err := client.CoreV1().Nodes().List(ctx, metav1.ListOptions{ LabelSelector: *nodeLabelSelector, + FieldSelector: *nodeFieldSelector, }) if err != nil { logger.WithFields(log.Fields{ @@ -82,6 +85,8 @@ func main() { "numNodes": len(nodeList.Items), "nodeLabelSelector": *nodeLabelSelector, "podLabelSelector": *podLabelSelector, + "nodeFieldSelector": *nodeFieldSelector, + "podFieldSelector": *podFieldSelector, }).Info("Found nodes") wg := sync.WaitGroup{} @@ -187,13 +192,13 @@ func processNode(client *kubernetes.Clientset, node v1.Node, progress *mpb.Progr nodeStats.Allocatable.CPU = *node.Status.Allocatable.Cpu() nodeStats.Allocatable.Memory = *node.Status.Allocatable.Memory() - nodeFieldSelector := fields.OneTermEqualSelector("spec.nodeName", node.GetName()).String() + fieldSelector := fmt.Sprintf("%s,%s", fields.OneTermEqualSelector("spec.nodeName", node.GetName()).String(), *podFieldSelector) ctx := context.Background() podsList, err := client.CoreV1().Pods("").List(ctx, metav1.ListOptions{ // Apply label selector from cli args LabelSelector: *podLabelSelector, // Limit to Pods on the current Node - FieldSelector: nodeFieldSelector, + FieldSelector: fieldSelector, }) if err != nil { logger.WithFields(log.Fields{