diff --git a/cmd/kubectl-tree/query.go b/cmd/kubectl-tree/query.go index 0591d2c..ed60e41 100644 --- a/cmd/kubectl-tree/query.go +++ b/cmd/kubectl-tree/query.go @@ -13,7 +13,7 @@ import ( ) // getAllResources finds all API objects in specified API resources in all namespaces (or non-namespaced). -func getAllResources(client dynamic.Interface, apis []apiResource, allNs bool) ([]unstructured.Unstructured, error) { +func getAllResources(client dynamic.Interface, apis []apiResource, allNs bool, labelSelector string) ([]unstructured.Unstructured, error) { var mu sync.Mutex var wg sync.WaitGroup var out []unstructured.Unstructured @@ -31,7 +31,7 @@ func getAllResources(client dynamic.Interface, apis []apiResource, allNs bool) ( go func(a apiResource) { defer wg.Done() klog.V(4).Infof("[query api] start: %s", a.GroupVersionResource()) - v, err := queryAPI(client, a, allNs) + v, err := queryAPI(client, a, allNs, labelSelector) if err != nil { klog.V(4).Infof("[query api] error querying: %s, error=%v", a.GroupVersionResource(), err) errResult = err @@ -51,7 +51,7 @@ func getAllResources(client dynamic.Interface, apis []apiResource, allNs bool) ( return out, errResult } -func queryAPI(client dynamic.Interface, api apiResource, allNs bool) ([]unstructured.Unstructured, error) { +func queryAPI(client dynamic.Interface, api apiResource, allNs bool, labelSelector string) ([]unstructured.Unstructured, error) { var out []unstructured.Unstructured var next string @@ -68,9 +68,11 @@ func queryAPI(client dynamic.Interface, api apiResource, allNs bool) ([]unstruct } else { intf = nintf } + resp, err := intf.List(context.TODO(), metav1.ListOptions{ - Limit: 250, - Continue: next, + Limit: 250, + Continue: next, + LabelSelector: labelSelector, }) if err != nil { return nil, fmt.Errorf("listing resources failed (%s): %w", api.GroupVersionResource(), err) diff --git a/cmd/kubectl-tree/rootcmd.go b/cmd/kubectl-tree/rootcmd.go index 4a29586..f784275 100644 --- a/cmd/kubectl-tree/rootcmd.go +++ b/cmd/kubectl-tree/rootcmd.go @@ -37,6 +37,7 @@ import ( const ( allNamespacesFlag = "all-namespaces" colorFlag = "color" + labelSelectorFlag = "selector" ) var cf *genericclioptions.ConfigFlags @@ -76,6 +77,12 @@ func run(command *cobra.Command, args []string) error { if err != nil { return err } + + labelSelector, err := command.Flags().GetString(labelSelectorFlag) + if err != nil { + return err + } + if colorArg == "always" { color.NoColor = false } else if colorArg == "never" { @@ -149,7 +156,7 @@ func run(command *cobra.Command, args []string) error { klog.V(5).Infof("target parent object: %#v", obj) klog.V(2).Infof("querying all api objects") - apiObjects, err := getAllResources(dyn, apis.resources(), allNs) + apiObjects, err := getAllResources(dyn, apis.resources(), allNs, labelSelector) if err != nil { return fmt.Errorf("error while querying api objects: %w", err) } @@ -180,6 +187,7 @@ func init() { rootCmd.Flags().BoolP(allNamespacesFlag, "A", false, "query all objects in all API groups, both namespaced and non-namespaced") rootCmd.Flags().StringP(colorFlag, "c", "auto", "Enable or disable color output. This can be 'always', 'never', or 'auto' (default = use color only if using tty). The flag is overridden by the NO_COLOR env variable if set.") + rootCmd.Flags().StringP(labelSelectorFlag, "l", "", "Selector (label query) to filter on, supports '=', '==', and '!='.(e.g. -l key1=value1,key2=value2). Matching objects must satisfy all of the specified label constraints.") cf.AddFlags(rootCmd.Flags()) if err := flag.Set("logtostderr", "true"); err != nil {