Skip to content

Instantly share code, notes, and snippets.

@judell
Last active May 5, 2024 00:39
Show Gist options
  • Save judell/ead7ba97cbb3453cbc8858f00b804c21 to your computer and use it in GitHub Desktop.
Save judell/ead7ba97cbb3453cbc8858f00b804c21 to your computer and use it in GitHub Desktop.
kolide.listAnything
func listAnything(ctx context.Context, d *plugin.QueryData, h *plugin.HydrateData, callee string, visitor ListPredicate, target string) (interface{}, error) {
// Create a slice to hold search queries
searches, err := query(ctx, d)
if err != nil {
plugin.Logger(ctx).Error(callee, "qualifier_operator_error", err)
return nil, err
}
// Establish connection to Kolide client
client, err := connect(ctx, d)
if err != nil {
plugin.Logger(ctx).Error(callee, "connection_error", err)
return nil, err
}
// Iterate through pagination cursors, with smallest number of pages
var maxLimit int32 = kolide.MaxPaging
if d.QueryContext.Limit != nil {
limit := int32(*d.QueryContext.Limit)
if limit < maxLimit {
maxLimit = limit
}
}
cursor := ""
for {
// Respect rate limiting
d.WaitForListRateLimit(ctx)
res, err := visitor(client, cursor, maxLimit, searches...)
if err != nil {
plugin.Logger(ctx).Error(callee, err)
return nil, err
}
// Stream retrieved results
collection := reflect.ValueOf(res).Elem().FieldByName(target)
if collection.IsValid() {
for i := 0; i < collection.Len(); i++ {
d.StreamListItem(ctx, collection.Index(i).Interface())
// Context can be cancelled due to manual cancellation or the limit has been hit
if d.RowsRemaining(ctx) == 0 {
return nil, nil
}
}
}
next := reflect.ValueOf(res).Elem().FieldByName("Pagination").FieldByName("NextCursor")
if next.IsValid() {
cursor = next.Interface().(string)
}
if cursor == "" {
break
}
}
return nil, nil
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment