Add online count to target/label responses (#513)

Closes #508
This commit is contained in:
Zachary Wasserman 2016-11-18 09:23:44 -08:00 committed by GitHub
parent 6133a61fd1
commit 3cd841051b
5 changed files with 79 additions and 39 deletions

View file

@ -15,7 +15,10 @@ type TargetService interface {
// (hosts and label) which match the supplied search query.
SearchTargets(ctx context.Context, query string, selectedHostIDs []uint, selectedLabelIDs []uint) (*TargetSearchResults, error)
CountHostsInTargets(ctx context.Context, hosts []uint, labels []uint) (uint, error)
// CountHostsInTargets returns the count of hosts in the selected
// targets. The first return uint is the total number of hosts in the
// targets. The second return uint is the total online hosts.
CountHostsInTargets(ctx context.Context, hostIDs []uint, labelIDs []uint) (uint, uint, error)
}
type TargetType int

View file

@ -18,6 +18,7 @@ type labelResponse struct {
kolide.Label
DisplayText string `json:"display_text"`
Count uint `json:"count"`
Online uint `json:"online"`
}
type getLabelResponse struct {
@ -34,7 +35,7 @@ func makeGetLabelEndpoint(svc kolide.Service) endpoint.Endpoint {
if err != nil {
return getLabelResponse{Err: err}, nil
}
count, err := svc.CountHostsInTargets(ctx, nil, []uint{label.ID})
total, online, err := svc.CountHostsInTargets(ctx, nil, []uint{label.ID})
if err != nil {
return getLabelResponse{Err: err}, nil
}
@ -42,7 +43,8 @@ func makeGetLabelEndpoint(svc kolide.Service) endpoint.Endpoint {
Label: labelResponse{
*label,
label.Name,
count,
total,
online,
},
}, nil
}
@ -73,7 +75,7 @@ func makeListLabelsEndpoint(svc kolide.Service) endpoint.Endpoint {
resp := listLabelsResponse{}
for _, label := range labels {
count, err := svc.CountHostsInTargets(ctx, nil, []uint{label.ID})
total, online, err := svc.CountHostsInTargets(ctx, nil, []uint{label.ID})
if err != nil {
return listLabelsResponse{Err: err}, nil
}
@ -81,7 +83,8 @@ func makeListLabelsEndpoint(svc kolide.Service) endpoint.Endpoint {
labelResponse{
*label,
label.Name,
count,
total,
online,
},
)
}
@ -111,7 +114,7 @@ func makeCreateLabelEndpoint(svc kolide.Service) endpoint.Endpoint {
if err != nil {
return createLabelResponse{Err: err}, nil
}
count, err := svc.CountHostsInTargets(ctx, nil, []uint{label.ID})
total, online, err := svc.CountHostsInTargets(ctx, nil, []uint{label.ID})
if err != nil {
return createLabelResponse{Err: err}, nil
}
@ -119,7 +122,8 @@ func makeCreateLabelEndpoint(svc kolide.Service) endpoint.Endpoint {
Label: labelResponse{
*label,
label.Name,
count,
total,
online,
},
}, nil
}

View file

@ -27,6 +27,7 @@ type labelSearchResult struct {
kolide.Label
DisplayText string `json:"display_text"`
Count uint `json:"count"`
Online uint `json:"online"`
}
type targetsData struct {
@ -35,9 +36,10 @@ type targetsData struct {
}
type searchTargetsResponse struct {
Targets *targetsData `json:"targets,omitempty"`
SelectedTargetsCount uint `json:"selected_targets_count,omitempty"`
Err error `json:"error,omitempty"`
Targets *targetsData `json:"targets,omitempty"`
SelectedTargetsCount uint `json:"selected_targets_count"`
SelectedTargetsOnline uint `json:"selected_targets_online"`
Err error `json:"error,omitempty"`
}
func (r searchTargetsResponse) error() error { return r.Err }
@ -51,11 +53,6 @@ func makeSearchTargetsEndpoint(svc kolide.Service) endpoint.Endpoint {
return searchTargetsResponse{Err: err}, nil
}
count, err := svc.CountHostsInTargets(ctx, req.Selected.Hosts, req.Selected.Labels)
if err != nil {
return searchTargetsResponse{Err: err}, nil
}
targets := &targetsData{
Hosts: []hostSearchResult{},
Labels: []labelSearchResult{},
@ -71,7 +68,7 @@ func makeSearchTargetsEndpoint(svc kolide.Service) endpoint.Endpoint {
}
for _, label := range results.Labels {
count, err := svc.CountHostsInTargets(ctx, nil, []uint{label.ID})
total, online, err := svc.CountHostsInTargets(ctx, nil, []uint{label.ID})
if err != nil {
return searchTargetsResponse{Err: err}, nil
}
@ -79,14 +76,21 @@ func makeSearchTargetsEndpoint(svc kolide.Service) endpoint.Endpoint {
labelSearchResult{
label,
label.Name,
count,
total,
online,
},
)
}
total, online, err := svc.CountHostsInTargets(ctx, req.Selected.Hosts, req.Selected.Labels)
if err != nil {
return searchTargetsResponse{Err: err}, nil
}
return searchTargetsResponse{
Targets: targets,
SelectedTargetsCount: count,
Targets: targets,
SelectedTargetsCount: total,
SelectedTargetsOnline: online,
}, nil
}
}

View file

@ -23,23 +23,30 @@ func (svc service) SearchTargets(ctx context.Context, query string, selectedHost
return results, nil
}
func (svc service) CountHostsInTargets(ctx context.Context, hosts []uint, labels []uint) (uint, error) {
hostsInLabels, err := svc.ds.ListUniqueHostsInLabels(labels)
func (svc service) CountHostsInTargets(ctx context.Context, hostIDs []uint, labelIDs []uint) (uint, uint, error) {
hosts, err := svc.ds.ListUniqueHostsInLabels(labelIDs)
if err != nil {
return 0, err
return 0, 0, err
}
for _, id := range hostIDs {
h, err := svc.ds.Host(id)
if err != nil {
return 0, 0, err
}
hosts = append(hosts, *h)
}
hostLookup := map[uint]bool{}
online := uint(0)
for _, host := range hosts {
hostLookup[host] = true
}
for _, host := range hostsInLabels {
if !hostLookup[host.ID] {
hostLookup[host.ID] = true
if svc.HostStatus(ctx, host) == "online" {
online++
}
}
}
return uint(len(hostLookup)), nil
return uint(len(hostLookup)), online, nil
}

View file

@ -5,6 +5,7 @@ import (
"testing"
"time"
"github.com/WatchBeam/clock"
"github.com/kolide/kolide-ose/server/datastore/inmem"
"github.com/kolide/kolide-ose/server/kolide"
"github.com/stretchr/testify/assert"
@ -47,7 +48,9 @@ func TestCountHostsInTargets(t *testing.T) {
ds, err := inmem.New()
require.Nil(t, err)
svc, err := newTestService(ds, nil)
mockClock := clock.NewMockClock()
svc, err := newTestServiceWithClock(ds, nil, mockClock)
require.Nil(t, err)
ctx := context.Background()
@ -59,6 +62,7 @@ func TestCountHostsInTargets(t *testing.T) {
UUID: "1",
})
require.Nil(t, err)
require.Nil(t, ds.MarkHostSeen(h1, mockClock.Now()))
h2, err := ds.NewHost(&kolide.Host{
HostName: "bar.local",
@ -67,6 +71,8 @@ func TestCountHostsInTargets(t *testing.T) {
UUID: "2",
})
require.Nil(t, err)
// make this host "offline"
require.Nil(t, ds.MarkHostSeen(h2, mockClock.Now().Add(-1*time.Hour)))
h3, err := ds.NewHost(&kolide.Host{
HostName: "baz.local",
@ -75,6 +81,7 @@ func TestCountHostsInTargets(t *testing.T) {
UUID: "3",
})
require.Nil(t, err)
require.Nil(t, ds.MarkHostSeen(h3, mockClock.Now().Add(-5*time.Minute)))
h4, err := ds.NewHost(&kolide.Host{
HostName: "xxx.local",
@ -83,6 +90,7 @@ func TestCountHostsInTargets(t *testing.T) {
UUID: "4",
})
require.Nil(t, err)
require.Nil(t, ds.MarkHostSeen(h4, mockClock.Now()))
h5, err := ds.NewHost(&kolide.Host{
HostName: "yyy.local",
@ -91,6 +99,7 @@ func TestCountHostsInTargets(t *testing.T) {
UUID: "5",
})
require.Nil(t, err)
require.Nil(t, ds.MarkHostSeen(h5, mockClock.Now()))
l1, err := ds.NewLabel(&kolide.Label{
Name: "label foo",
@ -118,25 +127,38 @@ func TestCountHostsInTargets(t *testing.T) {
assert.Nil(t, err)
}
count, err := svc.CountHostsInTargets(ctx, nil, []uint{l1.ID, l2.ID})
total, online, err := svc.CountHostsInTargets(ctx, nil, []uint{l1.ID, l2.ID})
assert.Nil(t, err)
assert.Equal(t, uint(5), count)
assert.Equal(t, uint(5), total)
assert.Equal(t, uint(4), online)
count, err = svc.CountHostsInTargets(ctx, []uint{h1.ID, h2.ID}, []uint{l1.ID, l2.ID})
total, online, err = svc.CountHostsInTargets(ctx, []uint{h1.ID, h2.ID}, []uint{l1.ID, l2.ID})
assert.Nil(t, err)
assert.Equal(t, uint(5), count)
assert.Equal(t, uint(5), total)
assert.Equal(t, uint(4), online)
count, err = svc.CountHostsInTargets(ctx, []uint{h1.ID, h2.ID}, nil)
total, online, err = svc.CountHostsInTargets(ctx, []uint{h1.ID, h2.ID}, nil)
assert.Nil(t, err)
assert.Equal(t, uint(2), count)
assert.Equal(t, uint(2), total)
assert.Equal(t, uint(1), online)
count, err = svc.CountHostsInTargets(ctx, []uint{h1.ID}, []uint{l2.ID})
total, online, err = svc.CountHostsInTargets(ctx, []uint{h1.ID}, []uint{l2.ID})
assert.Nil(t, err)
assert.Equal(t, uint(4), count)
assert.Equal(t, uint(4), total)
assert.Equal(t, uint(4), online)
count, err = svc.CountHostsInTargets(ctx, nil, nil)
total, online, err = svc.CountHostsInTargets(ctx, nil, nil)
assert.Nil(t, err)
assert.Equal(t, uint(0), count)
assert.Equal(t, uint(0), total)
assert.Equal(t, uint(0), online)
// Advance clock so all hosts are offline
mockClock.AddTime(1 * time.Hour)
total, online, err = svc.CountHostsInTargets(ctx, nil, []uint{l1.ID, l2.ID})
assert.Nil(t, err)
assert.Equal(t, uint(5), total)
assert.Equal(t, uint(0), online)
}
func TestSearchWithOmit(t *testing.T) {