Added hosts for each label (#963)

This commit is contained in:
John Murphy 2017-01-17 06:57:05 +08:00 committed by GitHub
parent da27a44493
commit a2fded1b2c
6 changed files with 66 additions and 52 deletions

View file

@ -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)
}

View file

@ -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
}

View file

@ -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
}

View file

@ -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 {

View file

@ -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
}
}

View file

@ -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
}