mirror of
https://github.com/fleetdm/fleet
synced 2026-05-23 17:08:53 +00:00
Make SearchHosts behave the same as the filtering in ListHosts (#4295)
This commit is contained in:
parent
2ab1b9ec85
commit
4034a7ab59
3 changed files with 24 additions and 33 deletions
1
changes/issue-3979-filter-hosts-targets
Normal file
1
changes/issue-3979-filter-hosts-targets
Normal file
|
|
@ -0,0 +1 @@
|
|||
* Make target search behave the same as host search
|
||||
|
|
@ -771,33 +771,19 @@ func (ds *Datastore) MarkHostsSeen(ctx context.Context, hostIDs []uint, t time.T
|
|||
|
||||
// SearchHosts performs a search on the hosts table using the following criteria:
|
||||
// - Use the provided team filter.
|
||||
// - Full-text search with the "query" argument (if query == "", then no fulltext matching is executed).
|
||||
// Full-text search is used even if "query" is a short or stopword.
|
||||
// (what defines a short word is the "ft_min_word_len" VARIABLE, set to 4 by default in Fleet deployments).
|
||||
// - Search hostname, uuid, hardware_serial, and primary_ip using LIKE (mimics ListHosts behavior)
|
||||
// - An optional list of IDs to omit from the search.
|
||||
func (ds *Datastore) SearchHosts(ctx context.Context, filter fleet.TeamFilter, query string, omit ...uint) ([]*fleet.Host, error) {
|
||||
var sqlb strings.Builder
|
||||
sqlb.WriteString(`SELECT
|
||||
func (ds *Datastore) SearchHosts(ctx context.Context, filter fleet.TeamFilter, matchQuery string, omit ...uint) ([]*fleet.Host, error) {
|
||||
query := `SELECT
|
||||
h.*,
|
||||
COALESCE(hst.seen_time, h.created_at) AS seen_time
|
||||
FROM hosts h
|
||||
LEFT JOIN host_seen_times hst
|
||||
ON (h.id=hst.host_id) WHERE`)
|
||||
ON (h.id=hst.host_id) WHERE TRUE `
|
||||
|
||||
var args []interface{}
|
||||
if len(query) > 0 {
|
||||
sqlb.WriteString(` (
|
||||
MATCH (hostname, uuid) AGAINST (? IN BOOLEAN MODE)
|
||||
OR MATCH (primary_ip, primary_mac) AGAINST (? IN BOOLEAN MODE)
|
||||
) AND`)
|
||||
// Transform query argument and append the truncation operator "*" for MATCH.
|
||||
// From Oracle docs: "If a word is specified with the truncation operator, it is not
|
||||
// stripped from a boolean query, even if it is too short or a stopword."
|
||||
hostQuery := transformQueryWithSuffix(query, "*")
|
||||
// Needs quotes to avoid each "." marking a word boundary.
|
||||
// TODO(lucas): Currently matching the primary_mac doesn't work, see #1959.
|
||||
ipQuery := `"` + query + `"`
|
||||
args = append(args, hostQuery, ipQuery)
|
||||
if len(matchQuery) > 0 {
|
||||
query, args = hostSearchLike(query, args, matchQuery, hostSearchColumns...)
|
||||
}
|
||||
var in interface{}
|
||||
// use -1 if there are no values to omit.
|
||||
|
|
@ -807,17 +793,17 @@ func (ds *Datastore) SearchHosts(ctx context.Context, filter fleet.TeamFilter, q
|
|||
in = -1
|
||||
}
|
||||
args = append(args, in)
|
||||
sqlb.WriteString(" id NOT IN (?) AND ")
|
||||
sqlb.WriteString(ds.whereFilterHostsByTeams(filter, "h"))
|
||||
sqlb.WriteString(` ORDER BY h.id DESC LIMIT 10`)
|
||||
query += " AND id NOT IN (?) AND "
|
||||
query += ds.whereFilterHostsByTeams(filter, "h")
|
||||
query += ` ORDER BY h.id DESC LIMIT 10`
|
||||
|
||||
sql, args, err := sqlx.In(sqlb.String(), args...)
|
||||
query, args, err := sqlx.In(query, args...)
|
||||
if err != nil {
|
||||
return nil, ctxerr.Wrap(ctx, err, "searching default hosts")
|
||||
}
|
||||
sql = ds.reader.Rebind(sql)
|
||||
query = ds.reader.Rebind(query)
|
||||
hosts := []*fleet.Host{}
|
||||
if err := sqlx.SelectContext(ctx, ds.reader, &hosts, sql, args...); err != nil {
|
||||
if err := sqlx.SelectContext(ctx, ds.reader, &hosts, query, args...); err != nil {
|
||||
return nil, ctxerr.Wrap(ctx, err, "searching hosts")
|
||||
}
|
||||
return hosts, nil
|
||||
|
|
|
|||
|
|
@ -877,7 +877,7 @@ func testHostsSearch(t *testing.T, ds *Datastore) {
|
|||
SeenTime: time.Now(),
|
||||
NodeKey: "1",
|
||||
UUID: "1",
|
||||
Hostname: "foo.local",
|
||||
Hostname: "fo.local",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
|
|
@ -923,19 +923,23 @@ func testHostsSearch(t *testing.T, ds *Datastore) {
|
|||
_, err = ds.SearchHosts(context.Background(), filter, "")
|
||||
require.NoError(t, err)
|
||||
|
||||
hosts, err := ds.SearchHosts(context.Background(), filter, "foo")
|
||||
hosts, err := ds.SearchHosts(context.Background(), filter, "fo")
|
||||
require.NoError(t, err)
|
||||
assert.Len(t, hosts, 2)
|
||||
|
||||
host, err := ds.SearchHosts(context.Background(), filter, "foo", h3.ID)
|
||||
hosts, err = ds.SearchHosts(context.Background(), filter, "fo.")
|
||||
require.NoError(t, err)
|
||||
require.Len(t, host, 1)
|
||||
assert.Equal(t, "foo.local", host[0].Hostname)
|
||||
assert.Len(t, hosts, 1)
|
||||
|
||||
host, err = ds.SearchHosts(context.Background(), filter, "foo", h3.ID, h2.ID)
|
||||
host, err := ds.SearchHosts(context.Background(), filter, "fo", h3.ID)
|
||||
require.NoError(t, err)
|
||||
require.Len(t, host, 1)
|
||||
assert.Equal(t, "foo.local", host[0].Hostname)
|
||||
assert.Equal(t, "fo.local", host[0].Hostname)
|
||||
|
||||
host, err = ds.SearchHosts(context.Background(), filter, "fo", h3.ID, h2.ID)
|
||||
require.NoError(t, err)
|
||||
require.Len(t, host, 1)
|
||||
assert.Equal(t, "fo.local", host[0].Hostname)
|
||||
|
||||
host, err = ds.SearchHosts(context.Background(), filter, "abc")
|
||||
require.NoError(t, err)
|
||||
|
|
|
|||
Loading…
Reference in a new issue