Fix host status regression from #1334 (#1383)

This commit is contained in:
Mike Arpaia 2017-03-09 11:36:24 -07:00 committed by GitHub
parent b23ab83336
commit f510691ad0
12 changed files with 48 additions and 29 deletions

View file

@ -591,7 +591,7 @@ func testGenerateHostStatusStatistics(t *testing.T, ds kolide.Datastore) {
// With an online interval of 60, both the host that checked in a minute ago
// as well as the host that checked in 30 seconds ago should both be online
online, offline, mia, new, err = ds.GenerateHostStatusStatistics(mockClock.Now(), 60)
online, offline, mia, new, err = ds.GenerateHostStatusStatistics(mockClock.Now(), 2*time.Minute)
assert.Nil(t, err)
assert.Equal(t, uint(2), online)
assert.Equal(t, uint(1), offline)
@ -599,7 +599,7 @@ func testGenerateHostStatusStatistics(t *testing.T, ds kolide.Datastore) {
assert.Equal(t, uint(4), new)
// With an online interval of 10, no hosts should be online
online, offline, mia, new, err = ds.GenerateHostStatusStatistics(mockClock.Now(), 10)
online, offline, mia, new, err = ds.GenerateHostStatusStatistics(mockClock.Now(), 20*time.Second)
assert.Nil(t, err)
assert.Equal(t, uint(0), online)
assert.Equal(t, uint(3), offline)
@ -609,7 +609,7 @@ func testGenerateHostStatusStatistics(t *testing.T, ds kolide.Datastore) {
// With an online interval of 3600 seconds (60 minutes), the host that checked
// in 30 seconds ago, a minute ago, and 60 minutes ago should all appear to be
// online
online, offline, mia, new, err = ds.GenerateHostStatusStatistics(mockClock.Now(), 60*60)
online, offline, mia, new, err = ds.GenerateHostStatusStatistics(mockClock.Now(), 2*time.Hour)
assert.Nil(t, err)
assert.Equal(t, uint(3), online)
assert.Equal(t, uint(0), offline)

View file

@ -113,7 +113,7 @@ func (d *Datastore) ListHosts(opt kolide.ListOptions) ([]*kolide.Host, error) {
return hosts, nil
}
func (d *Datastore) GenerateHostStatusStatistics(now time.Time, onlineInterval uint) (online, offline, mia, new uint, err error) {
func (d *Datastore) GenerateHostStatusStatistics(now time.Time, onlineInterval time.Duration) (online, offline, mia, new uint, err error) {
d.mtx.Lock()
defer d.mtx.Unlock()
@ -122,7 +122,7 @@ func (d *Datastore) GenerateHostStatusStatistics(now time.Time, onlineInterval u
new++
}
status := host.Status(now)
status := host.Status(now, onlineInterval)
switch status {
case kolide.StatusMIA:
mia++

View file

@ -290,7 +290,7 @@ func (d *Datastore) ListHosts(opt kolide.ListOptions) ([]*kolide.Host, error) {
return hosts, nil
}
func (d *Datastore) GenerateHostStatusStatistics(now time.Time, onlineInterval uint) (online, offline, mia, new uint, e error) {
func (d *Datastore) GenerateHostStatusStatistics(now time.Time, onlineInterval time.Duration) (online, offline, mia, new uint, e error) {
sqlStatement := `
SELECT (
SELECT count(id)
@ -323,7 +323,7 @@ func (d *Datastore) GenerateHostStatusStatistics(now time.Time, onlineInterval u
Online uint `db:"online"`
New uint `db:"new"`
}{}
err := d.db.Get(&counts, sqlStatement, now, 2*onlineInterval, now, now, 2*onlineInterval, now, now)
err := d.db.Get(&counts, sqlStatement, now, onlineInterval.Seconds(), now, now, onlineInterval.Seconds(), now, now)
if err != nil && err != sql.ErrNoRows {
e = errors.Wrap(err, "generating host statistics")
return

View file

@ -22,10 +22,6 @@ const (
// considered new.
NewDuration = 24 * time.Hour
// OfflineDuration if a host hasn't been in communition for this
// period it is considered offline.
OfflineDuration = 30 * time.Minute
// OfflineDuration if a host hasn't been in communition for this
// period it is considered MIA.
MIADuration = 30 * 24 * time.Hour
@ -40,7 +36,7 @@ type HostStore interface {
EnrollHost(osqueryHostId string, nodeKeySize int) (*Host, error)
AuthenticateHost(nodeKey string) (*Host, error)
MarkHostSeen(host *Host, t time.Time) error
GenerateHostStatusStatistics(now time.Time, onlineInterval uint) (online, offline, mia, new uint, err error)
GenerateHostStatusStatistics(now time.Time, onlineInterval time.Duration) (online, offline, mia, new uint, err error)
SearchHosts(query string, omit ...uint) ([]*Host, error)
// DistributedQueriesForHost retrieves the distributed queries that the
// given host should run. The result map is a mapping from campaign ID
@ -147,11 +143,11 @@ func RandomText(keySize int) (string, error) {
return base64.StdEncoding.EncodeToString(key), nil
}
func (h *Host) Status(now time.Time) string {
func (h *Host) Status(now time.Time, onlineInterval time.Duration) string {
switch {
case h.SeenTime.Add(MIADuration).Before(now):
return StatusMIA
case h.SeenTime.Add(OfflineDuration).Before(now):
case h.SeenTime.Add(onlineInterval).Before(now):
return StatusOffline
default:
return StatusOnline

View file

@ -50,16 +50,16 @@ func TestHostStatus(t *testing.T) {
host := Host{}
host.SeenTime = mockClock.Now()
assert.Equal(t, StatusOnline, host.Status(mockClock.Now()))
assert.Equal(t, StatusOnline, host.Status(mockClock.Now(), 60*time.Second))
host.SeenTime = mockClock.Now().Add(-1 * time.Minute)
assert.Equal(t, StatusOnline, host.Status(mockClock.Now()))
assert.Equal(t, StatusOnline, host.Status(mockClock.Now(), 60*time.Second))
host.SeenTime = mockClock.Now().Add(-1 * time.Hour)
assert.Equal(t, StatusOffline, host.Status(mockClock.Now()))
assert.Equal(t, StatusOffline, host.Status(mockClock.Now(), 60*time.Second))
host.SeenTime = mockClock.Now().Add(-35 * (24 * time.Hour)) // 35 days
assert.Equal(t, StatusMIA, host.Status(mockClock.Now()))
assert.Equal(t, StatusMIA, host.Status(mockClock.Now(), 60*time.Second))
}
func TestHostIsNew(t *testing.T) {

View file

@ -5,6 +5,7 @@ import (
"encoding/json"
"fmt"
"strings"
"time"
"golang.org/x/net/context"
)
@ -40,7 +41,7 @@ type OptionService interface {
// can deduce a minimum amount of time that we should expect to hear from an
// osqueryd agent if it is online. This is currently two times the most
// frequent check-in interval.
ExpectedCheckinInterval(ctx context.Context) (uint, error)
ExpectedCheckinInterval(ctx context.Context) (time.Duration, error)
}
const (

View file

@ -5,6 +5,7 @@ import (
"github.com/go-kit/kit/endpoint"
"github.com/kolide/kolide/server/kolide"
"github.com/pkg/errors"
"golang.org/x/net/context"
)
@ -15,9 +16,13 @@ type hostResponse struct {
}
func hostResponseForHost(ctx context.Context, svc kolide.Service, host *kolide.Host) (*hostResponse, error) {
onlineInterval, err := svc.ExpectedCheckinInterval(ctx)
if err != nil {
return nil, errors.Wrap(err, "getting expected check-in interval")
}
return &hostResponse{
Host: *host,
Status: host.Status(time.Now()),
Status: host.Status(time.Now(), onlineInterval),
DisplayText: host.HostName,
}, nil
}

View file

@ -5,6 +5,7 @@ import (
"github.com/go-kit/kit/endpoint"
"github.com/kolide/kolide/server/kolide"
"github.com/pkg/errors"
"golang.org/x/net/context"
)
@ -64,12 +65,17 @@ func makeSearchTargetsEndpoint(svc kolide.Service) endpoint.Endpoint {
Labels: []labelSearchResult{},
}
onlineInterval, err := svc.ExpectedCheckinInterval(ctx)
if err != nil {
return searchTargetsResponse{Err: errors.Wrap(err, "getting expected check-in interval")}, nil
}
for _, host := range results.Hosts {
targets.Hosts = append(targets.Hosts,
hostSearchResult{
hostResponse{
Host: host,
Status: host.Status(time.Now()),
Status: host.Status(time.Now(), onlineInterval),
},
host.HostName,
},

View file

@ -1,11 +1,15 @@
package service
import (
"time"
"github.com/kolide/kolide/server/kolide"
"github.com/pkg/errors"
"golang.org/x/net/context"
)
const expectedCheckinIntervalMultiplier = 2
func (svc service) GetOptions(ctx context.Context) ([]kolide.Option, error) {
opts, err := svc.ds.ListOptions()
if err != nil {
@ -21,7 +25,7 @@ func (svc service) ModifyOptions(ctx context.Context, req kolide.OptionRequest)
return req.Options, nil
}
func (svc service) ExpectedCheckinInterval(ctx context.Context) (uint, error) {
func (svc service) ExpectedCheckinInterval(ctx context.Context) (time.Duration, error) {
interval := uint(0)
found := false
@ -71,9 +75,9 @@ func (svc service) ExpectedCheckinInterval(ctx context.Context) (uint, error) {
// if we never found any interval options set, the default distributed
// interval is 60, so we use that
if !found {
return 60, nil
interval = 60
}
// return the lowest interval that we found
return interval, nil
return time.Duration(interval) * time.Second * expectedCheckinIntervalMultiplier, nil
}

View file

@ -3,6 +3,7 @@ package service
import (
"context"
"testing"
"time"
"github.com/kolide/kolide/server/config"
"github.com/kolide/kolide/server/datastore/inmem"
@ -44,7 +45,7 @@ func TestExpectedCheckinInterval(t *testing.T) {
require.Equal(t, 10, int(loggerTlsPeriod))
interval, err := svc.ExpectedCheckinInterval(ctx)
require.Nil(t, err)
assert.Equal(t, 10, int(interval))
assert.Equal(t, 10*time.Second*expectedCheckinIntervalMultiplier, interval)
options, err = svc.ModifyOptions(ctx, kolide.OptionRequest{
Options: []kolide.Option{
@ -69,7 +70,7 @@ func TestExpectedCheckinInterval(t *testing.T) {
require.Equal(t, 10, int(loggerTlsPeriod))
interval, err = svc.ExpectedCheckinInterval(ctx)
require.Nil(t, err)
assert.Equal(t, 5, int(interval))
assert.Equal(t, 5*time.Second*expectedCheckinIntervalMultiplier, interval)
options, err = svc.ModifyOptions(ctx, kolide.OptionRequest{
Options: []kolide.Option{
@ -94,5 +95,5 @@ func TestExpectedCheckinInterval(t *testing.T) {
require.Equal(t, 1, int(loggerTlsPeriod))
interval, err = svc.ExpectedCheckinInterval(ctx)
require.Nil(t, err)
assert.Equal(t, 1, int(interval))
assert.Equal(t, time.Second*expectedCheckinIntervalMultiplier, interval)
}

View file

@ -2,6 +2,7 @@ package service
import (
"github.com/kolide/kolide/server/kolide"
"github.com/pkg/errors"
"golang.org/x/net/context"
)
@ -44,10 +45,15 @@ func (svc service) CountHostsInTargets(ctx context.Context, hostIDs []uint, labe
result := &kolide.TargetMetrics{}
onlineInterval, err := svc.ExpectedCheckinInterval(ctx)
if err != nil {
return nil, errors.Wrap(err, "getting expected check-in interval")
}
for _, host := range hosts {
if !hostLookup[host.ID] {
hostLookup[host.ID] = true
switch host.Status(svc.clock.Now().UTC()) {
switch host.Status(svc.clock.Now().UTC(), onlineInterval) {
case kolide.StatusOnline:
result.OnlineHosts++
case kolide.StatusOffline:

View file

@ -78,7 +78,7 @@ func TestCountHostsInTargets(t *testing.T) {
UUID: "3",
})
require.Nil(t, err)
require.Nil(t, ds.MarkHostSeen(h3, mockClock.Now().Add(-5*time.Minute)))
require.Nil(t, ds.MarkHostSeen(h3, mockClock.Now().Add(-5*time.Second)))
h4, err := ds.NewHost(&kolide.Host{
HostName: "xxx.local",