Add support for filtering hosts in label (#335)

Support the same query syntax as the hosts endpoint, here also bounded
by the membership of the label.
This commit is contained in:
Zach Wasserman 2021-02-18 12:52:43 -08:00 committed by GitHub
parent 1c71d397a4
commit c6c5e65a7d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 61 additions and 42 deletions

View file

@ -330,7 +330,7 @@ func testListHostsInLabel(t *testing.T, db kolide.Datastore) {
{
hosts, err := db.ListHostsInLabel(l1.ID, kolide.ListOptions{})
hosts, err := db.ListHostsInLabel(l1.ID, kolide.HostListOptions{})
require.Nil(t, err)
assert.Len(t, hosts, 0)
}
@ -341,7 +341,7 @@ func testListHostsInLabel(t *testing.T, db kolide.Datastore) {
}
{
hosts, err := db.ListHostsInLabel(l1.ID, kolide.ListOptions{})
hosts, err := db.ListHostsInLabel(l1.ID, kolide.HostListOptions{})
require.Nil(t, err)
assert.Len(t, hosts, 3)
}

View file

@ -177,7 +177,7 @@ func (d *Datastore) SearchLabels(query string, omit ...uint) ([]kolide.Label, er
return results, nil
}
func (d *Datastore) ListHostsInLabel(lid uint, opt kolide.ListOptions) ([]kolide.Host, error) {
func (d *Datastore) ListHostsInLabel(lid uint, opt kolide.HostListOptions) ([]kolide.Host, error) {
var hosts []kolide.Host
d.mtx.Lock()

View file

@ -11,6 +11,8 @@ import (
"github.com/pkg/errors"
)
var hostSearchColumns = []string{"host_name", "uuid", "hardware_serial", "primary_ip"}
func (d *Datastore) NewHost(host *kolide.Host) (*kolide.Host, error) {
sqlStatement := `
INSERT INTO hosts (
@ -228,7 +230,7 @@ WHERE TRUE
params = append(params, time.Now())
}
sql, params = searchLike(sql, params, opt.MatchQuery, "host_name", "uuid", "hardware_serial", "primary_ip")
sql, params = searchLike(sql, params, opt.MatchQuery, hostSearchColumns...)
sql = appendListOptionsToSQL(sql, opt.ListOptions)

View file

@ -5,8 +5,8 @@ import (
"strings"
"time"
"github.com/jmoiron/sqlx"
"github.com/fleetdm/fleet/server/kolide"
"github.com/jmoiron/sqlx"
"github.com/pkg/errors"
)
@ -388,7 +388,7 @@ func (d *Datastore) ListLabelsForHost(hid uint) ([]kolide.Label, error) {
// ListHostsInLabel returns a list of kolide.Host that are associated
// with kolide.Label referened by Label ID
func (d *Datastore) ListHostsInLabel(lid uint, opt kolide.ListOptions) ([]kolide.Host, error) {
func (d *Datastore) ListHostsInLabel(lid uint, opt kolide.HostListOptions) ([]kolide.Host, error) {
sql := `
SELECT h.*
FROM label_membership lm
@ -396,9 +396,13 @@ func (d *Datastore) ListHostsInLabel(lid uint, opt kolide.ListOptions) ([]kolide
ON lm.host_id = h.id
WHERE lm.label_id = ?
`
sql = appendListOptionsToSQL(sql, opt)
params := []interface{}{lid}
sql, params = searchLike(sql, params, opt.MatchQuery, hostSearchColumns...)
sql = appendListOptionsToSQL(sql, opt.ListOptions)
hosts := []kolide.Host{}
err := d.db.Select(&hosts, sql, lid)
err := d.db.Select(&hosts, sql, params...)
if err != nil {
return nil, errors.Wrap(err, "selecting label query executions")
}

View file

@ -41,7 +41,7 @@ type LabelStore interface {
// ListHostsInLabel returns a slice of hosts in the label with the
// given ID.
ListHostsInLabel(lid uint, opt ListOptions) ([]Host, error)
ListHostsInLabel(lid uint, opt HostListOptions) ([]Host, error)
// ListUniqueHostsInLabels returns a slice of all of the hosts in the
// given label IDs. A host will only appear once in the results even if
@ -74,7 +74,7 @@ type LabelService interface {
// ListHostsInLabel returns a slice of hosts in the label with the
// given ID.
ListHostsInLabel(ctx context.Context, lid uint, opt ListOptions) ([]Host, error)
ListHostsInLabel(ctx context.Context, lid uint, opt HostListOptions) ([]Host, error)
// LabelsForHost returns the labels that the given host is in.
ListLabelsForHost(ctx context.Context, hid uint) ([]Label, error)

View file

@ -32,7 +32,7 @@ type RecordLabelQueryExecutionsFunc func(host *kolide.Host, results map[uint]boo
type ListLabelsForHostFunc func(hid uint) ([]kolide.Label, error)
type ListHostsInLabelFunc func(lid uint, opt kolide.ListOptions) ([]kolide.Host, error)
type ListHostsInLabelFunc func(lid uint, opt kolide.HostListOptions) ([]kolide.Host, error)
type ListUniqueHostsInLabelsFunc func(labels []uint) ([]kolide.Host, error)
@ -142,7 +142,7 @@ func (s *LabelStore) ListLabelsForHost(hid uint) ([]kolide.Label, error) {
return s.ListLabelsForHostFunc(hid)
}
func (s *LabelStore) ListHostsInLabel(lid uint, opt kolide.ListOptions) ([]kolide.Host, error) {
func (s *LabelStore) ListHostsInLabel(lid uint, opt kolide.HostListOptions) ([]kolide.Host, error) {
s.ListHostsInLabelFuncInvoked = true
return s.ListHostsInLabelFunc(lid, opt)
}

View file

@ -3,8 +3,8 @@ package service
import (
"context"
"github.com/go-kit/kit/endpoint"
"github.com/fleetdm/fleet/server/kolide"
"github.com/go-kit/kit/endpoint"
)
type getLabelRequest struct {
@ -159,7 +159,7 @@ func makeListLabelsEndpoint(svc kolide.Service) endpoint.Endpoint {
type listHostsInLabelRequest struct {
ID uint
ListOptions kolide.ListOptions
ListOptions kolide.HostListOptions
}
func makeListHostsInLabelEndpoint(svc kolide.Service) endpoint.Endpoint {

View file

@ -90,7 +90,7 @@ func (svc service) DeleteLabelByID(ctx context.Context, id uint) error {
return svc.ds.DeleteLabel(label.Name)
}
func (svc service) ListHostsInLabel(ctx context.Context, lid uint, opt kolide.ListOptions) ([]kolide.Host, error) {
func (svc service) ListHostsInLabel(ctx context.Context, lid uint, opt kolide.HostListOptions) ([]kolide.Host, error) {
return svc.ds.ListHostsInLabel(lid, opt)
}
@ -99,7 +99,7 @@ func (svc service) ListLabelsForHost(ctx context.Context, hid uint) ([]kolide.La
}
func (svc service) HostIDsForLabel(lid uint) ([]uint, error) {
hosts, err := svc.ds.ListHostsInLabel(lid, kolide.ListOptions{})
hosts, err := svc.ds.ListHostsInLabel(lid, kolide.HostListOptions{})
if err != nil {
return nil, err
}

View file

@ -7,6 +7,7 @@ import (
"net/http"
"net/url"
"strconv"
"strings"
"github.com/fleetdm/fleet/server/kolide"
"github.com/gorilla/mux"
@ -161,6 +162,39 @@ func listOptionsFromRequest(r *http.Request) (kolide.ListOptions, error) {
}, nil
}
func hostListOptionsFromRequest(r *http.Request) (kolide.HostListOptions, error) {
opt, err := listOptionsFromRequest(r)
if err != nil {
return kolide.HostListOptions{}, err
}
hopt := kolide.HostListOptions{ListOptions: opt}
status := r.URL.Query().Get("status")
switch kolide.HostStatus(status) {
case kolide.StatusNew, kolide.StatusOnline, kolide.StatusOffline, kolide.StatusMIA:
hopt.StatusFilter = kolide.HostStatus(status)
case "":
// No error when unset
default:
return hopt, errors.Errorf("invalid status %s", status)
}
if err != nil {
return hopt, err
}
additionalInfoFiltersString := r.URL.Query().Get("additional_info_filters")
if additionalInfoFiltersString != "" {
hopt.AdditionalFilters = strings.Split(additionalInfoFiltersString, ",")
}
query := r.URL.Query().Get("query")
hopt.MatchQuery = query
return hopt, nil
}
func decodeNoParamsRequest(ctx context.Context, r *http.Request) (interface{}, error) {
return nil, nil
}

View file

@ -3,10 +3,6 @@ package service
import (
"context"
"net/http"
"strings"
"github.com/fleetdm/fleet/server/kolide"
"github.com/pkg/errors"
)
func decodeGetHostRequest(ctx context.Context, r *http.Request) (interface{}, error) {
@ -34,29 +30,10 @@ func decodeDeleteHostRequest(ctx context.Context, r *http.Request) (interface{},
}
func decodeListHostsRequest(ctx context.Context, r *http.Request) (interface{}, error) {
opt, err := listOptionsFromRequest(r)
hopt := kolide.HostListOptions{ListOptions: opt}
status := r.URL.Query().Get("status")
switch kolide.HostStatus(status) {
case kolide.StatusNew, kolide.StatusOnline, kolide.StatusOffline, kolide.StatusMIA:
hopt.StatusFilter = kolide.HostStatus(status)
case "":
// No error when unset
default:
return nil, errors.Errorf("invalid status %s", status)
}
hopt, err := hostListOptionsFromRequest(r)
if err != nil {
return nil, err
}
additionalInfoFiltersString := r.URL.Query().Get("additional_info_filters")
if additionalInfoFiltersString != "" {
hopt.AdditionalFilters = strings.Split(additionalInfoFiltersString, ",")
}
query := r.URL.Query().Get("query")
hopt.MatchQuery = query
return listHostsRequest{ListOptions: hopt}, nil
}

View file

@ -49,11 +49,13 @@ func decodeListHostsInLabelRequest(ctx context.Context, r *http.Request) (interf
if err != nil {
return nil, err
}
opt, err := listOptionsFromRequest(r)
hopt, err := hostListOptionsFromRequest(r)
if err != nil {
return nil, err
}
return listHostsInLabelRequest{ID: id, ListOptions: opt}, nil
return listHostsInLabelRequest{ID: id, ListOptions: hopt}, nil
}
func decodeApplyLabelSpecsRequest(ctx context.Context, r *http.Request) (interface{}, error) {