2017-03-30 15:31:28 +00:00
|
|
|
package mysql
|
|
|
|
|
|
|
|
import (
|
2021-09-14 12:11:07 +00:00
|
|
|
"context"
|
2017-04-18 17:39:50 +00:00
|
|
|
"fmt"
|
2017-03-30 15:31:28 +00:00
|
|
|
"time"
|
|
|
|
|
2021-11-15 14:11:38 +00:00
|
|
|
"github.com/fleetdm/fleet/v4/server/contexts/ctxerr"
|
2021-06-26 04:46:51 +00:00
|
|
|
"github.com/fleetdm/fleet/v4/server/fleet"
|
2021-05-17 17:29:50 +00:00
|
|
|
"github.com/jmoiron/sqlx"
|
2017-03-30 15:31:28 +00:00
|
|
|
)
|
|
|
|
|
2022-02-03 17:56:22 +00:00
|
|
|
func (ds *Datastore) CountHostsInTargets(ctx context.Context, filter fleet.TeamFilter, targets fleet.HostTargets, now time.Time) (fleet.TargetMetrics, error) {
|
2017-04-18 17:39:50 +00:00
|
|
|
// The logic in this function should remain synchronized with
|
2021-11-15 14:55:27 +00:00
|
|
|
// host.Status and GenerateHostStatusStatistics - that is, the intervals associated
|
|
|
|
// with each status must be the same.
|
2017-04-18 17:39:50 +00:00
|
|
|
|
2021-05-27 20:18:00 +00:00
|
|
|
if len(targets.HostIDs) == 0 && len(targets.LabelIDs) == 0 && len(targets.TeamIDs) == 0 {
|
2017-03-30 15:31:28 +00:00
|
|
|
// No need to query if no targets selected
|
2021-06-06 22:07:29 +00:00
|
|
|
return fleet.TargetMetrics{}, nil
|
2017-03-30 15:31:28 +00:00
|
|
|
}
|
|
|
|
|
2017-04-18 17:39:50 +00:00
|
|
|
sql := fmt.Sprintf(`
|
2017-03-30 15:31:28 +00:00
|
|
|
SELECT
|
|
|
|
COUNT(*) total,
|
2021-12-01 12:05:23 +00:00
|
|
|
COALESCE(SUM(CASE WHEN DATE_ADD(COALESCE(hst.seen_time, h.created_at), INTERVAL 30 DAY) <= ? THEN 1 ELSE 0 END), 0) mia,
|
|
|
|
COALESCE(SUM(CASE WHEN DATE_ADD(COALESCE(hst.seen_time, h.created_at), INTERVAL LEAST(distributed_interval, config_tls_refresh) + %d SECOND) <= ? AND DATE_ADD(COALESCE(hst.seen_time, h.created_at), INTERVAL 30 DAY) >= ? THEN 1 ELSE 0 END), 0) offline,
|
|
|
|
COALESCE(SUM(CASE WHEN DATE_ADD(COALESCE(hst.seen_time, h.created_at), INTERVAL LEAST(distributed_interval, config_tls_refresh) + %d SECOND) > ? THEN 1 ELSE 0 END), 0) online,
|
2017-03-30 15:31:28 +00:00
|
|
|
COALESCE(SUM(CASE WHEN DATE_ADD(created_at, INTERVAL 1 DAY) >= ? THEN 1 ELSE 0 END), 0) new
|
|
|
|
FROM hosts h
|
2021-12-01 12:05:23 +00:00
|
|
|
LEFT JOIN host_seen_times hst ON (h.id=hst.host_id)
|
2021-05-27 20:18:00 +00:00
|
|
|
WHERE (id IN (?) OR (id IN (SELECT DISTINCT host_id FROM label_membership WHERE label_id IN (?))) OR team_id IN (?)) AND %s
|
2022-02-03 17:56:22 +00:00
|
|
|
`, fleet.OnlineIntervalBuffer, fleet.OnlineIntervalBuffer, ds.whereFilterHostsByTeams(filter, "h"))
|
2017-03-30 15:31:28 +00:00
|
|
|
|
|
|
|
// Using -1 in the ID slices for the IN clause allows us to include the
|
|
|
|
// IN clause even if we have no IDs to use. -1 will not match the
|
|
|
|
// auto-increment IDs, and will also allow us to use the same query in
|
|
|
|
// all situations (no need to remove the clause when there are no values)
|
|
|
|
queryLabelIDs := []int{-1}
|
2021-05-27 20:18:00 +00:00
|
|
|
for _, id := range targets.LabelIDs {
|
2017-03-30 15:31:28 +00:00
|
|
|
queryLabelIDs = append(queryLabelIDs, int(id))
|
|
|
|
}
|
|
|
|
queryHostIDs := []int{-1}
|
2021-05-27 20:18:00 +00:00
|
|
|
for _, id := range targets.HostIDs {
|
2017-03-30 15:31:28 +00:00
|
|
|
queryHostIDs = append(queryHostIDs, int(id))
|
|
|
|
}
|
2021-05-27 20:18:00 +00:00
|
|
|
queryTeamIDs := []int{-1}
|
|
|
|
for _, id := range targets.TeamIDs {
|
|
|
|
queryTeamIDs = append(queryTeamIDs, int(id))
|
|
|
|
}
|
2017-03-30 15:31:28 +00:00
|
|
|
|
2021-05-27 20:18:00 +00:00
|
|
|
query, args, err := sqlx.In(sql, now, now, now, now, now, queryHostIDs, queryLabelIDs, queryTeamIDs)
|
2017-03-30 15:31:28 +00:00
|
|
|
if err != nil {
|
2021-11-15 14:11:38 +00:00
|
|
|
return fleet.TargetMetrics{}, ctxerr.Wrap(ctx, err, "sqlx.In CountHostsInTargets")
|
2017-03-30 15:31:28 +00:00
|
|
|
}
|
|
|
|
|
2021-06-06 22:07:29 +00:00
|
|
|
res := fleet.TargetMetrics{}
|
2022-02-03 17:56:22 +00:00
|
|
|
err = sqlx.GetContext(ctx, ds.reader, &res, query, args...)
|
2017-03-30 15:31:28 +00:00
|
|
|
if err != nil {
|
2021-11-15 14:11:38 +00:00
|
|
|
return fleet.TargetMetrics{}, ctxerr.Wrap(ctx, err, "sqlx.Get CountHostsInTargets")
|
2017-03-30 15:31:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return res, nil
|
|
|
|
}
|
2020-03-23 01:33:04 +00:00
|
|
|
|
2022-02-03 17:56:22 +00:00
|
|
|
func (ds *Datastore) HostIDsInTargets(ctx context.Context, filter fleet.TeamFilter, targets fleet.HostTargets) ([]uint, error) {
|
2021-05-27 20:18:00 +00:00
|
|
|
if len(targets.HostIDs) == 0 && len(targets.LabelIDs) == 0 && len(targets.TeamIDs) == 0 {
|
2020-03-23 01:33:04 +00:00
|
|
|
// No need to query if no targets selected
|
|
|
|
return []uint{}, nil
|
|
|
|
}
|
|
|
|
|
2021-05-25 04:34:08 +00:00
|
|
|
sql := fmt.Sprintf(`
|
|
|
|
SELECT DISTINCT id
|
|
|
|
FROM hosts
|
2021-05-27 20:18:00 +00:00
|
|
|
WHERE (id IN (?) OR (id IN (SELECT host_id FROM label_membership WHERE label_id IN (?))) OR team_id IN (?)) AND %s
|
2021-05-25 04:34:08 +00:00
|
|
|
ORDER BY id ASC
|
|
|
|
`,
|
2022-02-03 17:56:22 +00:00
|
|
|
ds.whereFilterHostsByTeams(filter, "hosts"),
|
2021-05-25 04:34:08 +00:00
|
|
|
)
|
2020-03-23 01:33:04 +00:00
|
|
|
|
|
|
|
// Using -1 in the ID slices for the IN clause allows us to include the
|
|
|
|
// IN clause even if we have no IDs to use. -1 will not match the
|
|
|
|
// auto-increment IDs, and will also allow us to use the same query in
|
|
|
|
// all situations (no need to remove the clause when there are no values)
|
|
|
|
queryLabelIDs := []int{-1}
|
2021-05-27 20:18:00 +00:00
|
|
|
for _, id := range targets.LabelIDs {
|
2020-03-23 01:33:04 +00:00
|
|
|
queryLabelIDs = append(queryLabelIDs, int(id))
|
|
|
|
}
|
|
|
|
queryHostIDs := []int{-1}
|
2021-05-27 20:18:00 +00:00
|
|
|
for _, id := range targets.HostIDs {
|
2020-03-23 01:33:04 +00:00
|
|
|
queryHostIDs = append(queryHostIDs, int(id))
|
|
|
|
}
|
2021-05-27 20:18:00 +00:00
|
|
|
queryTeamIDs := []int{-1}
|
|
|
|
for _, id := range targets.TeamIDs {
|
|
|
|
queryTeamIDs = append(queryTeamIDs, int(id))
|
|
|
|
}
|
2020-03-23 01:33:04 +00:00
|
|
|
|
2021-05-27 20:18:00 +00:00
|
|
|
query, args, err := sqlx.In(sql, queryHostIDs, queryLabelIDs, queryTeamIDs)
|
2020-03-23 01:33:04 +00:00
|
|
|
if err != nil {
|
2021-11-15 14:11:38 +00:00
|
|
|
return nil, ctxerr.Wrap(ctx, err, "sqlx.In HostIDsInTargets")
|
2020-03-23 01:33:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
var res []uint
|
2022-02-03 17:56:22 +00:00
|
|
|
err = sqlx.SelectContext(ctx, ds.reader, &res, query, args...)
|
2020-03-23 01:33:04 +00:00
|
|
|
if err != nil {
|
2021-11-15 14:11:38 +00:00
|
|
|
return nil, ctxerr.Wrap(ctx, err, "sqlx.Get HostIDsInTargets")
|
2020-03-23 01:33:04 +00:00
|
|
|
}
|
|
|
|
return res, nil
|
|
|
|
}
|