mirror of
https://github.com/fleetdm/fleet
synced 2026-05-23 17:08:53 +00:00
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:
parent
1c71d397a4
commit
c6c5e65a7d
11 changed files with 61 additions and 42 deletions
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
Loading…
Reference in a new issue