2016-11-16 13:47:49 +00:00
|
|
|
package inmem
|
2016-09-30 01:19:51 +00:00
|
|
|
|
|
|
|
import (
|
|
|
|
"errors"
|
2016-10-17 19:30:47 +00:00
|
|
|
"sort"
|
2016-09-30 01:19:51 +00:00
|
|
|
"strconv"
|
2016-11-02 14:59:53 +00:00
|
|
|
"strings"
|
2016-09-30 01:19:51 +00:00
|
|
|
"time"
|
|
|
|
|
2017-06-22 19:50:45 +00:00
|
|
|
"github.com/kolide/fleet/server/kolide"
|
2016-12-15 02:27:22 +00:00
|
|
|
"github.com/patrickmn/sortutil"
|
2016-09-30 01:19:51 +00:00
|
|
|
)
|
|
|
|
|
2017-05-30 19:42:00 +00:00
|
|
|
func (d *Datastore) NewLabel(label *kolide.Label, opts ...kolide.OptionalArg) (*kolide.Label, error) {
|
2017-01-13 18:35:25 +00:00
|
|
|
d.mtx.Lock()
|
|
|
|
defer d.mtx.Unlock()
|
2016-09-30 01:19:51 +00:00
|
|
|
newLabel := *label
|
|
|
|
|
2016-12-16 00:12:43 +00:00
|
|
|
for _, l := range d.labels {
|
2016-09-30 01:19:51 +00:00
|
|
|
if l.Name == label.Name {
|
2016-12-20 18:35:22 +00:00
|
|
|
return nil, alreadyExists("Label", l.ID)
|
2016-09-30 01:19:51 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-12-16 00:12:43 +00:00
|
|
|
newLabel.ID = d.nextID(label)
|
|
|
|
d.labels[newLabel.ID] = &newLabel
|
2016-09-30 01:19:51 +00:00
|
|
|
|
|
|
|
return &newLabel, nil
|
|
|
|
}
|
|
|
|
|
2016-12-16 00:12:43 +00:00
|
|
|
func (d *Datastore) ListLabelsForHost(hid uint) ([]kolide.Label, error) {
|
2017-01-16 22:57:05 +00:00
|
|
|
d.mtx.Lock()
|
|
|
|
defer d.mtx.Unlock()
|
2016-09-30 01:19:51 +00:00
|
|
|
// First get IDs of label executions for the host
|
|
|
|
resLabels := []kolide.Label{}
|
2016-10-17 19:30:47 +00:00
|
|
|
|
2016-12-16 00:12:43 +00:00
|
|
|
for _, lqe := range d.labelQueryExecutions {
|
2016-10-03 03:14:35 +00:00
|
|
|
if lqe.HostID == hid && lqe.Matches {
|
2016-12-16 00:12:43 +00:00
|
|
|
if label := d.labels[lqe.LabelID]; label != nil {
|
2016-09-30 01:19:51 +00:00
|
|
|
resLabels = append(resLabels, *label)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return resLabels, nil
|
|
|
|
}
|
|
|
|
|
2016-12-16 00:12:43 +00:00
|
|
|
func (d *Datastore) LabelQueriesForHost(host *kolide.Host, cutoff time.Time) (map[string]string, error) {
|
2017-01-16 22:57:05 +00:00
|
|
|
d.mtx.Lock()
|
|
|
|
defer d.mtx.Unlock()
|
2016-09-30 01:19:51 +00:00
|
|
|
// Get post-cutoff executions for host
|
2016-11-03 01:17:23 +00:00
|
|
|
execedIDs := map[uint]bool{}
|
2016-10-17 19:30:47 +00:00
|
|
|
|
2016-12-16 00:12:43 +00:00
|
|
|
for _, lqe := range d.labelQueryExecutions {
|
2016-09-30 01:19:51 +00:00
|
|
|
if lqe.HostID == host.ID && (lqe.UpdatedAt == cutoff || lqe.UpdatedAt.After(cutoff)) {
|
2016-11-03 01:17:23 +00:00
|
|
|
execedIDs[lqe.LabelID] = true
|
2016-09-30 01:19:51 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-11-03 01:17:23 +00:00
|
|
|
queries := map[string]string{}
|
2016-12-16 00:12:43 +00:00
|
|
|
for _, label := range d.labels {
|
2016-11-03 01:17:23 +00:00
|
|
|
if (label.Platform == "" || strings.Contains(label.Platform, host.Platform)) && !execedIDs[label.ID] {
|
|
|
|
queries[strconv.Itoa(int(label.ID))] = label.Query
|
2016-09-30 01:19:51 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-11-03 01:17:23 +00:00
|
|
|
return queries, nil
|
2016-09-30 01:19:51 +00:00
|
|
|
}
|
|
|
|
|
2017-01-17 06:03:51 +00:00
|
|
|
func (d *Datastore) RecordLabelQueryExecutions(host *kolide.Host, results map[uint]bool, t time.Time) error {
|
2016-09-30 01:19:51 +00:00
|
|
|
// Record executions
|
2017-01-17 06:03:51 +00:00
|
|
|
for labelID, matches := range results {
|
|
|
|
label, ok := d.labels[labelID]
|
|
|
|
if !ok {
|
|
|
|
return notFound("Label").WithID(labelID)
|
2016-09-30 01:19:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
updated := false
|
2016-12-16 00:12:43 +00:00
|
|
|
d.mtx.Lock()
|
|
|
|
for _, lqe := range d.labelQueryExecutions {
|
2016-09-30 01:19:51 +00:00
|
|
|
if lqe.LabelID == label.ID && lqe.HostID == host.ID {
|
|
|
|
// Update existing execution values
|
|
|
|
lqe.UpdatedAt = t
|
|
|
|
lqe.Matches = matches
|
|
|
|
updated = true
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if !updated {
|
|
|
|
// Create new execution
|
|
|
|
lqe := kolide.LabelQueryExecution{
|
|
|
|
HostID: host.ID,
|
|
|
|
LabelID: label.ID,
|
|
|
|
UpdatedAt: t,
|
|
|
|
Matches: matches,
|
|
|
|
}
|
2016-12-16 00:12:43 +00:00
|
|
|
lqe.ID = d.nextID(lqe)
|
|
|
|
d.labelQueryExecutions[lqe.ID] = &lqe
|
2016-09-30 01:19:51 +00:00
|
|
|
}
|
2016-12-16 00:12:43 +00:00
|
|
|
d.mtx.Unlock()
|
2016-10-17 19:30:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2016-12-16 00:12:43 +00:00
|
|
|
func (d *Datastore) Label(lid uint) (*kolide.Label, error) {
|
|
|
|
d.mtx.Lock()
|
|
|
|
label, ok := d.labels[lid]
|
|
|
|
d.mtx.Unlock()
|
2016-10-17 19:30:47 +00:00
|
|
|
|
|
|
|
if !ok {
|
|
|
|
return nil, errors.New("Label not found")
|
|
|
|
}
|
|
|
|
return label, nil
|
|
|
|
}
|
|
|
|
|
2016-12-16 00:12:43 +00:00
|
|
|
func (d *Datastore) ListLabels(opt kolide.ListOptions) ([]*kolide.Label, error) {
|
2017-01-16 22:57:05 +00:00
|
|
|
d.mtx.Lock()
|
|
|
|
defer d.mtx.Unlock()
|
2016-10-17 19:30:47 +00:00
|
|
|
// We need to sort by keys to provide reliable ordering
|
|
|
|
keys := []int{}
|
|
|
|
|
2017-01-16 22:57:05 +00:00
|
|
|
for k := range d.labels {
|
2016-10-17 19:30:47 +00:00
|
|
|
keys = append(keys, int(k))
|
|
|
|
}
|
|
|
|
sort.Ints(keys)
|
|
|
|
|
|
|
|
labels := []*kolide.Label{}
|
|
|
|
for _, k := range keys {
|
2016-12-16 00:12:43 +00:00
|
|
|
labels = append(labels, d.labels[uint(k)])
|
2016-10-17 19:30:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Apply ordering
|
|
|
|
if opt.OrderKey != "" {
|
|
|
|
var fields = map[string]string{
|
|
|
|
"id": "ID",
|
|
|
|
"created_at": "CreatedAt",
|
|
|
|
"updated_at": "UpdatedAt",
|
|
|
|
"name": "Name",
|
|
|
|
}
|
|
|
|
if err := sortResults(labels, opt, fields); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2016-09-30 01:19:51 +00:00
|
|
|
}
|
|
|
|
|
2016-10-17 19:30:47 +00:00
|
|
|
// Apply limit/offset
|
2016-12-16 00:12:43 +00:00
|
|
|
low, high := d.getLimitOffsetSliceBounds(opt, len(labels))
|
2016-10-17 19:30:47 +00:00
|
|
|
labels = labels[low:high]
|
|
|
|
|
|
|
|
return labels, nil
|
|
|
|
}
|
|
|
|
|
2016-12-16 00:12:43 +00:00
|
|
|
func (d *Datastore) SearchLabels(query string, omit ...uint) ([]kolide.Label, error) {
|
2016-11-02 14:59:53 +00:00
|
|
|
omitLookup := map[uint]bool{}
|
|
|
|
for _, o := range omit {
|
|
|
|
omitLookup[o] = true
|
|
|
|
}
|
|
|
|
|
|
|
|
var results []kolide.Label
|
|
|
|
|
2016-12-16 00:12:43 +00:00
|
|
|
d.mtx.Lock()
|
|
|
|
defer d.mtx.Unlock()
|
2016-11-02 14:59:53 +00:00
|
|
|
|
2016-12-16 00:12:43 +00:00
|
|
|
for _, l := range d.labels {
|
2016-11-02 14:59:53 +00:00
|
|
|
if len(results) == 10 {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
|
2016-12-15 02:27:22 +00:00
|
|
|
if (strings.Contains(l.Name, query) || l.Name == "All Hosts") && !omitLookup[l.ID] {
|
2016-11-02 14:59:53 +00:00
|
|
|
results = append(results, *l)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-12-15 02:27:22 +00:00
|
|
|
sortutil.AscByField(results, "ID")
|
2016-11-02 14:59:53 +00:00
|
|
|
return results, nil
|
|
|
|
}
|
|
|
|
|
2016-12-16 00:12:43 +00:00
|
|
|
func (d *Datastore) ListHostsInLabel(lid uint) ([]kolide.Host, error) {
|
2016-11-02 14:59:53 +00:00
|
|
|
var hosts []kolide.Host
|
|
|
|
|
2016-12-16 00:12:43 +00:00
|
|
|
d.mtx.Lock()
|
|
|
|
defer d.mtx.Unlock()
|
2016-11-02 14:59:53 +00:00
|
|
|
|
2016-12-16 00:12:43 +00:00
|
|
|
for _, lqe := range d.labelQueryExecutions {
|
2016-11-02 14:59:53 +00:00
|
|
|
if lqe.LabelID == lid && lqe.Matches {
|
2016-12-16 00:12:43 +00:00
|
|
|
hosts = append(hosts, *d.hosts[lqe.HostID])
|
2016-11-02 14:59:53 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return hosts, nil
|
|
|
|
}
|
|
|
|
|
2016-12-16 00:12:43 +00:00
|
|
|
func (d *Datastore) ListUniqueHostsInLabels(labels []uint) ([]kolide.Host, error) {
|
2016-11-02 14:59:53 +00:00
|
|
|
var hosts []kolide.Host
|
|
|
|
|
|
|
|
labelSet := map[uint]bool{}
|
|
|
|
hostSet := map[uint]bool{}
|
|
|
|
|
|
|
|
for _, label := range labels {
|
|
|
|
labelSet[label] = true
|
|
|
|
}
|
|
|
|
|
2016-12-16 00:12:43 +00:00
|
|
|
d.mtx.Lock()
|
|
|
|
defer d.mtx.Unlock()
|
2016-11-02 14:59:53 +00:00
|
|
|
|
2016-12-16 00:12:43 +00:00
|
|
|
for _, lqe := range d.labelQueryExecutions {
|
2016-11-02 14:59:53 +00:00
|
|
|
if labelSet[lqe.LabelID] && lqe.Matches {
|
|
|
|
if !hostSet[lqe.HostID] {
|
2016-12-16 00:12:43 +00:00
|
|
|
hosts = append(hosts, *d.hosts[lqe.HostID])
|
2016-11-02 14:59:53 +00:00
|
|
|
hostSet[lqe.HostID] = true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return hosts, nil
|
|
|
|
}
|
2017-02-12 04:27:43 +00:00
|
|
|
|
|
|
|
func (d *Datastore) SaveLabel(label *kolide.Label) (*kolide.Label, error) {
|
|
|
|
panic("inmem is being deprecated")
|
|
|
|
}
|