@@ -6,6 +6,7 @@ package main
66import (
77 "bufio"
88 "bytes"
9+ "encoding/json"
910 "errors"
1011 "fmt"
1112 "reflect"
@@ -57,6 +58,14 @@ The output can be presented in one of several formats, using the --format <forma
5758 --format yaml - Output in YAML format
5859 --format table - Output in table format
5960 --format '{{ <go template> }}' - If the format begins and ends with '{{ }}', then it is used as a go template.
61+
62+ Filtering instances:
63+ --filter EXPR - Filter instances using yq expression (this is equivalent to --yq 'select(EXPR)')
64+ Can be specified multiple times and it works with all output formats.
65+ Examples:
66+ --filter '.status == "Running"'
67+ --filter '.vmType == "vz"'
68+ --filter '.status == "Running"' --filter '.vmType == "vz"'
6069` + store .FormatHelp + `
6170The following legacy flags continue to function:
6271 --json - equal to '--format json'` ,
@@ -72,6 +81,7 @@ The following legacy flags continue to function:
7281 listCommand .Flags ().BoolP ("quiet" , "q" , false , "Only show names" )
7382 listCommand .Flags ().Bool ("all-fields" , false , "Show all fields" )
7483 listCommand .Flags ().StringArray ("yq" , nil , "Apply yq expression to each instance" )
84+ listCommand .Flags ().StringArrayP ("filter" , "l" , nil , "Filter instances using yq expression (equivalent to --yq 'select(EXPR)')" )
7585
7686 return listCommand
7787}
@@ -121,6 +131,10 @@ func listAction(cmd *cobra.Command, args []string) error {
121131 if err != nil {
122132 return err
123133 }
134+ filter , err := cmd .Flags ().GetStringArray ("filter" )
135+ if err != nil {
136+ return err
137+ }
124138
125139 if jsonFormat {
126140 format = "json"
@@ -141,6 +155,14 @@ func listAction(cmd *cobra.Command, args []string) error {
141155 return errors .New ("option --list-fields conflicts with option --yq" )
142156 }
143157 }
158+ if len (filter ) != 0 {
159+ if listFields {
160+ return errors .New ("option --list-fields conflicts with option --filter" )
161+ }
162+ if len (yq ) != 0 {
163+ return errors .New ("option --filter conflicts with option --yq" )
164+ }
165+ }
144166
145167 if quiet && format != "table" {
146168 return errors .New ("option --quiet can only be used with '--format table'" )
@@ -220,15 +242,31 @@ func listAction(cmd *cobra.Command, args []string) error {
220242 options .TerminalWidth = w
221243 }
222244 }
223- // --yq implies --format json unless --format yaml has been explicitly specified
245+
246+ // --yq implies --format json unless --format has been explicitly specified
224247 if len (yq ) != 0 && ! cmd .Flags ().Changed ("format" ) {
225248 format = "json"
226249 }
250+
227251 // Always pipe JSON and YAML through yq to colorize it if isTTY
228252 if len (yq ) == 0 && (format == "json" || format == "yaml" ) {
229253 yq = append (yq , "." )
230254 }
231255
256+ for _ , f := range filter {
257+ yq = append (yq , "select(" + f + ")" )
258+ }
259+
260+ // handle --filter with table and go-template formats
261+ isGoTemplate := strings .HasPrefix (format , "{{" ) && strings .HasSuffix (format , "}}" )
262+ if len (filter ) != 0 && (format == "table" || isGoTemplate ) {
263+ instances , err = filterInstances (instances , yq )
264+ if err != nil {
265+ return err
266+ }
267+ yq = nil
268+ }
269+
232270 if len (yq ) == 0 {
233271 err = store .PrintInstances (cmd .OutOrStdout (), instances , format , & options )
234272 if err == nil && unmatchedInstances {
@@ -320,3 +358,31 @@ func listAction(cmd *cobra.Command, args []string) error {
320358func listBashComplete (cmd * cobra.Command , _ []string , _ string ) ([]string , cobra.ShellCompDirective ) {
321359 return bashCompleteInstanceNames (cmd )
322360}
361+
362+ // filterInstances applies yq expressions to instances and returns the filtered results.
363+ func filterInstances (instances []* limatype.Instance , yqExprs []string ) ([]* limatype.Instance , error ) {
364+ if len (yqExprs ) == 0 {
365+ return instances , nil
366+ }
367+
368+ yqExpr := strings .Join (yqExprs , " | " )
369+
370+ var filteredInstances []* limatype.Instance
371+ for _ , instance := range instances {
372+ jsonBytes , err := json .Marshal (instance )
373+ if err != nil {
374+ return nil , fmt .Errorf ("failed to marshal instance %s: %v" , instance .Name , err )
375+ }
376+
377+ result , err := yqutil .EvaluateExpression (yqExpr , jsonBytes )
378+ if err != nil {
379+ return nil , fmt .Errorf ("failed to apply filter %s: %v" , yqExpr , err )
380+ }
381+
382+ if len (result ) > 0 {
383+ filteredInstances = append (filteredInstances , instance )
384+ }
385+ }
386+
387+ return filteredInstances , nil
388+ }
0 commit comments