mirror of
https://github.com/fleetdm/fleet
synced 2026-05-24 01:18:42 +00:00
Added hosts for each label (#963)
This commit is contained in:
parent
da27a44493
commit
a2fded1b2c
6 changed files with 66 additions and 52 deletions
|
|
@ -176,6 +176,7 @@ func testManagingLabelsOnPacks(t *testing.T, ds kolide.Datastore) {
|
|||
labels, err = ds.ListLabelsForPack(monitoringPack.ID)
|
||||
require.Nil(t, err)
|
||||
assert.Len(t, labels, 2)
|
||||
|
||||
}
|
||||
|
||||
func testSearchLabels(t *testing.T, db kolide.Datastore) {
|
||||
|
|
@ -351,4 +352,9 @@ func testListUniqueHostsInLabels(t *testing.T, db kolide.Datastore) {
|
|||
uniqueHosts, err := db.ListUniqueHostsInLabels([]uint{l1.ID, l2.ID})
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, len(hosts), len(uniqueHosts))
|
||||
|
||||
labels, err := db.ListLabels(kolide.ListOptions{})
|
||||
require.Nil(t, err)
|
||||
require.Len(t, labels, 2)
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,10 +29,11 @@ func (d *Datastore) NewLabel(label *kolide.Label) (*kolide.Label, error) {
|
|||
}
|
||||
|
||||
func (d *Datastore) ListLabelsForHost(hid uint) ([]kolide.Label, error) {
|
||||
d.mtx.Lock()
|
||||
defer d.mtx.Unlock()
|
||||
// First get IDs of label executions for the host
|
||||
resLabels := []kolide.Label{}
|
||||
|
||||
d.mtx.Lock()
|
||||
for _, lqe := range d.labelQueryExecutions {
|
||||
if lqe.HostID == hid && lqe.Matches {
|
||||
if label := d.labels[lqe.LabelID]; label != nil {
|
||||
|
|
@ -40,16 +41,16 @@ func (d *Datastore) ListLabelsForHost(hid uint) ([]kolide.Label, error) {
|
|||
}
|
||||
}
|
||||
}
|
||||
d.mtx.Unlock()
|
||||
|
||||
return resLabels, nil
|
||||
}
|
||||
|
||||
func (d *Datastore) LabelQueriesForHost(host *kolide.Host, cutoff time.Time) (map[string]string, error) {
|
||||
d.mtx.Lock()
|
||||
defer d.mtx.Unlock()
|
||||
// Get post-cutoff executions for host
|
||||
execedIDs := map[uint]bool{}
|
||||
|
||||
d.mtx.Lock()
|
||||
for _, lqe := range d.labelQueryExecutions {
|
||||
if lqe.HostID == host.ID && (lqe.UpdatedAt == cutoff || lqe.UpdatedAt.After(cutoff)) {
|
||||
execedIDs[lqe.LabelID] = true
|
||||
|
|
@ -62,7 +63,6 @@ func (d *Datastore) LabelQueriesForHost(host *kolide.Host, cutoff time.Time) (ma
|
|||
queries[strconv.Itoa(int(label.ID))] = label.Query
|
||||
}
|
||||
}
|
||||
d.mtx.Unlock()
|
||||
|
||||
return queries, nil
|
||||
}
|
||||
|
|
@ -141,11 +141,12 @@ func (d *Datastore) Label(lid uint) (*kolide.Label, error) {
|
|||
}
|
||||
|
||||
func (d *Datastore) ListLabels(opt kolide.ListOptions) ([]*kolide.Label, error) {
|
||||
d.mtx.Lock()
|
||||
defer d.mtx.Unlock()
|
||||
// We need to sort by keys to provide reliable ordering
|
||||
keys := []int{}
|
||||
|
||||
d.mtx.Lock()
|
||||
for k, _ := range d.labels {
|
||||
for k := range d.labels {
|
||||
keys = append(keys, int(k))
|
||||
}
|
||||
sort.Ints(keys)
|
||||
|
|
@ -154,7 +155,6 @@ func (d *Datastore) ListLabels(opt kolide.ListOptions) ([]*kolide.Label, error)
|
|||
for _, k := range keys {
|
||||
labels = append(labels, d.labels[uint(k)])
|
||||
}
|
||||
d.mtx.Unlock()
|
||||
|
||||
// Apply ordering
|
||||
if opt.OrderKey != "" {
|
||||
|
|
@ -199,7 +199,6 @@ func (d *Datastore) SearchLabels(query string, omit ...uint) ([]kolide.Label, er
|
|||
}
|
||||
|
||||
sortutil.AscByField(results, "ID")
|
||||
|
||||
return results, nil
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -54,13 +54,17 @@ func (d *Datastore) Label(lid uint) (*kolide.Label, error) {
|
|||
|
||||
// ListLabels returns all labels limited or sorted by kolide.ListOptions
|
||||
func (d *Datastore) ListLabels(opt kolide.ListOptions) ([]*kolide.Label, error) {
|
||||
sql := `
|
||||
query := `
|
||||
SELECT * FROM labels WHERE NOT deleted
|
||||
`
|
||||
sql = appendListOptionsToSQL(sql, opt)
|
||||
query = appendListOptionsToSQL(query, opt)
|
||||
labels := []*kolide.Label{}
|
||||
|
||||
if err := d.db.Select(&labels, sql); err != nil {
|
||||
if err := d.db.Select(&labels, query); err != nil {
|
||||
// it's ok if no labels exist
|
||||
if err == sql.ErrNoRows {
|
||||
return labels, nil
|
||||
}
|
||||
return nil, errors.Wrap(err, "selecting labels")
|
||||
}
|
||||
|
||||
|
|
@ -150,6 +154,7 @@ func (d *Datastore) ListLabelsForHost(hid uint) ([]kolide.Label, error) {
|
|||
if err != nil {
|
||||
return nil, errors.Wrap(err, "selecting host labels")
|
||||
}
|
||||
|
||||
return labels, nil
|
||||
|
||||
}
|
||||
|
|
@ -274,6 +279,5 @@ func (d *Datastore) SearchLabels(query string, omit ...uint) ([]kolide.Label, er
|
|||
if err != nil {
|
||||
return nil, errors.Wrap(err, "selecting labels for search")
|
||||
}
|
||||
|
||||
return matches, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,6 +40,9 @@ type LabelService interface {
|
|||
GetLabel(ctx context.Context, id uint) (label *Label, err error)
|
||||
NewLabel(ctx context.Context, p LabelPayload) (label *Label, err error)
|
||||
DeleteLabel(ctx context.Context, id uint) (err error)
|
||||
// HostIDsForLabel returns ids of hosts that belong to the label identified
|
||||
// by lid
|
||||
HostIDsForLabel(lid uint) ([]uint, error)
|
||||
}
|
||||
|
||||
type LabelPayload struct {
|
||||
|
|
|
|||
|
|
@ -6,10 +6,6 @@ import (
|
|||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Get Label
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
type getLabelRequest struct {
|
||||
ID uint
|
||||
}
|
||||
|
|
@ -21,6 +17,7 @@ type labelResponse struct {
|
|||
Online uint `json:"online"`
|
||||
Offline uint `json:"offline"`
|
||||
MissingInAction uint `json:"missing_in_action"`
|
||||
HostIDs []uint `json:"host_ids,omitempty"`
|
||||
}
|
||||
|
||||
type getLabelResponse struct {
|
||||
|
|
@ -30,6 +27,29 @@ type getLabelResponse struct {
|
|||
|
||||
func (r getLabelResponse) error() error { return r.Err }
|
||||
|
||||
func labelResponseForLabel(ctx context.Context, svc kolide.Service, label *kolide.Label) (*labelResponse, error) {
|
||||
metrics, err := svc.CountHostsInTargets(ctx, nil, []uint{label.ID})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
hosts, err := svc.HostIDsForLabel(label.ID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &labelResponse{
|
||||
*label,
|
||||
label.Name,
|
||||
metrics.TotalHosts,
|
||||
metrics.OnlineHosts,
|
||||
metrics.OfflineHosts,
|
||||
metrics.MissingInActionHosts,
|
||||
hosts,
|
||||
}, nil
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Get Label
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
func makeGetLabelEndpoint(svc kolide.Service) endpoint.Endpoint {
|
||||
return func(ctx context.Context, request interface{}) (interface{}, error) {
|
||||
req := request.(getLabelRequest)
|
||||
|
|
@ -37,20 +57,11 @@ func makeGetLabelEndpoint(svc kolide.Service) endpoint.Endpoint {
|
|||
if err != nil {
|
||||
return getLabelResponse{Err: err}, nil
|
||||
}
|
||||
metrics, err := svc.CountHostsInTargets(ctx, nil, []uint{label.ID})
|
||||
resp, err := labelResponseForLabel(ctx, svc, label)
|
||||
if err != nil {
|
||||
return getLabelResponse{Err: err}, nil
|
||||
}
|
||||
return getLabelResponse{
|
||||
Label: labelResponse{
|
||||
*label,
|
||||
label.Name,
|
||||
metrics.TotalHosts,
|
||||
metrics.OnlineHosts,
|
||||
metrics.OfflineHosts,
|
||||
metrics.MissingInActionHosts,
|
||||
},
|
||||
}, nil
|
||||
return getLabelResponse{Label: *resp}, nil
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -79,20 +90,11 @@ func makeListLabelsEndpoint(svc kolide.Service) endpoint.Endpoint {
|
|||
|
||||
resp := listLabelsResponse{}
|
||||
for _, label := range labels {
|
||||
metrics, err := svc.CountHostsInTargets(ctx, nil, []uint{label.ID})
|
||||
labelResp, err := labelResponseForLabel(ctx, svc, label)
|
||||
if err != nil {
|
||||
return listLabelsResponse{Err: err}, nil
|
||||
}
|
||||
resp.Labels = append(resp.Labels,
|
||||
labelResponse{
|
||||
*label,
|
||||
label.Name,
|
||||
metrics.TotalHosts,
|
||||
metrics.OnlineHosts,
|
||||
metrics.OfflineHosts,
|
||||
metrics.MissingInActionHosts,
|
||||
},
|
||||
)
|
||||
resp.Labels = append(resp.Labels, *labelResp)
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
|
|
@ -117,23 +119,11 @@ func makeCreateLabelEndpoint(svc kolide.Service) endpoint.Endpoint {
|
|||
return func(ctx context.Context, request interface{}) (interface{}, error) {
|
||||
req := request.(createLabelRequest)
|
||||
label, err := svc.NewLabel(ctx, req.payload)
|
||||
labelResp, err := labelResponseForLabel(ctx, svc, label)
|
||||
if err != nil {
|
||||
return createLabelResponse{Err: err}, nil
|
||||
}
|
||||
metrics, err := svc.CountHostsInTargets(ctx, nil, []uint{label.ID})
|
||||
if err != nil {
|
||||
return createLabelResponse{Err: err}, nil
|
||||
}
|
||||
return createLabelResponse{
|
||||
Label: labelResponse{
|
||||
*label,
|
||||
label.Name,
|
||||
metrics.TotalHosts,
|
||||
metrics.OnlineHosts,
|
||||
metrics.OfflineHosts,
|
||||
metrics.MissingInActionHosts,
|
||||
},
|
||||
}, nil
|
||||
return createLabelResponse{Label: *labelResp}, nil
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -44,3 +44,15 @@ func (svc service) NewLabel(ctx context.Context, p kolide.LabelPayload) (*kolide
|
|||
func (svc service) DeleteLabel(ctx context.Context, id uint) error {
|
||||
return svc.ds.DeleteLabel(id)
|
||||
}
|
||||
|
||||
func (svc service) HostIDsForLabel(lid uint) ([]uint, error) {
|
||||
hosts, err := svc.ds.ListHostsInLabel(lid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var ids []uint
|
||||
for _, h := range hosts {
|
||||
ids = append(ids, h.ID)
|
||||
}
|
||||
return ids, nil
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue