2016-11-16 13:47:49 +00:00
|
|
|
package inmem
|
2016-09-30 01:19:51 +00:00
|
|
|
|
2016-10-04 20:34:36 +00:00
|
|
|
import (
|
2016-10-13 18:21:47 +00:00
|
|
|
"sort"
|
|
|
|
|
2017-06-22 19:50:45 +00:00
|
|
|
"github.com/kolide/fleet/server/kolide"
|
2017-01-13 18:35:25 +00:00
|
|
|
"github.com/pkg/errors"
|
2016-10-04 20:34:36 +00:00
|
|
|
)
|
2016-09-30 01:19:51 +00:00
|
|
|
|
2017-05-30 19:42:00 +00:00
|
|
|
func (d *Datastore) NewQuery(query *kolide.Query, opts ...kolide.OptionalArg) (*kolide.Query, error) {
|
2016-12-16 00:12:43 +00:00
|
|
|
d.mtx.Lock()
|
|
|
|
defer d.mtx.Unlock()
|
2016-09-30 01:19:51 +00:00
|
|
|
|
|
|
|
newQuery := *query
|
|
|
|
|
2016-12-16 00:12:43 +00:00
|
|
|
for _, q := range d.queries {
|
2016-09-30 01:19:51 +00:00
|
|
|
if query.Name == q.Name {
|
2016-12-20 18:35:22 +00:00
|
|
|
return nil, alreadyExists("Query", q.ID)
|
2016-09-30 01:19:51 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-12-16 00:12:43 +00:00
|
|
|
newQuery.ID = d.nextID(newQuery)
|
2017-01-06 01:48:56 +00:00
|
|
|
newQuery.Packs = []kolide.Pack{}
|
2016-12-16 00:12:43 +00:00
|
|
|
d.queries[newQuery.ID] = &newQuery
|
2016-09-30 01:19:51 +00:00
|
|
|
|
|
|
|
return &newQuery, nil
|
|
|
|
}
|
|
|
|
|
2016-12-16 00:12:43 +00:00
|
|
|
func (d *Datastore) SaveQuery(query *kolide.Query) error {
|
|
|
|
d.mtx.Lock()
|
|
|
|
defer d.mtx.Unlock()
|
2016-09-30 01:19:51 +00:00
|
|
|
|
2016-12-16 00:12:43 +00:00
|
|
|
if _, ok := d.queries[query.ID]; !ok {
|
2016-12-20 18:35:22 +00:00
|
|
|
return notFound("Query").WithID(query.ID)
|
2016-09-30 01:19:51 +00:00
|
|
|
}
|
|
|
|
|
2016-12-16 00:12:43 +00:00
|
|
|
d.queries[query.ID] = query
|
2016-09-30 01:19:51 +00:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2016-12-09 17:12:45 +00:00
|
|
|
// DeleteQueries (soft) deletes the existing query objects with the provided
|
|
|
|
// IDs. The number of deleted queries is returned along with any error.
|
2016-12-16 00:12:43 +00:00
|
|
|
func (d *Datastore) DeleteQueries(ids []uint) (uint, error) {
|
|
|
|
d.mtx.Lock()
|
|
|
|
defer d.mtx.Unlock()
|
2016-12-09 17:12:45 +00:00
|
|
|
|
|
|
|
deleted := uint(0)
|
|
|
|
for _, id := range ids {
|
2016-12-16 00:12:43 +00:00
|
|
|
if _, ok := d.queries[id]; ok {
|
|
|
|
delete(d.queries, id)
|
2016-12-09 17:12:45 +00:00
|
|
|
deleted++
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return deleted, nil
|
|
|
|
}
|
2016-09-30 01:19:51 +00:00
|
|
|
|
2016-12-16 00:12:43 +00:00
|
|
|
func (d *Datastore) getUserNameByID(id uint) string {
|
|
|
|
if u, ok := d.users[id]; ok {
|
2016-12-07 20:22:31 +00:00
|
|
|
return u.Name
|
|
|
|
}
|
|
|
|
return ""
|
|
|
|
}
|
|
|
|
|
2016-12-16 00:12:43 +00:00
|
|
|
func (d *Datastore) Query(id uint) (*kolide.Query, error) {
|
|
|
|
d.mtx.Lock()
|
|
|
|
defer d.mtx.Unlock()
|
2016-09-30 01:19:51 +00:00
|
|
|
|
2016-12-16 00:12:43 +00:00
|
|
|
query, ok := d.queries[id]
|
2016-09-30 01:19:51 +00:00
|
|
|
if !ok {
|
2016-12-20 18:35:22 +00:00
|
|
|
return nil, notFound("Query").WithID(id)
|
2016-09-30 01:19:51 +00:00
|
|
|
}
|
|
|
|
|
2018-10-11 19:37:18 +00:00
|
|
|
query.AuthorName = d.getUserNameByID(*query.AuthorID)
|
2016-12-07 20:22:31 +00:00
|
|
|
|
2016-12-16 00:12:43 +00:00
|
|
|
if err := d.loadPacksForQueries([]*kolide.Query{query}); err != nil {
|
2017-01-13 18:35:25 +00:00
|
|
|
return nil, errors.Wrap(err, "error fetching query by id")
|
2016-12-06 18:22:28 +00:00
|
|
|
}
|
|
|
|
|
2016-09-30 01:19:51 +00:00
|
|
|
return query, nil
|
|
|
|
}
|
|
|
|
|
2016-12-16 00:12:43 +00:00
|
|
|
func (d *Datastore) ListQueries(opt kolide.ListOptions) ([]*kolide.Query, error) {
|
|
|
|
d.mtx.Lock()
|
|
|
|
defer d.mtx.Unlock()
|
2016-09-30 01:19:51 +00:00
|
|
|
|
2016-10-13 18:21:47 +00:00
|
|
|
// We need to sort by keys to provide reliable ordering
|
|
|
|
keys := []int{}
|
2016-12-16 00:12:43 +00:00
|
|
|
for k, _ := range d.queries {
|
2016-10-13 18:21:47 +00:00
|
|
|
keys = append(keys, int(k))
|
|
|
|
}
|
|
|
|
sort.Ints(keys)
|
|
|
|
|
2016-09-30 01:19:51 +00:00
|
|
|
queries := []*kolide.Query{}
|
2016-10-13 18:21:47 +00:00
|
|
|
for _, k := range keys {
|
2016-12-16 00:12:43 +00:00
|
|
|
q := d.queries[uint(k)]
|
2016-12-07 20:22:31 +00:00
|
|
|
if q.Saved {
|
2018-10-11 19:37:18 +00:00
|
|
|
q.AuthorName = d.getUserNameByID(*q.AuthorID)
|
2016-12-07 20:22:31 +00:00
|
|
|
queries = append(queries, q)
|
2016-12-06 18:16:04 +00:00
|
|
|
}
|
2016-09-30 01:19:51 +00:00
|
|
|
}
|
|
|
|
|
2016-10-17 14:01:14 +00:00
|
|
|
// Apply ordering
|
|
|
|
if opt.OrderKey != "" {
|
|
|
|
var fields = map[string]string{
|
|
|
|
"id": "ID",
|
|
|
|
"created_at": "CreatedAt",
|
|
|
|
"updated_at": "UpdatedAt",
|
|
|
|
"name": "Name",
|
|
|
|
"query": "Query",
|
|
|
|
"interval": "Interval",
|
|
|
|
"snapshot": "Snapshot",
|
|
|
|
"differential": "Differential",
|
|
|
|
"platform": "Platform",
|
|
|
|
"version": "Version",
|
|
|
|
}
|
|
|
|
if err := sortResults(queries, opt, fields); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-10-13 18:21:47 +00:00
|
|
|
// Apply limit/offset
|
2016-12-16 00:12:43 +00:00
|
|
|
low, high := d.getLimitOffsetSliceBounds(opt, len(queries))
|
2016-10-13 18:21:47 +00:00
|
|
|
queries = queries[low:high]
|
|
|
|
|
2016-12-16 00:12:43 +00:00
|
|
|
if err := d.loadPacksForQueries(queries); err != nil {
|
2017-01-13 18:35:25 +00:00
|
|
|
return nil, errors.Wrap(err, "error listing queries")
|
2016-12-06 18:22:28 +00:00
|
|
|
}
|
|
|
|
|
2016-09-30 01:19:51 +00:00
|
|
|
return queries, nil
|
|
|
|
}
|
2016-12-06 18:22:28 +00:00
|
|
|
|
|
|
|
// loadPacksForQueries loads the packs associated with the provided queries
|
2016-12-16 00:12:43 +00:00
|
|
|
func (d *Datastore) loadPacksForQueries(queries []*kolide.Query) error {
|
2016-12-06 18:22:28 +00:00
|
|
|
for _, q := range queries {
|
|
|
|
q.Packs = make([]kolide.Pack, 0)
|
2016-12-16 00:12:43 +00:00
|
|
|
for _, sq := range d.scheduledQueries {
|
2018-01-03 19:18:05 +00:00
|
|
|
if sq.QueryName == q.Name {
|
2016-12-16 00:12:43 +00:00
|
|
|
q.Packs = append(q.Packs, *d.packs[sq.PackID])
|
2016-12-06 18:22:28 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|