Skip to content

Commit b557c9c

Browse files
committed
Add support for excluding a list of parameters from an API response
1 parent 91f5600 commit b557c9c

File tree

4 files changed

+77
-26
lines changed

4 files changed

+77
-26
lines changed

cli/completer.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -357,6 +357,7 @@ func (t *autoCompleter) Do(line []rune, pos int) (options [][]rune, offset int)
357357
}
358358
return
359359
}
360+
360361
if arg.Type == config.FAKE && arg.Name == "filter=" {
361362
offset = 0
362363
filterInputs := strings.Split(strings.Replace(argInput, ",", ",|", -1), "|")
@@ -373,6 +374,22 @@ func (t *autoCompleter) Do(line []rune, pos int) (options [][]rune, offset int)
373374
return
374375
}
375376

377+
if arg.Type == config.FAKE && arg.Name == "exclude=" {
378+
offset = 0
379+
excludeFilterInputs := strings.Split(strings.Replace(argInput, ",", ",|", -1), "|")
380+
lastExcludeFilterInput := lastString(excludeFilterInputs)
381+
for _, key := range apiFound.ResponseKeys {
382+
if inArray(key, excludeFilterInputs) {
383+
continue
384+
}
385+
if strings.HasPrefix(key, lastExcludeFilterInput) {
386+
options = append(options, []rune(key[len(lastExcludeFilterInput):]))
387+
offset = len(lastExcludeFilterInput)
388+
}
389+
}
390+
return
391+
}
392+
376393
autocompleteAPI := findAutocompleteAPI(arg, apiFound, apiMap)
377394
if autocompleteAPI == nil {
378395
return nil, 0

cmd/api.go

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ func init() {
8282
if strings.HasSuffix(err.Error(), "context canceled") {
8383
return nil
8484
} else if response != nil {
85-
printResult(r.Config.Core.Output, response, nil)
85+
printResult(r.Config.Core.Output, response, nil, nil)
8686
}
8787
return err
8888
}
@@ -98,8 +98,19 @@ func init() {
9898
}
9999
}
100100

101+
var excludeKeys []string
102+
for _, arg := range apiArgs {
103+
if strings.HasPrefix(arg, "exclude=") {
104+
for _, excludeKey := range strings.Split(strings.Split(arg, "=")[1], ",") {
105+
if len(strings.TrimSpace(excludeKey)) > 0 {
106+
excludeKeys = append(excludeKeys, strings.TrimSpace(excludeKey))
107+
}
108+
}
109+
}
110+
}
111+
101112
if len(response) > 0 {
102-
printResult(r.Config.Core.Output, response, filterKeys)
113+
printResult(r.Config.Core.Output, response, filterKeys, excludeKeys)
103114
}
104115

105116
return nil

cmd/output.go

Lines changed: 40 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -206,51 +206,67 @@ func printCsv(response map[string]interface{}, filter []string) {
206206
enc.Flush()
207207
}
208208

209-
func filterResponse(response map[string]interface{}, filter []string, outputType string) map[string]interface{} {
210-
if filter == nil || len(filter) == 0 {
209+
func filterResponse(response map[string]interface{}, filter []string, excludeFilter []string, outputType string) map[string]interface{} {
210+
if (filter == nil || len(filter) == 0) && (excludeFilter == nil || len(excludeFilter) == 0) {
211211
return response
212212
}
213+
214+
excludeSet := make(map[string]struct{}, len(excludeFilter))
215+
for _, key := range excludeFilter {
216+
excludeSet[key] = struct{}{}
217+
}
218+
219+
filterSet := make(map[string]struct{}, len(filter))
220+
for _, key := range filter {
221+
filterSet[key] = struct{}{}
222+
}
223+
213224
filteredResponse := make(map[string]interface{})
214-
for k, v := range response {
215-
valueType := reflect.TypeOf(v)
216-
if valueType.Kind() == reflect.Slice || valueType.Kind() == reflect.Map {
217-
items, ok := v.([]interface{})
218-
if !ok {
219-
continue
220-
}
225+
226+
for key, value := range response {
227+
switch items := value.(type) {
228+
case []interface{}:
221229
var filteredRows []interface{}
222230
for _, item := range items {
223231
row, ok := item.(map[string]interface{})
224-
if !ok || len(row) < 1 {
232+
if !ok || len(row) == 0 {
225233
continue
226234
}
235+
227236
filteredRow := make(map[string]interface{})
228-
for _, filterKey := range filter {
229-
for field := range row {
230-
if filterKey == field {
231-
filteredRow[field] = row[field]
237+
238+
if len(filter) > 0 {
239+
// Include only keys that exist in filterSet
240+
for filterKey := range filterSet {
241+
if val, exists := row[filterKey]; exists {
242+
filteredRow[filterKey] = val
243+
} else if outputType == config.COLUMN || outputType == config.CSV || outputType == config.TABLE {
244+
filteredRow[filterKey] = "" // Ensure all filter keys exist in row
232245
}
233246
}
234-
if outputType == config.COLUMN || outputType == config.CSV || outputType == config.TABLE {
235-
if _, ok := filteredRow[filterKey]; !ok {
236-
filteredRow[filterKey] = ""
247+
} else {
248+
// Exclude keys from excludeFilter
249+
for field, val := range row {
250+
if _, excluded := excludeSet[field]; !excluded {
251+
filteredRow[field] = val
237252
}
238253
}
239254
}
255+
240256
filteredRows = append(filteredRows, filteredRow)
241257
}
242-
filteredResponse[k] = filteredRows
243-
} else {
244-
filteredResponse[k] = v
245-
continue
246-
}
258+
filteredResponse[key] = filteredRows
247259

260+
default:
261+
filteredResponse[key] = value
262+
}
248263
}
264+
249265
return filteredResponse
250266
}
251267

252-
func printResult(outputType string, response map[string]interface{}, filter []string) {
253-
response = filterResponse(response, filter, outputType)
268+
func printResult(outputType string, response map[string]interface{}, filter []string, excludeFilter []string) {
269+
response = filterResponse(response, filter, excludeFilter, outputType)
254270
switch outputType {
255271
case config.JSON:
256272
printJSON(response)

config/cache.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,13 @@ func (c *Config) UpdateCache(response map[string]interface{}) interface{} {
151151
Description: "cloudmonkey specific response key filtering",
152152
})
153153

154+
// Add exclude arg
155+
apiArgs = append(apiArgs, &APIArg{
156+
Name: "exclude=",
157+
Type: FAKE,
158+
Description: "cloudmonkey specific response key to exlude when filtering",
159+
})
160+
154161
sort.Slice(apiArgs, func(i, j int) bool {
155162
return apiArgs[i].Name < apiArgs[j].Name
156163
})

0 commit comments

Comments
 (0)