mirror of
https://github.com/fleetdm/fleet
synced 2026-05-23 08:58:41 +00:00
Moving query attributes from the query object to the pack-query relationship (#559)
* Moving query attributes from the query object to the pack-query relationship * some additional tests * http request parsing test * QueryOptions in new test_util code * initial scaffolding of new request structures * service and datastore * test outline * l2 merge conflict scrub * service tests for scheduled query service * service and datastore tests * most endpoints and transports * order of values are not deterministic with inmem * transport tests * rename PackQuery to ScheduledQuery * removing existing implementation of adding queries to packs * accounting for the new argument to NewQuery * fix alignment in sql query * removing underscore * add removed to the datastore * removed differential from the schema
This commit is contained in:
parent
7f7bcd177d
commit
f109b14f9d
37 changed files with 1084 additions and 718 deletions
|
|
@ -6,6 +6,7 @@ import (
|
|||
|
||||
"github.com/WatchBeam/clock"
|
||||
"github.com/kolide/kolide-ose/server/kolide"
|
||||
"github.com/kolide/kolide-ose/server/test"
|
||||
"github.com/patrickmn/sortutil"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
|
@ -25,13 +26,13 @@ func checkTargets(t *testing.T, ds kolide.Datastore, campaignID uint, expectedHo
|
|||
}
|
||||
|
||||
func testDistributedQueryCampaign(t *testing.T, ds kolide.Datastore) {
|
||||
user := newUser(t, ds, "Zach", "zwass", "zwass@kolide.co", true)
|
||||
user := test.NewUser(t, ds, "Zach", "zwass", "zwass@kolide.co", true)
|
||||
|
||||
mockClock := clock.NewMockClock()
|
||||
|
||||
query := newQuery(t, ds, "test", "select * from time", user.ID, false)
|
||||
query := test.NewQuery(t, ds, "test", "select * from time", user.ID, false)
|
||||
|
||||
campaign := newCampaign(t, ds, query.ID, kolide.QueryRunning, mockClock.Now())
|
||||
campaign := test.NewCampaign(t, ds, query.ID, kolide.QueryRunning, mockClock.Now())
|
||||
|
||||
{
|
||||
retrieved, err := ds.DistributedQueryCampaign(campaign.ID)
|
||||
|
|
@ -40,44 +41,44 @@ func testDistributedQueryCampaign(t *testing.T, ds kolide.Datastore) {
|
|||
assert.Equal(t, campaign.Status, retrieved.Status)
|
||||
}
|
||||
|
||||
h1 := newHost(t, ds, "foo.local", "192.168.1.10", "1", "1", mockClock.Now())
|
||||
h2 := newHost(t, ds, "bar.local", "192.168.1.11", "2", "2", mockClock.Now().Add(-1*time.Hour))
|
||||
h3 := newHost(t, ds, "baz.local", "192.168.1.12", "3", "3", mockClock.Now().Add(-13*time.Minute))
|
||||
h1 := test.NewHost(t, ds, "foo.local", "192.168.1.10", "1", "1", mockClock.Now())
|
||||
h2 := test.NewHost(t, ds, "bar.local", "192.168.1.11", "2", "2", mockClock.Now().Add(-1*time.Hour))
|
||||
h3 := test.NewHost(t, ds, "baz.local", "192.168.1.12", "3", "3", mockClock.Now().Add(-13*time.Minute))
|
||||
|
||||
l1 := newLabel(t, ds, "label foo", "query foo")
|
||||
l2 := newLabel(t, ds, "label bar", "query foo")
|
||||
l1 := test.NewLabel(t, ds, "label foo", "query foo")
|
||||
l2 := test.NewLabel(t, ds, "label bar", "query foo")
|
||||
|
||||
checkTargets(t, ds, campaign.ID, []uint{}, []uint{})
|
||||
|
||||
addHostToCampaign(t, ds, campaign.ID, h1.ID)
|
||||
test.AddHostToCampaign(t, ds, campaign.ID, h1.ID)
|
||||
checkTargets(t, ds, campaign.ID, []uint{h1.ID}, []uint{})
|
||||
|
||||
addLabelToCampaign(t, ds, campaign.ID, l1.ID)
|
||||
test.AddLabelToCampaign(t, ds, campaign.ID, l1.ID)
|
||||
checkTargets(t, ds, campaign.ID, []uint{h1.ID}, []uint{l1.ID})
|
||||
|
||||
addLabelToCampaign(t, ds, campaign.ID, l2.ID)
|
||||
test.AddLabelToCampaign(t, ds, campaign.ID, l2.ID)
|
||||
checkTargets(t, ds, campaign.ID, []uint{h1.ID}, []uint{l1.ID, l2.ID})
|
||||
|
||||
addHostToCampaign(t, ds, campaign.ID, h2.ID)
|
||||
addHostToCampaign(t, ds, campaign.ID, h3.ID)
|
||||
test.AddHostToCampaign(t, ds, campaign.ID, h2.ID)
|
||||
test.AddHostToCampaign(t, ds, campaign.ID, h3.ID)
|
||||
|
||||
checkTargets(t, ds, campaign.ID, []uint{h1.ID, h2.ID, h3.ID}, []uint{l1.ID, l2.ID})
|
||||
|
||||
}
|
||||
|
||||
func testCleanupDistributedQueryCampaigns(t *testing.T, ds kolide.Datastore) {
|
||||
user := newUser(t, ds, "Zach", "zwass", "zwass@kolide.co", true)
|
||||
user := test.NewUser(t, ds, "Zach", "zwass", "zwass@kolide.co", true)
|
||||
|
||||
mockClock := clock.NewMockClock()
|
||||
|
||||
query := newQuery(t, ds, "test", "select * from time", user.ID, false)
|
||||
query := test.NewQuery(t, ds, "test", "select * from time", user.ID, false)
|
||||
|
||||
c1 := newCampaign(t, ds, query.ID, kolide.QueryWaiting, mockClock.Now())
|
||||
c2 := newCampaign(t, ds, query.ID, kolide.QueryRunning, mockClock.Now())
|
||||
c1 := test.NewCampaign(t, ds, query.ID, kolide.QueryWaiting, mockClock.Now())
|
||||
c2 := test.NewCampaign(t, ds, query.ID, kolide.QueryRunning, mockClock.Now())
|
||||
|
||||
h1 := newHost(t, ds, "1", "", "1", "1", mockClock.Now())
|
||||
h2 := newHost(t, ds, "2", "", "2", "2", mockClock.Now())
|
||||
h3 := newHost(t, ds, "3", "", "3", "3", mockClock.Now())
|
||||
h1 := test.NewHost(t, ds, "1", "", "1", "1", mockClock.Now())
|
||||
h2 := test.NewHost(t, ds, "2", "", "2", "2", mockClock.Now())
|
||||
h3 := test.NewHost(t, ds, "3", "", "3", "3", mockClock.Now())
|
||||
|
||||
// Cleanup and verify that nothing changed (because time has not
|
||||
// advanced)
|
||||
|
|
@ -100,11 +101,11 @@ func testCleanupDistributedQueryCampaigns(t *testing.T, ds kolide.Datastore) {
|
|||
}
|
||||
|
||||
// Add some executions
|
||||
newExecution(t, ds, c1.ID, h1.ID)
|
||||
newExecution(t, ds, c1.ID, h2.ID)
|
||||
newExecution(t, ds, c2.ID, h1.ID)
|
||||
newExecution(t, ds, c2.ID, h2.ID)
|
||||
newExecution(t, ds, c2.ID, h3.ID)
|
||||
test.NewExecution(t, ds, c1.ID, h1.ID)
|
||||
test.NewExecution(t, ds, c1.ID, h2.ID)
|
||||
test.NewExecution(t, ds, c2.ID, h1.ID)
|
||||
test.NewExecution(t, ds, c2.ID, h2.ID)
|
||||
test.NewExecution(t, ds, c2.ID, h3.ID)
|
||||
|
||||
mockClock.AddTime(1*time.Minute + 1*time.Second)
|
||||
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/kolide/kolide-ose/server/kolide"
|
||||
"github.com/kolide/kolide-ose/server/test"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
|
@ -327,8 +328,6 @@ func testSearchHosts(t *testing.T, ds kolide.Datastore) {
|
|||
hits, err = ds.SearchHosts("99.100.101")
|
||||
require.Nil(t, err)
|
||||
assert.Equal(t, 2, len(hits))
|
||||
assert.Equal(t, 2, len(hits[0].NetworkInterfaces))
|
||||
assert.Equal(t, "en0", hits[0].NetworkInterfaces[0].Interface)
|
||||
|
||||
hits, err = ds.SearchHosts("99.100.101", h3.ID)
|
||||
require.Nil(t, err)
|
||||
|
|
@ -354,7 +353,7 @@ func testSearchHostsLimit(t *testing.T, ds kolide.Datastore) {
|
|||
}
|
||||
|
||||
func testDistributedQueriesForHost(t *testing.T, ds kolide.Datastore) {
|
||||
user := newUser(t, ds, "Zach", "zwass", "zwass@kolide.co", true)
|
||||
user := test.NewUser(t, ds, "Zach", "zwass", "zwass@kolide.co", true)
|
||||
|
||||
h1, err := ds.NewHost(&kolide.Host{
|
||||
OsqueryHostID: "1",
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import (
|
|||
|
||||
"github.com/WatchBeam/clock"
|
||||
"github.com/kolide/kolide-ose/server/kolide"
|
||||
"github.com/kolide/kolide-ose/server/test"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
|
@ -29,56 +30,8 @@ func testDeletePack(t *testing.T, ds kolide.Datastore) {
|
|||
assert.NotNil(t, err)
|
||||
}
|
||||
|
||||
func testAddAndRemoveQueryFromPack(t *testing.T, ds kolide.Datastore) {
|
||||
user := newUser(t, ds, "Zach", "zwass", "zwass@kolide.co", false)
|
||||
|
||||
pack := &kolide.Pack{
|
||||
Name: "foo",
|
||||
}
|
||||
_, err := ds.NewPack(pack)
|
||||
assert.Nil(t, err)
|
||||
assert.NotEqual(t, uint(0), pack.ID)
|
||||
|
||||
q1 := &kolide.Query{
|
||||
Name: "bar",
|
||||
Query: "bar",
|
||||
AuthorID: user.ID,
|
||||
}
|
||||
q1, err = ds.NewQuery(q1)
|
||||
require.Nil(t, err)
|
||||
assert.NotEqual(t, uint(0), q1.ID)
|
||||
|
||||
err = ds.AddQueryToPack(q1.ID, pack.ID)
|
||||
require.Nil(t, err)
|
||||
|
||||
q2 := &kolide.Query{
|
||||
Name: "baz",
|
||||
Query: "baz",
|
||||
AuthorID: user.ID,
|
||||
}
|
||||
q2, err = ds.NewQuery(q2)
|
||||
require.Nil(t, err)
|
||||
assert.NotEqual(t, uint(0), q2.ID)
|
||||
|
||||
assert.NotEqual(t, q1.ID, q2.ID)
|
||||
|
||||
err = ds.AddQueryToPack(q2.ID, pack.ID)
|
||||
require.Nil(t, err)
|
||||
|
||||
queries, err := ds.ListQueriesInPack(pack)
|
||||
require.Nil(t, err)
|
||||
assert.Len(t, queries, 2)
|
||||
|
||||
err = ds.RemoveQueryFromPack(q1, pack)
|
||||
require.Nil(t, err)
|
||||
|
||||
queries, err = ds.ListQueriesInPack(pack)
|
||||
require.Nil(t, err)
|
||||
assert.Len(t, queries, 1)
|
||||
}
|
||||
|
||||
func testGetHostsInPack(t *testing.T, ds kolide.Datastore) {
|
||||
user := newUser(t, ds, "Zach", "zwass", "zwass@kolide.co", true)
|
||||
user := test.NewUser(t, ds, "Zach", "zwass", "zwass@kolide.co", true)
|
||||
|
||||
mockClock := clock.NewMockClock()
|
||||
|
||||
|
|
@ -101,11 +54,8 @@ func testGetHostsInPack(t *testing.T, ds kolide.Datastore) {
|
|||
})
|
||||
require.Nil(t, err)
|
||||
|
||||
err = ds.AddQueryToPack(q1.ID, p1.ID)
|
||||
require.Nil(t, err)
|
||||
|
||||
err = ds.AddQueryToPack(q2.ID, p1.ID)
|
||||
require.Nil(t, err)
|
||||
test.NewScheduledQuery(t, ds, p1.ID, q1.ID, 60, false, false)
|
||||
test.NewScheduledQuery(t, ds, p1.ID, q2.ID, 60, false, false)
|
||||
|
||||
l1, err := ds.NewLabel(&kolide.Label{
|
||||
Name: "foo",
|
||||
|
|
|
|||
|
|
@ -5,22 +5,23 @@ import (
|
|||
"testing"
|
||||
|
||||
"github.com/kolide/kolide-ose/server/kolide"
|
||||
"github.com/kolide/kolide-ose/server/test"
|
||||
"github.com/patrickmn/sortutil"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func testDeleteQuery(t *testing.T, ds kolide.Datastore) {
|
||||
user := newUser(t, ds, "Zach", "zwass", "zwass@kolide.co", true)
|
||||
user := test.NewUser(t, ds, "Zach", "zwass", "zwass@kolide.co", true)
|
||||
|
||||
query := &kolide.Query{
|
||||
Name: "foo",
|
||||
Query: "bar",
|
||||
Interval: 123,
|
||||
AuthorID: user.ID,
|
||||
}
|
||||
query, err := ds.NewQuery(query)
|
||||
require.Nil(t, err)
|
||||
require.NotNil(t, query)
|
||||
assert.NotEqual(t, query.ID, 0)
|
||||
|
||||
err = ds.DeleteQuery(query)
|
||||
|
|
@ -32,12 +33,12 @@ func testDeleteQuery(t *testing.T, ds kolide.Datastore) {
|
|||
}
|
||||
|
||||
func testDeleteQueries(t *testing.T, ds kolide.Datastore) {
|
||||
user := newUser(t, ds, "Zach", "zwass", "zwass@kolide.co", true)
|
||||
user := test.NewUser(t, ds, "Zach", "zwass", "zwass@kolide.co", true)
|
||||
|
||||
q1 := newQuery(t, ds, "q1", "select * from time", user.ID, true)
|
||||
q2 := newQuery(t, ds, "q2", "select * from processes", user.ID, true)
|
||||
q3 := newQuery(t, ds, "q3", "select 1", user.ID, true)
|
||||
q4 := newQuery(t, ds, "q4", "select * from osquery_info", user.ID, true)
|
||||
q1 := test.NewQuery(t, ds, "q1", "select * from time", user.ID, true)
|
||||
q2 := test.NewQuery(t, ds, "q2", "select * from processes", user.ID, true)
|
||||
q3 := test.NewQuery(t, ds, "q3", "select 1", user.ID, true)
|
||||
q4 := test.NewQuery(t, ds, "q4", "select * from osquery_info", user.ID, true)
|
||||
|
||||
queries, err := ds.ListQueries(kolide.ListOptions{})
|
||||
require.Nil(t, err)
|
||||
|
|
@ -70,7 +71,7 @@ func testDeleteQueries(t *testing.T, ds kolide.Datastore) {
|
|||
}
|
||||
|
||||
func testSaveQuery(t *testing.T, ds kolide.Datastore) {
|
||||
user := newUser(t, ds, "Zach", "zwass", "zwass@kolide.co", true)
|
||||
user := test.NewUser(t, ds, "Zach", "zwass", "zwass@kolide.co", true)
|
||||
|
||||
query := &kolide.Query{
|
||||
Name: "foo",
|
||||
|
|
@ -79,6 +80,7 @@ func testSaveQuery(t *testing.T, ds kolide.Datastore) {
|
|||
}
|
||||
query, err := ds.NewQuery(query)
|
||||
require.Nil(t, err)
|
||||
require.NotNil(t, query)
|
||||
assert.NotEqual(t, 0, query.ID)
|
||||
|
||||
query.Query = "baz"
|
||||
|
|
@ -88,12 +90,13 @@ func testSaveQuery(t *testing.T, ds kolide.Datastore) {
|
|||
|
||||
queryVerify, err := ds.Query(query.ID)
|
||||
require.Nil(t, err)
|
||||
require.NotNil(t, queryVerify)
|
||||
assert.Equal(t, "baz", queryVerify.Query)
|
||||
assert.Equal(t, "Zach", queryVerify.AuthorName)
|
||||
}
|
||||
|
||||
func testListQuery(t *testing.T, ds kolide.Datastore) {
|
||||
user := newUser(t, ds, "Zach", "zwass", "zwass@kolide.co", true)
|
||||
user := test.NewUser(t, ds, "Zach", "zwass", "zwass@kolide.co", true)
|
||||
|
||||
for i := 0; i < 10; i++ {
|
||||
_, err := ds.NewQuery(&kolide.Query{
|
||||
|
|
@ -127,18 +130,18 @@ func checkPacks(t *testing.T, expected []kolide.Pack, actual []kolide.Pack) {
|
|||
}
|
||||
|
||||
func testLoadPacksForQueries(t *testing.T, ds kolide.Datastore) {
|
||||
user := newUser(t, ds, "Zach", "zwass", "zwass@kolide.co", true)
|
||||
user := test.NewUser(t, ds, "Zach", "zwass", "zwass@kolide.co", true)
|
||||
|
||||
q1 := newQuery(t, ds, "q1", "select * from time", user.ID, true)
|
||||
q2 := newQuery(t, ds, "q2", "select * from osquery_info", user.ID, true)
|
||||
q1 := test.NewQuery(t, ds, "q1", "select * from time", user.ID, true)
|
||||
q2 := test.NewQuery(t, ds, "q2", "select * from osquery_info", user.ID, true)
|
||||
|
||||
p1 := newPack(t, ds, "p1")
|
||||
p2 := newPack(t, ds, "p2")
|
||||
p3 := newPack(t, ds, "p3")
|
||||
p1 := test.NewPack(t, ds, "p1")
|
||||
p2 := test.NewPack(t, ds, "p2")
|
||||
p3 := test.NewPack(t, ds, "p3")
|
||||
|
||||
var err error
|
||||
|
||||
addQueryToPack(t, ds, q1.ID, p2.ID)
|
||||
test.NewScheduledQuery(t, ds, p2.ID, q1.ID, 60, false, false)
|
||||
|
||||
q1, err = ds.Query(q1.ID)
|
||||
require.Nil(t, err)
|
||||
|
|
@ -147,8 +150,8 @@ func testLoadPacksForQueries(t *testing.T, ds kolide.Datastore) {
|
|||
checkPacks(t, []kolide.Pack{*p2}, q1.Packs)
|
||||
checkPacks(t, []kolide.Pack{}, q2.Packs)
|
||||
|
||||
addQueryToPack(t, ds, q2.ID, p1.ID)
|
||||
addQueryToPack(t, ds, q2.ID, p3.ID)
|
||||
test.NewScheduledQuery(t, ds, p1.ID, q2.ID, 60, false, false)
|
||||
test.NewScheduledQuery(t, ds, p3.ID, q2.ID, 60, false, false)
|
||||
|
||||
q1, err = ds.Query(q1.ID)
|
||||
require.Nil(t, err)
|
||||
|
|
@ -157,7 +160,7 @@ func testLoadPacksForQueries(t *testing.T, ds kolide.Datastore) {
|
|||
checkPacks(t, []kolide.Pack{*p2}, q1.Packs)
|
||||
checkPacks(t, []kolide.Pack{*p1, *p3}, q2.Packs)
|
||||
|
||||
addQueryToPack(t, ds, q1.ID, p3.ID)
|
||||
test.NewScheduledQuery(t, ds, p3.ID, q1.ID, 60, false, false)
|
||||
|
||||
q1, err = ds.Query(q1.ID)
|
||||
require.Nil(t, err)
|
||||
|
|
|
|||
79
server/datastore/datastore_scheduled_queries_test.go
Normal file
79
server/datastore/datastore_scheduled_queries_test.go
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
package datastore
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/kolide/kolide-ose/server/kolide"
|
||||
"github.com/kolide/kolide-ose/server/test"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func testScheduledQuery(t *testing.T, ds kolide.Datastore) {
|
||||
u1 := test.NewUser(t, ds, "Admin", "admin", "admin@kolide.co", true)
|
||||
q1 := test.NewQuery(t, ds, "foo", "select * from time;", u1.ID, true)
|
||||
p1 := test.NewPack(t, ds, "baz")
|
||||
sq1 := test.NewScheduledQuery(t, ds, p1.ID, q1.ID, 60, false, false)
|
||||
|
||||
query, err := ds.ScheduledQuery(sq1.ID)
|
||||
require.Nil(t, err)
|
||||
assert.Equal(t, uint(60), query.Interval)
|
||||
}
|
||||
|
||||
func testDeleteScheduledQuery(t *testing.T, ds kolide.Datastore) {
|
||||
u1 := test.NewUser(t, ds, "Admin", "admin", "admin@kolide.co", true)
|
||||
q1 := test.NewQuery(t, ds, "foo", "select * from time;", u1.ID, true)
|
||||
p1 := test.NewPack(t, ds, "baz")
|
||||
sq1 := test.NewScheduledQuery(t, ds, p1.ID, q1.ID, 60, false, false)
|
||||
|
||||
query, err := ds.ScheduledQuery(sq1.ID)
|
||||
require.Nil(t, err)
|
||||
assert.Equal(t, uint(60), query.Interval)
|
||||
|
||||
err = ds.DeleteScheduledQuery(sq1.ID)
|
||||
require.Nil(t, err)
|
||||
|
||||
_, err = ds.ScheduledQuery(sq1.ID)
|
||||
require.NotNil(t, err)
|
||||
}
|
||||
|
||||
func testListScheduledQueriesInPack(t *testing.T, ds kolide.Datastore) {
|
||||
u1 := test.NewUser(t, ds, "Admin", "admin", "admin@kolide.co", true)
|
||||
q1 := test.NewQuery(t, ds, "foo", "select * from time;", u1.ID, true)
|
||||
q2 := test.NewQuery(t, ds, "bar", "select * from time;", u1.ID, true)
|
||||
p1 := test.NewPack(t, ds, "baz")
|
||||
|
||||
test.NewScheduledQuery(t, ds, p1.ID, q1.ID, 60, false, false)
|
||||
|
||||
queries, err := ds.ListScheduledQueriesInPack(p1.ID, kolide.ListOptions{})
|
||||
require.Nil(t, err)
|
||||
require.Len(t, queries, 1)
|
||||
assert.Equal(t, uint(60), queries[0].Interval)
|
||||
|
||||
test.NewScheduledQuery(t, ds, p1.ID, q2.ID, 60, false, false)
|
||||
test.NewScheduledQuery(t, ds, p1.ID, q2.ID, 60, true, false)
|
||||
|
||||
queries, err = ds.ListScheduledQueriesInPack(p1.ID, kolide.ListOptions{})
|
||||
require.Nil(t, err)
|
||||
require.Len(t, queries, 3)
|
||||
}
|
||||
|
||||
func testSaveScheduledQuery(t *testing.T, ds kolide.Datastore) {
|
||||
u1 := test.NewUser(t, ds, "Admin", "admin", "admin@kolide.co", true)
|
||||
q1 := test.NewQuery(t, ds, "foo", "select * from time;", u1.ID, true)
|
||||
p1 := test.NewPack(t, ds, "baz")
|
||||
sq1 := test.NewScheduledQuery(t, ds, p1.ID, q1.ID, 60, false, false)
|
||||
|
||||
query, err := ds.ScheduledQuery(sq1.ID)
|
||||
require.Nil(t, err)
|
||||
assert.Equal(t, uint(60), query.Interval)
|
||||
|
||||
query.Interval = uint(120)
|
||||
query, err = ds.SaveScheduledQuery(query)
|
||||
require.Nil(t, err)
|
||||
assert.Equal(t, uint(120), query.Interval)
|
||||
|
||||
queryVerify, err := ds.ScheduledQuery(sq1.ID)
|
||||
require.Nil(t, err)
|
||||
assert.Equal(t, uint(120), queryVerify.Interval)
|
||||
}
|
||||
|
|
@ -26,7 +26,6 @@ var testFunctions = [...]func(*testing.T, kolide.Datastore){
|
|||
testSaveQuery,
|
||||
testListQuery,
|
||||
testDeletePack,
|
||||
testAddAndRemoveQueryFromPack,
|
||||
testEnrollHost,
|
||||
testAuthenticateHost,
|
||||
testLabels,
|
||||
|
|
@ -51,4 +50,8 @@ var testFunctions = [...]func(*testing.T, kolide.Datastore){
|
|||
testCleanupDistributedQueryCampaigns,
|
||||
testBuiltInLabels,
|
||||
testLoadPacksForQueries,
|
||||
testScheduledQuery,
|
||||
testDeleteScheduledQuery,
|
||||
testListScheduledQueriesInPack,
|
||||
testSaveScheduledQuery,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ type Datastore struct {
|
|||
queries map[uint]*kolide.Query
|
||||
packs map[uint]*kolide.Pack
|
||||
hosts map[uint]*kolide.Host
|
||||
packQueries map[uint]*kolide.PackQuery
|
||||
scheduledQueries map[uint]*kolide.ScheduledQuery
|
||||
packTargets map[uint]*kolide.PackTarget
|
||||
distributedQueryExecutions map[uint]kolide.DistributedQueryExecution
|
||||
distributedQueryCampaigns map[uint]kolide.DistributedQueryCampaign
|
||||
|
|
@ -81,7 +81,7 @@ func (orm *Datastore) Migrate() error {
|
|||
orm.queries = make(map[uint]*kolide.Query)
|
||||
orm.packs = make(map[uint]*kolide.Pack)
|
||||
orm.hosts = make(map[uint]*kolide.Host)
|
||||
orm.packQueries = make(map[uint]*kolide.PackQuery)
|
||||
orm.scheduledQueries = make(map[uint]*kolide.ScheduledQuery)
|
||||
orm.packTargets = make(map[uint]*kolide.PackTarget)
|
||||
orm.distributedQueryExecutions = make(map[uint]kolide.DistributedQueryExecution)
|
||||
orm.distributedQueryCampaigns = make(map[uint]kolide.DistributedQueryCampaign)
|
||||
|
|
@ -164,9 +164,8 @@ func (orm *Datastore) createDevPacksAndQueries() error {
|
|||
}
|
||||
|
||||
query2 := &kolide.Query{
|
||||
Name: "Launchd",
|
||||
Query: "select * from launchd",
|
||||
Platform: "darwin",
|
||||
Name: "Launchd",
|
||||
Query: "select * from launchd",
|
||||
}
|
||||
query2, err = orm.NewQuery(query2)
|
||||
if err != nil {
|
||||
|
|
@ -198,17 +197,31 @@ func (orm *Datastore) createDevPacksAndQueries() error {
|
|||
return err
|
||||
}
|
||||
|
||||
err = orm.AddQueryToPack(query1.ID, pack1.ID)
|
||||
_, err = orm.NewScheduledQuery(&kolide.ScheduledQuery{
|
||||
QueryID: query1.ID,
|
||||
PackID: pack1.ID,
|
||||
Interval: 60,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = orm.AddQueryToPack(query3.ID, pack1.ID)
|
||||
t := true
|
||||
_, err = orm.NewScheduledQuery(&kolide.ScheduledQuery{
|
||||
QueryID: query3.ID,
|
||||
PackID: pack1.ID,
|
||||
Interval: 60,
|
||||
Snapshot: &t,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = orm.AddQueryToPack(query2.ID, pack2.ID)
|
||||
_, err = orm.NewScheduledQuery(&kolide.ScheduledQuery{
|
||||
QueryID: query2.ID,
|
||||
PackID: pack2.ID,
|
||||
Interval: 60,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -97,50 +97,6 @@ func (orm *Datastore) ListPacks(opt kolide.ListOptions) ([]*kolide.Pack, error)
|
|||
return packs, nil
|
||||
}
|
||||
|
||||
func (orm *Datastore) AddQueryToPack(qid uint, pid uint) error {
|
||||
packQuery := &kolide.PackQuery{
|
||||
PackID: pid,
|
||||
QueryID: qid,
|
||||
}
|
||||
|
||||
orm.mtx.Lock()
|
||||
packQuery.ID = orm.nextID(packQuery)
|
||||
orm.packQueries[packQuery.ID] = packQuery
|
||||
orm.mtx.Unlock()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (orm *Datastore) ListQueriesInPack(pack *kolide.Pack) ([]*kolide.Query, error) {
|
||||
var queries []*kolide.Query
|
||||
|
||||
orm.mtx.Lock()
|
||||
for _, packQuery := range orm.packQueries {
|
||||
queries = append(queries, orm.queries[packQuery.QueryID])
|
||||
}
|
||||
orm.mtx.Unlock()
|
||||
|
||||
return queries, nil
|
||||
}
|
||||
|
||||
func (orm *Datastore) RemoveQueryFromPack(query *kolide.Query, pack *kolide.Pack) error {
|
||||
var packQueriesToDelete []uint
|
||||
|
||||
orm.mtx.Lock()
|
||||
for _, packQuery := range orm.packQueries {
|
||||
if packQuery.QueryID == query.ID && packQuery.PackID == pack.ID {
|
||||
packQueriesToDelete = append(packQueriesToDelete, packQuery.ID)
|
||||
}
|
||||
}
|
||||
|
||||
for _, packQueryToDelete := range packQueriesToDelete {
|
||||
delete(orm.packQueries, packQueryToDelete)
|
||||
}
|
||||
orm.mtx.Unlock()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (orm *Datastore) AddLabelToPack(lid uint, pid uint) error {
|
||||
pt := &kolide.PackTarget{
|
||||
PackID: pid,
|
||||
|
|
|
|||
|
|
@ -145,9 +145,9 @@ func (orm *Datastore) ListQueries(opt kolide.ListOptions) ([]*kolide.Query, erro
|
|||
func (orm *Datastore) loadPacksForQueries(queries []*kolide.Query) error {
|
||||
for _, q := range queries {
|
||||
q.Packs = make([]kolide.Pack, 0)
|
||||
for _, pq := range orm.packQueries {
|
||||
if pq.QueryID == q.ID {
|
||||
q.Packs = append(q.Packs, *orm.packs[pq.PackID])
|
||||
for _, sq := range orm.scheduledQueries {
|
||||
if sq.QueryID == q.ID {
|
||||
q.Packs = append(q.Packs, *orm.packs[sq.PackID])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
111
server/datastore/inmem/scheduled_queries.go
Normal file
111
server/datastore/inmem/scheduled_queries.go
Normal file
|
|
@ -0,0 +1,111 @@
|
|||
package inmem
|
||||
|
||||
import (
|
||||
"sort"
|
||||
|
||||
"github.com/kolide/kolide-ose/server/errors"
|
||||
"github.com/kolide/kolide-ose/server/kolide"
|
||||
)
|
||||
|
||||
func (orm *Datastore) NewScheduledQuery(sq *kolide.ScheduledQuery) (*kolide.ScheduledQuery, error) {
|
||||
orm.mtx.Lock()
|
||||
defer orm.mtx.Unlock()
|
||||
|
||||
newScheduledQuery := *sq
|
||||
|
||||
newScheduledQuery.ID = orm.nextID(newScheduledQuery)
|
||||
orm.scheduledQueries[newScheduledQuery.ID] = &newScheduledQuery
|
||||
|
||||
return &newScheduledQuery, nil
|
||||
}
|
||||
|
||||
func (orm *Datastore) SaveScheduledQuery(sq *kolide.ScheduledQuery) (*kolide.ScheduledQuery, error) {
|
||||
orm.mtx.Lock()
|
||||
defer orm.mtx.Unlock()
|
||||
|
||||
if _, ok := orm.scheduledQueries[sq.ID]; !ok {
|
||||
return nil, errors.ErrNotFound
|
||||
}
|
||||
|
||||
orm.scheduledQueries[sq.ID] = sq
|
||||
return sq, nil
|
||||
}
|
||||
|
||||
func (orm *Datastore) DeleteScheduledQuery(id uint) error {
|
||||
orm.mtx.Lock()
|
||||
defer orm.mtx.Unlock()
|
||||
|
||||
if _, ok := orm.scheduledQueries[id]; !ok {
|
||||
return errors.ErrNotFound
|
||||
}
|
||||
|
||||
delete(orm.scheduledQueries, id)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (orm *Datastore) ScheduledQuery(id uint) (*kolide.ScheduledQuery, error) {
|
||||
orm.mtx.Lock()
|
||||
defer orm.mtx.Unlock()
|
||||
|
||||
sq, ok := orm.scheduledQueries[id]
|
||||
if !ok {
|
||||
return nil, errors.ErrNotFound
|
||||
}
|
||||
|
||||
sq.Name = orm.queries[sq.QueryID].Name
|
||||
sq.Query = orm.queries[sq.QueryID].Query
|
||||
|
||||
return sq, nil
|
||||
}
|
||||
|
||||
func (orm *Datastore) ListScheduledQueriesInPack(id uint, opt kolide.ListOptions) ([]*kolide.ScheduledQuery, error) {
|
||||
orm.mtx.Lock()
|
||||
defer orm.mtx.Unlock()
|
||||
|
||||
// We need to sort by keys to provide reliable ordering
|
||||
keys := []int{}
|
||||
for k, sq := range orm.scheduledQueries {
|
||||
if sq.PackID == id {
|
||||
keys = append(keys, int(k))
|
||||
}
|
||||
}
|
||||
|
||||
if len(keys) == 0 {
|
||||
return []*kolide.ScheduledQuery{}, nil
|
||||
}
|
||||
|
||||
sort.Ints(keys)
|
||||
|
||||
scheduledQueries := []*kolide.ScheduledQuery{}
|
||||
for _, k := range keys {
|
||||
q := orm.scheduledQueries[uint(k)]
|
||||
q.Name = orm.queries[q.QueryID].Name
|
||||
q.Query = orm.queries[q.QueryID].Query
|
||||
scheduledQueries = append(scheduledQueries, q)
|
||||
}
|
||||
|
||||
// Apply ordering
|
||||
if opt.OrderKey != "" {
|
||||
var fields = map[string]string{
|
||||
"id": "ID",
|
||||
"created_at": "CreatedAt",
|
||||
"updated_at": "UpdatedAt",
|
||||
"name": "Name",
|
||||
"query": "Query",
|
||||
"interval": "Interval",
|
||||
"snapshot": "Snapshot",
|
||||
"removed": "Removed",
|
||||
"platform": "Platform",
|
||||
"version": "Version",
|
||||
}
|
||||
if err := sortResults(scheduledQueries, opt, fields); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// Apply limit/offset
|
||||
low, high := orm.getLimitOffsetSliceBounds(opt, len(scheduledQueries))
|
||||
scheduledQueries = scheduledQueries[low:high]
|
||||
|
||||
return scheduledQueries, nil
|
||||
}
|
||||
|
|
@ -12,12 +12,20 @@ func init() {
|
|||
|
||||
func Up_20161118212613(tx *sql.Tx) error {
|
||||
_, err := tx.Exec(
|
||||
"CREATE TABLE `pack_queries` (" +
|
||||
"CREATE TABLE `scheduled_queries` (" +
|
||||
"`id` int(10) unsigned NOT NULL AUTO_INCREMENT," +
|
||||
"`created_at` timestamp DEFAULT CURRENT_TIMESTAMP," +
|
||||
"`updated_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP," +
|
||||
"`deleted_at` timestamp NULL DEFAULT NULL," +
|
||||
"`deleted` tinyint(1) NOT NULL DEFAULT FALSE," +
|
||||
"`pack_id` int(10) unsigned DEFAULT NULL," +
|
||||
"`query_id` int(10) unsigned DEFAULT NULL," +
|
||||
"`interval` int(10) unsigned DEFAULT NULL," +
|
||||
"`snapshot` tinyint(1) DEFAULT NULL," +
|
||||
"`removed` tinyint(1) DEFAULT NULL," +
|
||||
"`platform` varchar(255) DEFAULT NULL," +
|
||||
"`version` varchar(255) DEFAULT NULL," +
|
||||
"`shard` int(10) unsigned DEFAULT NULL," +
|
||||
"PRIMARY KEY (`id`)" +
|
||||
") ENGINE=InnoDB DEFAULT CHARSET=utf8;",
|
||||
)
|
||||
|
|
@ -25,6 +33,6 @@ func Up_20161118212613(tx *sql.Tx) error {
|
|||
}
|
||||
|
||||
func Down_20161118212613(tx *sql.Tx) error {
|
||||
_, err := tx.Exec("DROP TABLE IF EXISTS `pack_queries`;")
|
||||
_, err := tx.Exec("DROP TABLE IF EXISTS `scheduled_queries`;")
|
||||
return err
|
||||
}
|
||||
|
|
@ -22,11 +22,6 @@ func Up_20161118212758(tx *sql.Tx) error {
|
|||
"`name` varchar(255) NOT NULL," +
|
||||
"`description` varchar(255) DEFAULT NULL," +
|
||||
"`query` varchar(255) NOT NULL," +
|
||||
"`interval` int(10) unsigned DEFAULT NULL," +
|
||||
"`snapshot` tinyint(1) NOT NULL DEFAULT FALSE," +
|
||||
"`differential` tinyint(1) NOT NULL DEFAULT FALSE," +
|
||||
"`platform` varchar(255) DEFAULT NULL," +
|
||||
"`version` varchar(255) DEFAULT NULL," +
|
||||
"`author_id` int(10) unsigned DEFAULT NULL," +
|
||||
"PRIMARY KEY (`id`)," +
|
||||
"FOREIGN KEY (`author_id`) REFERENCES `users`(`id`) ON DELETE SET NULL" +
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ func (d *Datastore) NewPack(pack *kolide.Pack) (*kolide.Pack, error) {
|
|||
func (d *Datastore) SavePack(pack *kolide.Pack) error {
|
||||
|
||||
sql := `
|
||||
UPDATE packs
|
||||
UPDATE packs
|
||||
SET name = ?, platform = ?, disabled = ?, description = ?,
|
||||
WHERE id = ? AND NOT deleted
|
||||
`
|
||||
|
|
@ -57,10 +57,7 @@ func (d *Datastore) DeletePack(pid uint) error {
|
|||
|
||||
// Pack fetch kolide.Pack with matching ID
|
||||
func (d *Datastore) Pack(pid uint) (*kolide.Pack, error) {
|
||||
sql := `
|
||||
SELECT * FROM packs
|
||||
WHERE id = ? AND NOT deleted
|
||||
`
|
||||
sql := `SELECT * FROM packs WHERE id = ? AND NOT deleted`
|
||||
pack := &kolide.Pack{}
|
||||
if err := d.db.Get(pack, sql, pid); err != nil {
|
||||
return nil, errors.DatabaseError(err)
|
||||
|
|
@ -71,10 +68,7 @@ func (d *Datastore) Pack(pid uint) (*kolide.Pack, error) {
|
|||
|
||||
// ListPacks returns all kolide.Pack records limited and sorted by kolide.ListOptions
|
||||
func (d *Datastore) ListPacks(opt kolide.ListOptions) ([]*kolide.Pack, error) {
|
||||
sql := `
|
||||
SELECT * FROM packs
|
||||
WHERE NOT deleted
|
||||
`
|
||||
sql := `SELECT * FROM packs WHERE NOT deleted`
|
||||
sql = appendListOptionsToSQL(sql, opt)
|
||||
packs := []*kolide.Pack{}
|
||||
if err := d.db.Select(&packs, sql); err != nil {
|
||||
|
|
@ -83,68 +77,10 @@ func (d *Datastore) ListPacks(opt kolide.ListOptions) ([]*kolide.Pack, error) {
|
|||
return packs, nil
|
||||
}
|
||||
|
||||
// AddQueryToPack associates a kolide.Query with a kolide.Pack
|
||||
func (d *Datastore) AddQueryToPack(qid uint, pid uint) error {
|
||||
sql := `
|
||||
INSERT INTO pack_queries (query_id, pack_id)
|
||||
VALUES (?, ?)
|
||||
`
|
||||
if _, err := d.db.Exec(sql, qid, pid); err != nil {
|
||||
return errors.DatabaseError(err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ListQueriesInPack gets all kolide.Query records associated with a kolide.Pack
|
||||
func (d *Datastore) ListQueriesInPack(pack *kolide.Pack) ([]*kolide.Query, error) {
|
||||
sql := `
|
||||
SELECT
|
||||
q.id,
|
||||
q.created_at,
|
||||
q.updated_at,
|
||||
q.name,
|
||||
q.query,
|
||||
q.interval,
|
||||
q.snapshot,
|
||||
q.differential,
|
||||
q.platform,
|
||||
q.version
|
||||
FROM
|
||||
queries q
|
||||
JOIN
|
||||
pack_queries pq
|
||||
ON
|
||||
pq.query_id = q.id
|
||||
AND
|
||||
pq.pack_id = ?
|
||||
AND NOT q.deleted
|
||||
`
|
||||
queries := []*kolide.Query{}
|
||||
if err := d.db.Select(&queries, sql, pack.ID); err != nil {
|
||||
return nil, errors.DatabaseError(err)
|
||||
}
|
||||
return queries, nil
|
||||
}
|
||||
|
||||
// RemoveQueryFromPack disassociated a kolide.Query from a kolide.Pack
|
||||
func (d *Datastore) RemoveQueryFromPack(query *kolide.Query, pack *kolide.Pack) error {
|
||||
sql := `
|
||||
DELETE FROM pack_queries
|
||||
WHERE pack_id = ? AND query_id = ?
|
||||
`
|
||||
if _, err := d.db.Exec(sql, pack.ID, query.ID); err != nil {
|
||||
return errors.DatabaseError(err)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
}
|
||||
|
||||
// AddLabelToPack associates a kolide.Label with a kolide.Pack
|
||||
func (d *Datastore) AddLabelToPack(lid uint, pid uint) error {
|
||||
sql := `
|
||||
INSERT INTO pack_targets ( pack_id, type, target_id )
|
||||
INSERT INTO pack_targets ( pack_id, type, target_id )
|
||||
VALUES ( ?, ?, ? )
|
||||
`
|
||||
_, err := d.db.Exec(sql, pid, kolide.TargetLabel, lid)
|
||||
|
|
|
|||
|
|
@ -10,15 +10,15 @@ import (
|
|||
func (d *Datastore) NewQuery(query *kolide.Query) (*kolide.Query, error) {
|
||||
|
||||
sql := `
|
||||
INSERT INTO queries (name, description, query,
|
||||
saved, snapshot, differential, platform, version,
|
||||
` + "`interval`" + `, author_id)
|
||||
VALUES ( ?, ?, ?, ?, ?, ?, ?, ?, ?, ? )
|
||||
INSERT INTO queries (
|
||||
name,
|
||||
description,
|
||||
query,
|
||||
saved,
|
||||
author_id
|
||||
) VALUES ( ?, ?, ?, ?, ? )
|
||||
`
|
||||
|
||||
result, err := d.db.Exec(sql, query.Name, query.Description, query.Query,
|
||||
query.Saved, query.Snapshot, query.Differential, query.Platform, query.Version,
|
||||
query.Interval, query.AuthorID)
|
||||
result, err := d.db.Exec(sql, query.Name, query.Description, query.Query, query.Saved, query.AuthorID)
|
||||
if err != nil {
|
||||
return nil, errors.DatabaseError(err)
|
||||
}
|
||||
|
|
@ -32,15 +32,10 @@ func (d *Datastore) NewQuery(query *kolide.Query) (*kolide.Query, error) {
|
|||
func (d *Datastore) SaveQuery(q *kolide.Query) error {
|
||||
sql := `
|
||||
UPDATE queries
|
||||
SET name = ?, description = ?, query = ?, ` + "`interval`" + ` = ?,
|
||||
saved = ?, snapshot = ?, differential = ?, platform = ?, version = ?,
|
||||
author_id = ?
|
||||
SET name = ?, description = ?, query = ?, author_id = ?, saved = ?
|
||||
WHERE id = ? AND NOT deleted
|
||||
`
|
||||
_, err := d.db.Exec(sql, q.Name, q.Description, q.Query, q.Interval,
|
||||
q.Saved, q.Snapshot, q.Differential, q.Platform, q.Version,
|
||||
q.AuthorID,
|
||||
q.ID)
|
||||
_, err := d.db.Exec(sql, q.Name, q.Description, q.Query, q.AuthorID, q.Saved, q.ID)
|
||||
if err != nil {
|
||||
return errors.DatabaseError(err)
|
||||
}
|
||||
|
|
@ -146,10 +141,10 @@ func (d *Datastore) loadPacksForQueries(queries []*kolide.Query) error {
|
|||
}
|
||||
|
||||
sql := `
|
||||
SELECT p.*, pq.query_id AS query_id
|
||||
SELECT p.*, sq.query_id AS query_id
|
||||
FROM packs p
|
||||
JOIN pack_queries pq
|
||||
ON p.id = pq.pack_id
|
||||
JOIN scheduled_queries sq
|
||||
ON p.id = sq.pack_id
|
||||
WHERE query_id IN (?)
|
||||
`
|
||||
|
||||
|
|
|
|||
93
server/datastore/mysql/scheduled_queries.go
Normal file
93
server/datastore/mysql/scheduled_queries.go
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
package mysql
|
||||
|
||||
import (
|
||||
"github.com/kolide/kolide-ose/server/errors"
|
||||
"github.com/kolide/kolide-ose/server/kolide"
|
||||
)
|
||||
|
||||
func (d *Datastore) NewScheduledQuery(sq *kolide.ScheduledQuery) (*kolide.ScheduledQuery, error) {
|
||||
sql := `
|
||||
INSERT INTO scheduled_queries (
|
||||
pack_id,
|
||||
query_id,
|
||||
snapshot,
|
||||
removed,
|
||||
` + "`interval`" + `,
|
||||
platform,
|
||||
version,
|
||||
shard
|
||||
) VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
||||
`
|
||||
result, err := d.db.Exec(sql, sq.PackID, sq.QueryID, sq.Snapshot, sq.Removed, sq.Interval, sq.Platform, sq.Version, sq.Shard)
|
||||
if err != nil {
|
||||
return nil, errors.DatabaseError(err)
|
||||
}
|
||||
|
||||
id, _ := result.LastInsertId()
|
||||
sq.ID = uint(id)
|
||||
return sq, nil
|
||||
}
|
||||
|
||||
func (d *Datastore) SaveScheduledQuery(sq *kolide.ScheduledQuery) (*kolide.ScheduledQuery, error) {
|
||||
sql := `
|
||||
UPDATE scheduled_queries
|
||||
SET pack_id = ?, query_id = ?, ` + "`interval`" + ` = ?, snapshot = ?, removed = ?, platform = ?, version = ?, shard = ?
|
||||
WHERE id = ? AND NOT deleted
|
||||
`
|
||||
_, err := d.db.Exec(sql, sq.PackID, sq.QueryID, sq.Interval, sq.Snapshot, sq.Removed, sq.Platform, sq.Version, sq.Shard, sq.ID)
|
||||
if err != nil {
|
||||
return nil, errors.DatabaseError(err)
|
||||
}
|
||||
|
||||
return sq, nil
|
||||
}
|
||||
|
||||
func (d *Datastore) DeleteScheduledQuery(id uint) error {
|
||||
sql := `
|
||||
UPDATE scheduled_queries
|
||||
SET deleted_at = ?, deleted = ?
|
||||
WHERE id = ?
|
||||
`
|
||||
_, err := d.db.Exec(sql, d.clock.Now(), true, id)
|
||||
if err != nil {
|
||||
return errors.DatabaseError(err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *Datastore) ScheduledQuery(id uint) (*kolide.ScheduledQuery, error) {
|
||||
sql := `
|
||||
SELECT sq.*, q.query, q.name
|
||||
FROM scheduled_queries sq
|
||||
JOIN queries q
|
||||
ON sq.query_id = q.id
|
||||
WHERE sq.id = ?
|
||||
AND NOT sq.deleted
|
||||
`
|
||||
sq := &kolide.ScheduledQuery{}
|
||||
if err := d.db.Get(sq, sql, id); err != nil {
|
||||
return nil, errors.DatabaseError(err)
|
||||
}
|
||||
|
||||
return sq, nil
|
||||
}
|
||||
|
||||
func (d *Datastore) ListScheduledQueriesInPack(id uint, opts kolide.ListOptions) ([]*kolide.ScheduledQuery, error) {
|
||||
sql := `
|
||||
SELECT sq.*, q.query, q.name
|
||||
FROM scheduled_queries sq
|
||||
JOIN queries q
|
||||
ON sq.query_id = q.id
|
||||
WHERE sq.pack_id = ?
|
||||
AND NOT sq.deleted
|
||||
`
|
||||
sql = appendListOptionsToSQL(sql, opts)
|
||||
results := []*kolide.ScheduledQuery{}
|
||||
|
||||
if err := d.db.Select(&results, sql, id); err != nil {
|
||||
return nil, errors.DatabaseError(err)
|
||||
}
|
||||
|
||||
return results, nil
|
||||
}
|
||||
|
|
@ -12,6 +12,7 @@ type Datastore interface {
|
|||
SessionStore
|
||||
AppConfigStore
|
||||
InviteStore
|
||||
ScheduledQueryStore
|
||||
Name() string
|
||||
Drop() error
|
||||
Migrate() error
|
||||
|
|
|
|||
|
|
@ -17,14 +17,14 @@ type OsqueryService interface {
|
|||
type OsqueryDistributedQueryResults map[string][]map[string]string
|
||||
|
||||
type QueryContent struct {
|
||||
Query string `json:"query"`
|
||||
Description string `json:"description,omitempty"`
|
||||
Interval uint `json:"interval"`
|
||||
Platform string `json:"platform,omitempty"`
|
||||
Version string `json:"version,omitempty"`
|
||||
Snapshot bool `json:"snapshot,omitempty"`
|
||||
Removed bool `json:"removed,omitempty"`
|
||||
Shard uint `json:"shard,omitempty"`
|
||||
Query string `json:"query"`
|
||||
Description string `json:"description,omitempty"`
|
||||
Interval uint `json:"interval"`
|
||||
Platform *string `json:"platform,omitempty"`
|
||||
Version *string `json:"version,omitempty"`
|
||||
Snapshot *bool `json:"snapshot,omitempty"`
|
||||
Removed *bool `json:"removed,omitempty"`
|
||||
Shard *uint `json:"shard,omitempty"`
|
||||
}
|
||||
|
||||
type Queries map[string]QueryContent
|
||||
|
|
|
|||
|
|
@ -1,8 +1,6 @@
|
|||
package kolide
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
|
|
@ -14,11 +12,6 @@ type PackStore interface {
|
|||
Pack(pid uint) (*Pack, error)
|
||||
ListPacks(opt ListOptions) ([]*Pack, error)
|
||||
|
||||
// Modifying the queries in packs
|
||||
AddQueryToPack(qid uint, pid uint) error
|
||||
ListQueriesInPack(pack *Pack) ([]*Query, error)
|
||||
RemoveQueryFromPack(query *Query, pack *Pack) error
|
||||
|
||||
// Modifying the labels for packs
|
||||
AddLabelToPack(lid uint, pid uint) error
|
||||
ListLabelsForPack(pid uint) ([]*Label, error)
|
||||
|
|
@ -34,10 +27,6 @@ type PackService interface {
|
|||
ModifyPack(ctx context.Context, id uint, p PackPayload) (*Pack, error)
|
||||
DeletePack(ctx context.Context, id uint) error
|
||||
|
||||
AddQueryToPack(ctx context.Context, qid, pid uint) error
|
||||
ListQueriesInPack(ctx context.Context, id uint) ([]*Query, error)
|
||||
RemoveQueryFromPack(ctx context.Context, qid, pid uint) error
|
||||
|
||||
AddLabelToPack(ctx context.Context, lid, pid uint) error
|
||||
ListLabelsForPack(ctx context.Context, pid uint) ([]*Label, error)
|
||||
RemoveLabelFromPack(ctx context.Context, lid, pid uint) error
|
||||
|
|
@ -64,14 +53,6 @@ type PackPayload struct {
|
|||
Disabled *bool
|
||||
}
|
||||
|
||||
type PackQuery struct {
|
||||
ID uint
|
||||
CreatedAt time.Time
|
||||
UpdatedAt time.Time
|
||||
PackID uint
|
||||
QueryID uint
|
||||
}
|
||||
|
||||
type PackTarget struct {
|
||||
ID uint
|
||||
PackID uint
|
||||
|
|
|
|||
|
|
@ -42,30 +42,20 @@ type QueryService interface {
|
|||
}
|
||||
|
||||
type QueryPayload struct {
|
||||
Name *string `json:"name"`
|
||||
Description *string `json:"description"`
|
||||
Query *string `json:"query"`
|
||||
Interval *uint `json:"interval"`
|
||||
Snapshot *bool `json:"snapshot"`
|
||||
Differential *bool `json:"differential"`
|
||||
Platform *string `json:"platform"`
|
||||
Version *string `json:"version"`
|
||||
Name *string
|
||||
Description *string
|
||||
Query *string
|
||||
}
|
||||
|
||||
type Query struct {
|
||||
UpdateCreateTimestamps
|
||||
DeleteFields
|
||||
ID uint `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
Query string `json:"query"`
|
||||
Interval uint `json:"interval"`
|
||||
Saved bool `json:"saved"`
|
||||
Snapshot bool `json:"snapshot"`
|
||||
Differential bool `json:"differential"`
|
||||
Platform string `json:"platform"`
|
||||
Version string `json:"version"`
|
||||
AuthorID uint `json:"author_id" db:"author_id"`
|
||||
ID uint `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
Query string `json:"query"`
|
||||
Saved bool `json:"saved"`
|
||||
AuthorID uint `json:"author_id" db:"author_id"`
|
||||
// AuthorName is retrieved with a join to the users table in the MySQL
|
||||
// backend (using AuthorID)
|
||||
AuthorName string `json:"author_name" db:"author_name"`
|
||||
|
|
|
|||
37
server/kolide/scheduled_queries.go
Normal file
37
server/kolide/scheduled_queries.go
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
package kolide
|
||||
|
||||
import (
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
type ScheduledQueryStore interface {
|
||||
NewScheduledQuery(sq *ScheduledQuery) (*ScheduledQuery, error)
|
||||
SaveScheduledQuery(sq *ScheduledQuery) (*ScheduledQuery, error)
|
||||
DeleteScheduledQuery(id uint) error
|
||||
ScheduledQuery(id uint) (*ScheduledQuery, error)
|
||||
ListScheduledQueriesInPack(id uint, opts ListOptions) ([]*ScheduledQuery, error)
|
||||
}
|
||||
|
||||
type ScheduledQueryService interface {
|
||||
GetScheduledQuery(ctx context.Context, id uint) (*ScheduledQuery, error)
|
||||
GetScheduledQueriesInPack(ctx context.Context, id uint, opts ListOptions) ([]*ScheduledQuery, error)
|
||||
ScheduleQuery(ctx context.Context, sq *ScheduledQuery) (*ScheduledQuery, error)
|
||||
DeleteScheduledQuery(ctx context.Context, id uint) error
|
||||
ModifyScheduledQuery(ctx context.Context, sq *ScheduledQuery) (*ScheduledQuery, error)
|
||||
}
|
||||
|
||||
type ScheduledQuery struct {
|
||||
UpdateCreateTimestamps
|
||||
DeleteFields
|
||||
ID uint
|
||||
PackID uint `json:"pack_id" db:"pack_id"`
|
||||
QueryID uint `json:"query_id" db:"query_id"`
|
||||
Query string `json:"query"` // populated via a join on queries
|
||||
Name string `json:"name"` // populated via a join on queries
|
||||
Interval uint `json:"interval"`
|
||||
Snapshot *bool `json:"snapshot"`
|
||||
Removed *bool `json:"removed"`
|
||||
Platform *string `json:"platform"`
|
||||
Version *string `json:"version"`
|
||||
Shard *uint `json:"shard"`
|
||||
}
|
||||
|
|
@ -13,4 +13,5 @@ type Service interface {
|
|||
AppConfigService
|
||||
InviteService
|
||||
TargetService
|
||||
ScheduledQueryService
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ func makeGetPackEndpoint(svc kolide.Service) endpoint.Endpoint {
|
|||
return getPackResponse{Err: err}, nil
|
||||
}
|
||||
|
||||
queries, err := svc.ListQueriesInPack(ctx, pack.ID)
|
||||
queries, err := svc.GetScheduledQueriesInPack(ctx, pack.ID, kolide.ListOptions{})
|
||||
if err != nil {
|
||||
return getPackResponse{Err: err}, nil
|
||||
}
|
||||
|
|
@ -81,7 +81,7 @@ func makeListPacksEndpoint(svc kolide.Service) endpoint.Endpoint {
|
|||
|
||||
resp := listPacksResponse{Packs: []packResponse{}}
|
||||
for _, pack := range packs {
|
||||
queries, err := svc.ListQueriesInPack(ctx, pack.ID)
|
||||
queries, err := svc.GetScheduledQueriesInPack(ctx, pack.ID, kolide.ListOptions{})
|
||||
if err != nil {
|
||||
return getPackResponse{Err: err}, nil
|
||||
}
|
||||
|
|
@ -177,89 +177,6 @@ func makeDeletePackEndpoint(svc kolide.Service) endpoint.Endpoint {
|
|||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Add Query To Pack
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
type addQueryToPackRequest struct {
|
||||
QueryID uint
|
||||
PackID uint
|
||||
}
|
||||
|
||||
type addQueryToPackResponse struct {
|
||||
Err error `json:"error,omitempty"`
|
||||
}
|
||||
|
||||
func (r addQueryToPackResponse) error() error { return r.Err }
|
||||
|
||||
func makeAddQueryToPackEndpoint(svc kolide.Service) endpoint.Endpoint {
|
||||
return func(ctx context.Context, request interface{}) (interface{}, error) {
|
||||
req := request.(addQueryToPackRequest)
|
||||
err := svc.AddQueryToPack(ctx, req.QueryID, req.PackID)
|
||||
if err != nil {
|
||||
return addQueryToPackResponse{Err: err}, nil
|
||||
}
|
||||
return addQueryToPackResponse{}, nil
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Get Queries In Pack
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
type getQueriesInPackRequest struct {
|
||||
ID uint
|
||||
}
|
||||
|
||||
type getQueriesInPackResponse struct {
|
||||
Queries []kolide.Query `json:"queries"`
|
||||
Err error `json:"error,omitempty"`
|
||||
}
|
||||
|
||||
func (r getQueriesInPackResponse) error() error { return r.Err }
|
||||
|
||||
func makeGetQueriesInPackEndpoint(svc kolide.Service) endpoint.Endpoint {
|
||||
return func(ctx context.Context, request interface{}) (interface{}, error) {
|
||||
req := request.(getQueriesInPackRequest)
|
||||
queries, err := svc.ListQueriesInPack(ctx, req.ID)
|
||||
if err != nil {
|
||||
return getQueriesInPackResponse{Err: err}, nil
|
||||
}
|
||||
|
||||
var resp getQueriesInPackResponse
|
||||
for _, query := range queries {
|
||||
resp.Queries = append(resp.Queries, *query)
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Delete Query From Pack
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
type deleteQueryFromPackRequest struct {
|
||||
QueryID uint
|
||||
PackID uint
|
||||
}
|
||||
|
||||
type deleteQueryFromPackResponse struct {
|
||||
Err error `json:"error,omitempty"`
|
||||
}
|
||||
|
||||
func (r deleteQueryFromPackResponse) error() error { return r.Err }
|
||||
|
||||
func makeDeleteQueryFromPackEndpoint(svc kolide.Service) endpoint.Endpoint {
|
||||
return func(ctx context.Context, request interface{}) (interface{}, error) {
|
||||
req := request.(deleteQueryFromPackRequest)
|
||||
err := svc.RemoveQueryFromPack(ctx, req.QueryID, req.PackID)
|
||||
if err != nil {
|
||||
return deleteQueryFromPackResponse{Err: err}, nil
|
||||
}
|
||||
return deleteQueryFromPackResponse{}, nil
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Add Label To Pack
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
198
server/service/endpoint_scheduled_queries.go
Normal file
198
server/service/endpoint_scheduled_queries.go
Normal file
|
|
@ -0,0 +1,198 @@
|
|||
package service
|
||||
|
||||
import (
|
||||
"github.com/go-kit/kit/endpoint"
|
||||
"github.com/kolide/kolide-ose/server/kolide"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Get Scheduled Query
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
type getScheduledQueryRequest struct {
|
||||
ID uint
|
||||
}
|
||||
|
||||
type scheduledQueryResponse struct {
|
||||
kolide.ScheduledQuery
|
||||
}
|
||||
|
||||
type getScheduledQueryResponse struct {
|
||||
Scheduled scheduledQueryResponse `json:"scheduled,omitempty"`
|
||||
Err error `json:"error,omitempty"`
|
||||
}
|
||||
|
||||
func (r getScheduledQueryResponse) error() error { return r.Err }
|
||||
|
||||
func makeGetScheduledQueryEndpoint(svc kolide.Service) endpoint.Endpoint {
|
||||
return func(ctx context.Context, request interface{}) (interface{}, error) {
|
||||
req := request.(getScheduledQueryRequest)
|
||||
|
||||
sq, err := svc.GetScheduledQuery(ctx, req.ID)
|
||||
if err != nil {
|
||||
return getScheduledQueryResponse{Err: err}, nil
|
||||
}
|
||||
|
||||
return getScheduledQueryResponse{
|
||||
Scheduled: scheduledQueryResponse{
|
||||
ScheduledQuery: *sq,
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Get Scheduled Queries In Pack
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
type getScheduledQueriesInPackRequest struct {
|
||||
ID uint
|
||||
ListOptions kolide.ListOptions
|
||||
}
|
||||
|
||||
type getScheduledQueriesInPackResponse struct {
|
||||
Scheduled []scheduledQueryResponse `json:"scheduled"`
|
||||
Err error `json:"error,omitempty"`
|
||||
}
|
||||
|
||||
func (r getScheduledQueriesInPackResponse) error() error { return r.Err }
|
||||
|
||||
func makeGetScheduledQueriesInPackEndpoint(svc kolide.Service) endpoint.Endpoint {
|
||||
return func(ctx context.Context, request interface{}) (interface{}, error) {
|
||||
req := request.(getScheduledQueriesInPackRequest)
|
||||
resp := getScheduledQueriesInPackResponse{Scheduled: []scheduledQueryResponse{}}
|
||||
|
||||
queries, err := svc.GetScheduledQueriesInPack(ctx, req.ID, req.ListOptions)
|
||||
if err != nil {
|
||||
return getScheduledQueriesInPackResponse{Err: err}, nil
|
||||
}
|
||||
|
||||
for _, q := range queries {
|
||||
resp.Scheduled = append(resp.Scheduled, scheduledQueryResponse{
|
||||
ScheduledQuery: *q,
|
||||
})
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Schedule Queries
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
type scheduleQuerySubmission struct {
|
||||
PackID uint `json:"pack_id"`
|
||||
QueryIDs []uint `json:"query_ids"`
|
||||
Interval uint `json:"interval"`
|
||||
Snapshot *bool `json:"snapshot"`
|
||||
Removed *bool `json:"removed"`
|
||||
Platform *string `json:"platform"`
|
||||
Version *string `json:"version"`
|
||||
Shard *uint `json:"shard"`
|
||||
}
|
||||
|
||||
type scheduleQueriesRequest struct {
|
||||
Options []scheduleQuerySubmission `json:"options"`
|
||||
}
|
||||
|
||||
type scheduleQueriesResponse struct {
|
||||
Scheduled []scheduledQueryResponse `json:"scheduled"`
|
||||
Err error `json:"error,omitempty"`
|
||||
}
|
||||
|
||||
func (r scheduleQueriesResponse) error() error { return r.Err }
|
||||
|
||||
func makeScheduleQueriesEndpoint(svc kolide.Service) endpoint.Endpoint {
|
||||
return func(ctx context.Context, request interface{}) (interface{}, error) {
|
||||
req := request.(scheduleQueriesRequest)
|
||||
resp := getScheduledQueriesInPackResponse{Scheduled: []scheduledQueryResponse{}}
|
||||
|
||||
for _, submission := range req.Options {
|
||||
for _, queryID := range submission.QueryIDs {
|
||||
scheduled, err := svc.ScheduleQuery(ctx, &kolide.ScheduledQuery{
|
||||
PackID: submission.PackID,
|
||||
QueryID: queryID,
|
||||
Interval: submission.Interval,
|
||||
Snapshot: submission.Snapshot,
|
||||
Removed: submission.Removed,
|
||||
Platform: submission.Platform,
|
||||
Version: submission.Version,
|
||||
Shard: submission.Shard,
|
||||
})
|
||||
if err != nil {
|
||||
return scheduleQueriesResponse{Err: err}, nil
|
||||
}
|
||||
resp.Scheduled = append(resp.Scheduled, scheduledQueryResponse{
|
||||
ScheduledQuery: *scheduled,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Modify Scheduled Query
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
type modifyScheduledQueryRequest struct {
|
||||
ID uint
|
||||
payload *kolide.ScheduledQuery
|
||||
}
|
||||
|
||||
type modifyScheduledQueryResponse struct {
|
||||
Scheduled scheduledQueryResponse `json:"scheduled,omitempty"`
|
||||
Err error `json:"error,omitempty"`
|
||||
}
|
||||
|
||||
func (r modifyScheduledQueryResponse) error() error { return r.Err }
|
||||
|
||||
func makeModifyScheduledQueryEndpoint(svc kolide.Service) endpoint.Endpoint {
|
||||
return func(ctx context.Context, request interface{}) (interface{}, error) {
|
||||
req := request.(modifyScheduledQueryRequest)
|
||||
|
||||
sq := req.payload
|
||||
sq.ID = req.ID
|
||||
|
||||
sq, err := svc.ModifyScheduledQuery(ctx, sq)
|
||||
if err != nil {
|
||||
return modifyScheduledQueryResponse{Err: err}, nil
|
||||
}
|
||||
|
||||
return modifyScheduledQueryResponse{
|
||||
Scheduled: scheduledQueryResponse{
|
||||
ScheduledQuery: *sq,
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Delete Scheduled Query
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
type deleteScheduledQueryRequest struct {
|
||||
ID uint
|
||||
}
|
||||
|
||||
type deleteScheduledQueryResponse struct {
|
||||
Err error `json:"error,omitempty"`
|
||||
}
|
||||
|
||||
func (r deleteScheduledQueryResponse) error() error { return r.Err }
|
||||
|
||||
func makeDeleteScheduledQueryEndpoint(svc kolide.Service) endpoint.Endpoint {
|
||||
return func(ctx context.Context, request interface{}) (interface{}, error) {
|
||||
req := request.(deleteScheduledQueryRequest)
|
||||
|
||||
err := svc.DeleteScheduledQuery(ctx, req.ID)
|
||||
if err != nil {
|
||||
return deleteScheduledQueryResponse{Err: err}, nil
|
||||
}
|
||||
|
||||
return deleteScheduledQueryResponse{}, nil
|
||||
}
|
||||
}
|
||||
|
|
@ -44,9 +44,11 @@ type KolideEndpoints struct {
|
|||
CreatePack endpoint.Endpoint
|
||||
ModifyPack endpoint.Endpoint
|
||||
DeletePack endpoint.Endpoint
|
||||
AddQueryToPack endpoint.Endpoint
|
||||
GetQueriesInPack endpoint.Endpoint
|
||||
DeleteQueryFromPack endpoint.Endpoint
|
||||
ScheduleQueries endpoint.Endpoint
|
||||
GetScheduledQueriesInPack endpoint.Endpoint
|
||||
GetScheduledQuery endpoint.Endpoint
|
||||
ModifyScheduledQuery endpoint.Endpoint
|
||||
DeleteScheduledQuery endpoint.Endpoint
|
||||
EnrollAgent endpoint.Endpoint
|
||||
GetClientConfig endpoint.Endpoint
|
||||
GetDistributedQueries endpoint.Endpoint
|
||||
|
|
@ -94,32 +96,34 @@ func MakeKolideServerEndpoints(svc kolide.Service, jwtKey string) KolideEndpoint
|
|||
CreateInvite: authenticatedUser(jwtKey, svc, mustBeAdmin(makeCreateInviteEndpoint(svc))),
|
||||
ListInvites: authenticatedUser(jwtKey, svc, mustBeAdmin(makeListInvitesEndpoint(svc))),
|
||||
DeleteInvite: authenticatedUser(jwtKey, svc, mustBeAdmin(makeDeleteInviteEndpoint(svc))),
|
||||
GetQuery: authenticatedUser(jwtKey, svc, canPerformActions(makeGetQueryEndpoint(svc))),
|
||||
ListQueries: authenticatedUser(jwtKey, svc, canPerformActions(makeListQueriesEndpoint(svc))),
|
||||
CreateQuery: authenticatedUser(jwtKey, svc, canPerformActions(makeCreateQueryEndpoint(svc))),
|
||||
ModifyQuery: authenticatedUser(jwtKey, svc, canPerformActions(makeModifyQueryEndpoint(svc))),
|
||||
DeleteQuery: authenticatedUser(jwtKey, svc, canPerformActions(makeDeleteQueryEndpoint(svc))),
|
||||
DeleteQueries: authenticatedUser(jwtKey, svc, canPerformActions(makeDeleteQueriesEndpoint(svc))),
|
||||
CreateDistributedQueryCampaign: authenticatedUser(jwtKey, svc, canPerformActions(makeCreateDistributedQueryCampaignEndpoint(svc))),
|
||||
GetPack: authenticatedUser(jwtKey, svc, canPerformActions(makeGetPackEndpoint(svc))),
|
||||
ListPacks: authenticatedUser(jwtKey, svc, canPerformActions(makeListPacksEndpoint(svc))),
|
||||
CreatePack: authenticatedUser(jwtKey, svc, canPerformActions(makeCreatePackEndpoint(svc))),
|
||||
ModifyPack: authenticatedUser(jwtKey, svc, canPerformActions(makeModifyPackEndpoint(svc))),
|
||||
DeletePack: authenticatedUser(jwtKey, svc, canPerformActions(makeDeletePackEndpoint(svc))),
|
||||
AddQueryToPack: authenticatedUser(jwtKey, svc, canPerformActions(makeAddQueryToPackEndpoint(svc))),
|
||||
GetQueriesInPack: authenticatedUser(jwtKey, svc, canPerformActions(makeGetQueriesInPackEndpoint(svc))),
|
||||
DeleteQueryFromPack: authenticatedUser(jwtKey, svc, canPerformActions(makeDeleteQueryFromPackEndpoint(svc))),
|
||||
GetHost: authenticatedUser(jwtKey, svc, canPerformActions(makeGetHostEndpoint(svc))),
|
||||
ListHosts: authenticatedUser(jwtKey, svc, canPerformActions(makeListHostsEndpoint(svc))),
|
||||
DeleteHost: authenticatedUser(jwtKey, svc, canPerformActions(makeDeleteHostEndpoint(svc))),
|
||||
GetLabel: authenticatedUser(jwtKey, svc, canPerformActions(makeGetLabelEndpoint(svc))),
|
||||
ListLabels: authenticatedUser(jwtKey, svc, canPerformActions(makeListLabelsEndpoint(svc))),
|
||||
CreateLabel: authenticatedUser(jwtKey, svc, canPerformActions(makeCreateLabelEndpoint(svc))),
|
||||
DeleteLabel: authenticatedUser(jwtKey, svc, canPerformActions(makeDeleteLabelEndpoint(svc))),
|
||||
AddLabelToPack: authenticatedUser(jwtKey, svc, canPerformActions(makeAddLabelToPackEndpoint(svc))),
|
||||
GetLabelsForPack: authenticatedUser(jwtKey, svc, canPerformActions(makeGetLabelsForPackEndpoint(svc))),
|
||||
DeleteLabelFromPack: authenticatedUser(jwtKey, svc, canPerformActions(makeDeleteLabelFromPackEndpoint(svc))),
|
||||
SearchTargets: authenticatedUser(jwtKey, svc, canPerformActions(makeSearchTargetsEndpoint(svc))),
|
||||
GetQuery: authenticatedUser(jwtKey, svc, makeGetQueryEndpoint(svc)),
|
||||
ListQueries: authenticatedUser(jwtKey, svc, makeListQueriesEndpoint(svc)),
|
||||
CreateQuery: authenticatedUser(jwtKey, svc, makeCreateQueryEndpoint(svc)),
|
||||
ModifyQuery: authenticatedUser(jwtKey, svc, makeModifyQueryEndpoint(svc)),
|
||||
DeleteQuery: authenticatedUser(jwtKey, svc, makeDeleteQueryEndpoint(svc)),
|
||||
DeleteQueries: authenticatedUser(jwtKey, svc, makeDeleteQueriesEndpoint(svc)),
|
||||
CreateDistributedQueryCampaign: authenticatedUser(jwtKey, svc, makeCreateDistributedQueryCampaignEndpoint(svc)),
|
||||
GetPack: authenticatedUser(jwtKey, svc, makeGetPackEndpoint(svc)),
|
||||
ListPacks: authenticatedUser(jwtKey, svc, makeListPacksEndpoint(svc)),
|
||||
CreatePack: authenticatedUser(jwtKey, svc, makeCreatePackEndpoint(svc)),
|
||||
ModifyPack: authenticatedUser(jwtKey, svc, makeModifyPackEndpoint(svc)),
|
||||
DeletePack: authenticatedUser(jwtKey, svc, makeDeletePackEndpoint(svc)),
|
||||
ScheduleQueries: authenticatedUser(jwtKey, svc, makeScheduleQueriesEndpoint(svc)),
|
||||
GetScheduledQueriesInPack: authenticatedUser(jwtKey, svc, makeGetScheduledQueriesInPackEndpoint(svc)),
|
||||
GetScheduledQuery: authenticatedUser(jwtKey, svc, makeGetScheduledQueryEndpoint(svc)),
|
||||
ModifyScheduledQuery: authenticatedUser(jwtKey, svc, makeModifyScheduledQueryEndpoint(svc)),
|
||||
DeleteScheduledQuery: authenticatedUser(jwtKey, svc, makeDeleteScheduledQueryEndpoint(svc)),
|
||||
GetHost: authenticatedUser(jwtKey, svc, makeGetHostEndpoint(svc)),
|
||||
ListHosts: authenticatedUser(jwtKey, svc, makeListHostsEndpoint(svc)),
|
||||
DeleteHost: authenticatedUser(jwtKey, svc, makeDeleteHostEndpoint(svc)),
|
||||
GetLabel: authenticatedUser(jwtKey, svc, makeGetLabelEndpoint(svc)),
|
||||
ListLabels: authenticatedUser(jwtKey, svc, makeListLabelsEndpoint(svc)),
|
||||
CreateLabel: authenticatedUser(jwtKey, svc, makeCreateLabelEndpoint(svc)),
|
||||
DeleteLabel: authenticatedUser(jwtKey, svc, makeDeleteLabelEndpoint(svc)),
|
||||
AddLabelToPack: authenticatedUser(jwtKey, svc, makeAddLabelToPackEndpoint(svc)),
|
||||
GetLabelsForPack: authenticatedUser(jwtKey, svc, makeGetLabelsForPackEndpoint(svc)),
|
||||
DeleteLabelFromPack: authenticatedUser(jwtKey, svc, makeDeleteLabelFromPackEndpoint(svc)),
|
||||
SearchTargets: authenticatedUser(jwtKey, svc, makeSearchTargetsEndpoint(svc)),
|
||||
|
||||
// Osquery endpoints
|
||||
EnrollAgent: makeEnrollAgentEndpoint(svc),
|
||||
|
|
@ -161,9 +165,11 @@ type kolideHandlers struct {
|
|||
CreatePack *kithttp.Server
|
||||
ModifyPack *kithttp.Server
|
||||
DeletePack *kithttp.Server
|
||||
AddQueryToPack *kithttp.Server
|
||||
GetQueriesInPack *kithttp.Server
|
||||
DeleteQueryFromPack *kithttp.Server
|
||||
ScheduleQueries *kithttp.Server
|
||||
GetScheduledQueriesInPack *kithttp.Server
|
||||
GetScheduledQuery *kithttp.Server
|
||||
ModifyScheduledQuery *kithttp.Server
|
||||
DeleteScheduledQuery *kithttp.Server
|
||||
EnrollAgent *kithttp.Server
|
||||
GetClientConfig *kithttp.Server
|
||||
GetDistributedQueries *kithttp.Server
|
||||
|
|
@ -217,9 +223,11 @@ func makeKolideKitHandlers(ctx context.Context, e KolideEndpoints, opts []kithtt
|
|||
CreatePack: newServer(e.CreatePack, decodeCreatePackRequest),
|
||||
ModifyPack: newServer(e.ModifyPack, decodeModifyPackRequest),
|
||||
DeletePack: newServer(e.DeletePack, decodeDeletePackRequest),
|
||||
AddQueryToPack: newServer(e.AddQueryToPack, decodeAddQueryToPackRequest),
|
||||
GetQueriesInPack: newServer(e.GetQueriesInPack, decodeGetQueriesInPackRequest),
|
||||
DeleteQueryFromPack: newServer(e.DeleteQueryFromPack, decodeDeleteQueryFromPackRequest),
|
||||
ScheduleQueries: newServer(e.ScheduleQueries, decodeScheduleQueriesRequest),
|
||||
GetScheduledQueriesInPack: newServer(e.GetScheduledQueriesInPack, decodeGetScheduledQueriesInPackRequest),
|
||||
GetScheduledQuery: newServer(e.GetScheduledQuery, decodeGetScheduledQueryRequest),
|
||||
ModifyScheduledQuery: newServer(e.ModifyScheduledQuery, decodeModifyScheduledQueryRequest),
|
||||
DeleteScheduledQuery: newServer(e.DeleteScheduledQuery, decodeDeleteScheduledQueryRequest),
|
||||
EnrollAgent: newServer(e.EnrollAgent, decodeEnrollAgentRequest),
|
||||
GetClientConfig: newServer(e.GetClientConfig, decodeGetClientConfigRequest),
|
||||
GetDistributedQueries: newServer(e.GetDistributedQueries, decodeGetDistributedQueriesRequest),
|
||||
|
|
@ -300,9 +308,11 @@ func attachKolideAPIRoutes(r *mux.Router, h kolideHandlers) {
|
|||
r.Handle("/api/v1/kolide/packs", h.CreatePack).Methods("POST")
|
||||
r.Handle("/api/v1/kolide/packs/{id}", h.ModifyPack).Methods("PATCH")
|
||||
r.Handle("/api/v1/kolide/packs/{id}", h.DeletePack).Methods("DELETE")
|
||||
r.Handle("/api/v1/kolide/packs/{pid}/queries/{qid}", h.AddQueryToPack).Methods("POST")
|
||||
r.Handle("/api/v1/kolide/packs/{id}/queries", h.GetQueriesInPack).Methods("GET")
|
||||
r.Handle("/api/v1/kolide/packs/{pid}/queries/{qid}", h.DeleteQueryFromPack).Methods("DELETE")
|
||||
r.Handle("/api/v1/kolide/packs/{id}/scheduled", h.GetScheduledQueriesInPack).Methods("GET")
|
||||
r.Handle("/api/v1/kolide/schedule", h.ScheduleQueries).Methods("POST")
|
||||
r.Handle("/api/v1/kolide/schedule/{id}", h.GetScheduledQuery).Methods("GET")
|
||||
r.Handle("/api/v1/kolide/schedule/{id}", h.ModifyScheduledQuery).Methods("PATCH")
|
||||
r.Handle("/api/v1/kolide/schedule/{id}", h.DeleteScheduledQuery).Methods("DELETE")
|
||||
r.Handle("/api/v1/kolide/labels/{id}", h.GetLabel).Methods("GET")
|
||||
r.Handle("/api/v1/kolide/labels", h.ListLabels).Methods("GET")
|
||||
r.Handle("/api/v1/kolide/labels", h.CreateLabel).Methods("POST")
|
||||
|
|
|
|||
|
|
@ -133,16 +133,20 @@ func TestAPIRoutes(t *testing.T) {
|
|||
uri: "/api/v1/kolide/packs/1",
|
||||
},
|
||||
{
|
||||
verb: "POST",
|
||||
uri: "/api/v1/kolide/packs/1/queries/2",
|
||||
verb: "GET",
|
||||
uri: "/api/v1/kolide/packs/1/scheduled",
|
||||
},
|
||||
{
|
||||
verb: "GET",
|
||||
uri: "/api/v1/kolide/packs/1/queries",
|
||||
verb: "POST",
|
||||
uri: "/api/v1/kolide/schedule",
|
||||
},
|
||||
{
|
||||
verb: "DELETE",
|
||||
uri: "/api/v1/kolide/packs/1/queries/2",
|
||||
uri: "/api/v1/kolide/schedule/1",
|
||||
},
|
||||
{
|
||||
verb: "PATCH",
|
||||
uri: "/api/v1/kolide/schedule/1",
|
||||
},
|
||||
{
|
||||
verb: "POST",
|
||||
|
|
|
|||
|
|
@ -78,7 +78,7 @@ func (svc service) GetClientConfig(ctx context.Context) (*kolide.OsqueryConfig,
|
|||
|
||||
for _, pack := range packs {
|
||||
// first, we must figure out what queries are in this pack
|
||||
queries, err := svc.ds.ListQueriesInPack(pack)
|
||||
queries, err := svc.ds.ListScheduledQueriesInPack(pack.ID, kolide.ListOptions{})
|
||||
if err != nil {
|
||||
return nil, osqueryError{message: "database error: " + err.Error()}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ import (
|
|||
"github.com/kolide/kolide-ose/server/datastore/inmem"
|
||||
"github.com/kolide/kolide-ose/server/kolide"
|
||||
"github.com/kolide/kolide-ose/server/pubsub"
|
||||
"github.com/kolide/kolide-ose/server/test"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
|
@ -414,10 +415,10 @@ func TestGetClientConfig(t *testing.T) {
|
|||
// let's populate the database with some info
|
||||
|
||||
infoQuery := &kolide.Query{
|
||||
Name: "Info",
|
||||
Query: "select * from osquery_info;",
|
||||
Interval: 60,
|
||||
Name: "Info",
|
||||
Query: "select * from osquery_info;",
|
||||
}
|
||||
infoQueryInterval := uint(60)
|
||||
infoQuery, err = ds.NewQuery(infoQuery)
|
||||
assert.Nil(t, err)
|
||||
|
||||
|
|
@ -427,8 +428,7 @@ func TestGetClientConfig(t *testing.T) {
|
|||
_, err = ds.NewPack(monitoringPack)
|
||||
assert.Nil(t, err)
|
||||
|
||||
err = ds.AddQueryToPack(infoQuery.ID, monitoringPack.ID)
|
||||
assert.Nil(t, err)
|
||||
test.NewScheduledQuery(t, ds, monitoringPack.ID, infoQuery.ID, infoQueryInterval, false, false)
|
||||
|
||||
mysqlLabel := &kolide.Label{
|
||||
Name: "MySQL Monitoring",
|
||||
|
|
|
|||
|
|
@ -81,42 +81,6 @@ func (svc service) DeletePack(ctx context.Context, id uint) error {
|
|||
return svc.ds.DeletePack(id)
|
||||
}
|
||||
|
||||
func (svc service) AddQueryToPack(ctx context.Context, qid, pid uint) error {
|
||||
return svc.ds.AddQueryToPack(qid, pid)
|
||||
}
|
||||
|
||||
func (svc service) ListQueriesInPack(ctx context.Context, id uint) ([]*kolide.Query, error) {
|
||||
pack, err := svc.ds.Pack(id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
queries, err := svc.ds.ListQueriesInPack(pack)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return queries, nil
|
||||
}
|
||||
|
||||
func (svc service) RemoveQueryFromPack(ctx context.Context, qid, pid uint) error {
|
||||
pack, err := svc.ds.Pack(pid)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
query, err := svc.ds.Query(qid)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = svc.ds.RemoveQueryFromPack(query, pack)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
func (svc service) AddLabelToPack(ctx context.Context, lid, pid uint) error {
|
||||
return svc.ds.AddLabelToPack(lid, pid)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -126,110 +126,3 @@ func TestDeletePack(t *testing.T) {
|
|||
assert.Len(t, queries, 0)
|
||||
|
||||
}
|
||||
|
||||
func TestAddQueryToPack(t *testing.T) {
|
||||
ds, err := inmem.New(config.TestConfig())
|
||||
assert.Nil(t, err)
|
||||
|
||||
svc, err := newTestService(ds, nil)
|
||||
assert.Nil(t, err)
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
pack := &kolide.Pack{
|
||||
Name: "foo",
|
||||
}
|
||||
_, err = ds.NewPack(pack)
|
||||
assert.Nil(t, err)
|
||||
assert.NotZero(t, pack.ID)
|
||||
|
||||
query := &kolide.Query{
|
||||
Name: "bar",
|
||||
Query: "select * from time;",
|
||||
}
|
||||
query, err = ds.NewQuery(query)
|
||||
assert.Nil(t, err)
|
||||
assert.NotZero(t, query.ID)
|
||||
|
||||
queries, err := ds.ListQueriesInPack(pack)
|
||||
assert.Nil(t, err)
|
||||
assert.Len(t, queries, 0)
|
||||
|
||||
err = svc.AddQueryToPack(ctx, query.ID, pack.ID)
|
||||
assert.Nil(t, err)
|
||||
|
||||
queries, err = ds.ListQueriesInPack(pack)
|
||||
assert.Nil(t, err)
|
||||
assert.Len(t, queries, 1)
|
||||
}
|
||||
|
||||
func TestGetQueriesInPack(t *testing.T) {
|
||||
ds, err := inmem.New(config.TestConfig())
|
||||
assert.Nil(t, err)
|
||||
|
||||
svc, err := newTestService(ds, nil)
|
||||
assert.Nil(t, err)
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
pack := &kolide.Pack{
|
||||
Name: "foo",
|
||||
}
|
||||
_, err = ds.NewPack(pack)
|
||||
assert.Nil(t, err)
|
||||
assert.NotZero(t, pack.ID)
|
||||
|
||||
query := &kolide.Query{
|
||||
Name: "bar",
|
||||
Query: "select * from time;",
|
||||
}
|
||||
query, err = ds.NewQuery(query)
|
||||
assert.Nil(t, err)
|
||||
assert.NotZero(t, query.ID)
|
||||
|
||||
err = ds.AddQueryToPack(query.ID, pack.ID)
|
||||
assert.Nil(t, err)
|
||||
|
||||
queries, err := svc.ListQueriesInPack(ctx, pack.ID)
|
||||
assert.Nil(t, err)
|
||||
assert.Len(t, queries, 1)
|
||||
}
|
||||
|
||||
func TestRemoveQueryFromPack(t *testing.T) {
|
||||
ds, err := inmem.New(config.TestConfig())
|
||||
assert.Nil(t, err)
|
||||
|
||||
svc, err := newTestService(ds, nil)
|
||||
assert.Nil(t, err)
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
pack := &kolide.Pack{
|
||||
Name: "foo",
|
||||
}
|
||||
_, err = ds.NewPack(pack)
|
||||
assert.Nil(t, err)
|
||||
assert.NotZero(t, pack.ID)
|
||||
|
||||
query := &kolide.Query{
|
||||
Name: "bar",
|
||||
Query: "select * from time;",
|
||||
}
|
||||
query, err = ds.NewQuery(query)
|
||||
assert.Nil(t, err)
|
||||
assert.NotZero(t, query.ID)
|
||||
|
||||
err = ds.AddQueryToPack(query.ID, pack.ID)
|
||||
assert.Nil(t, err)
|
||||
|
||||
queries, err := ds.ListQueriesInPack(pack)
|
||||
assert.Nil(t, err)
|
||||
assert.Len(t, queries, 1)
|
||||
|
||||
err = svc.RemoveQueryFromPack(ctx, query.ID, pack.ID)
|
||||
assert.Nil(t, err)
|
||||
|
||||
queries, err = ds.ListQueriesInPack(pack)
|
||||
assert.Nil(t, err)
|
||||
assert.Len(t, queries, 0)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,26 +29,6 @@ func (svc service) NewQuery(ctx context.Context, p kolide.QueryPayload) (*kolide
|
|||
query.Query = *p.Query
|
||||
}
|
||||
|
||||
if p.Interval != nil {
|
||||
query.Interval = *p.Interval
|
||||
}
|
||||
|
||||
if p.Snapshot != nil {
|
||||
query.Snapshot = *p.Snapshot
|
||||
}
|
||||
|
||||
if p.Differential != nil {
|
||||
query.Differential = *p.Differential
|
||||
}
|
||||
|
||||
if p.Platform != nil {
|
||||
query.Platform = *p.Platform
|
||||
}
|
||||
|
||||
if p.Version != nil {
|
||||
query.Version = *p.Version
|
||||
}
|
||||
|
||||
vc, ok := viewer.FromContext(ctx)
|
||||
if ok {
|
||||
query.AuthorID = vc.UserID()
|
||||
|
|
@ -79,26 +59,6 @@ func (svc service) ModifyQuery(ctx context.Context, id uint, p kolide.QueryPaylo
|
|||
query.Query = *p.Query
|
||||
}
|
||||
|
||||
if p.Interval != nil {
|
||||
query.Interval = *p.Interval
|
||||
}
|
||||
|
||||
if p.Snapshot != nil {
|
||||
query.Snapshot = *p.Snapshot
|
||||
}
|
||||
|
||||
if p.Differential != nil {
|
||||
query.Differential = *p.Differential
|
||||
}
|
||||
|
||||
if p.Platform != nil {
|
||||
query.Platform = *p.Platform
|
||||
}
|
||||
|
||||
if p.Version != nil {
|
||||
query.Version = *p.Version
|
||||
}
|
||||
|
||||
err = svc.ds.SaveQuery(query)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
|
|||
26
server/service/service_scheduled_queries.go
Normal file
26
server/service/service_scheduled_queries.go
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
package service
|
||||
|
||||
import (
|
||||
"github.com/kolide/kolide-ose/server/kolide"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
func (svc service) GetScheduledQuery(ctx context.Context, id uint) (*kolide.ScheduledQuery, error) {
|
||||
return svc.ds.ScheduledQuery(id)
|
||||
}
|
||||
|
||||
func (svc service) GetScheduledQueriesInPack(ctx context.Context, id uint, opts kolide.ListOptions) ([]*kolide.ScheduledQuery, error) {
|
||||
return svc.ds.ListScheduledQueriesInPack(id, opts)
|
||||
}
|
||||
|
||||
func (svc service) ScheduleQuery(ctx context.Context, sq *kolide.ScheduledQuery) (*kolide.ScheduledQuery, error) {
|
||||
return svc.ds.NewScheduledQuery(sq)
|
||||
}
|
||||
|
||||
func (svc service) ModifyScheduledQuery(ctx context.Context, sq *kolide.ScheduledQuery) (*kolide.ScheduledQuery, error) {
|
||||
return svc.ds.SaveScheduledQuery(sq)
|
||||
}
|
||||
|
||||
func (svc service) DeleteScheduledQuery(ctx context.Context, id uint) error {
|
||||
return svc.ds.DeleteScheduledQuery(id)
|
||||
}
|
||||
104
server/service/service_scheduled_queries_test.go
Normal file
104
server/service/service_scheduled_queries_test.go
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
package service
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/kolide/kolide-ose/server/config"
|
||||
"github.com/kolide/kolide-ose/server/datastore/inmem"
|
||||
"github.com/kolide/kolide-ose/server/kolide"
|
||||
"github.com/kolide/kolide-ose/server/test"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
func TestGetScheduledQueriesInPack(t *testing.T) {
|
||||
ds, err := inmem.New(config.TestConfig())
|
||||
assert.Nil(t, err)
|
||||
svc, err := newTestService(ds, nil)
|
||||
assert.Nil(t, err)
|
||||
ctx := context.Background()
|
||||
|
||||
u1 := test.NewUser(t, ds, "Admin", "admin", "admin@kolide.co", true)
|
||||
q1 := test.NewQuery(t, ds, "foo", "select * from time;", u1.ID, true)
|
||||
q2 := test.NewQuery(t, ds, "bar", "select * from time;", u1.ID, true)
|
||||
p1 := test.NewPack(t, ds, "baz")
|
||||
sq1 := test.NewScheduledQuery(t, ds, p1.ID, q1.ID, 60, false, false)
|
||||
|
||||
queries, err := svc.GetScheduledQueriesInPack(ctx, p1.ID, kolide.ListOptions{})
|
||||
require.Nil(t, err)
|
||||
require.Len(t, queries, 1)
|
||||
assert.Equal(t, sq1.ID, queries[0].ID)
|
||||
|
||||
test.NewScheduledQuery(t, ds, p1.ID, q2.ID, 60, false, false)
|
||||
test.NewScheduledQuery(t, ds, p1.ID, q2.ID, 60, true, false)
|
||||
|
||||
queries, err = svc.GetScheduledQueriesInPack(ctx, p1.ID, kolide.ListOptions{})
|
||||
require.Nil(t, err)
|
||||
require.Len(t, queries, 3)
|
||||
}
|
||||
|
||||
func TestGetScheduledQuery(t *testing.T) {
|
||||
ds, err := inmem.New(config.TestConfig())
|
||||
assert.Nil(t, err)
|
||||
svc, err := newTestService(ds, nil)
|
||||
assert.Nil(t, err)
|
||||
ctx := context.Background()
|
||||
|
||||
u1 := test.NewUser(t, ds, "Admin", "admin", "admin@kolide.co", true)
|
||||
q1 := test.NewQuery(t, ds, "foo", "select * from time;", u1.ID, true)
|
||||
p1 := test.NewPack(t, ds, "baz")
|
||||
sq1 := test.NewScheduledQuery(t, ds, p1.ID, q1.ID, 60, false, false)
|
||||
|
||||
query, err := svc.GetScheduledQuery(ctx, sq1.ID)
|
||||
require.Nil(t, err)
|
||||
assert.Equal(t, uint(60), query.Interval)
|
||||
}
|
||||
|
||||
func TestModifyScheduledQuery(t *testing.T) {
|
||||
ds, err := inmem.New(config.TestConfig())
|
||||
assert.Nil(t, err)
|
||||
svc, err := newTestService(ds, nil)
|
||||
assert.Nil(t, err)
|
||||
ctx := context.Background()
|
||||
|
||||
u1 := test.NewUser(t, ds, "Admin", "admin", "admin@kolide.co", true)
|
||||
q1 := test.NewQuery(t, ds, "foo", "select * from time;", u1.ID, true)
|
||||
p1 := test.NewPack(t, ds, "baz")
|
||||
sq1 := test.NewScheduledQuery(t, ds, p1.ID, q1.ID, 60, false, false)
|
||||
|
||||
query, err := svc.GetScheduledQuery(ctx, sq1.ID)
|
||||
require.Nil(t, err)
|
||||
assert.Equal(t, uint(60), query.Interval)
|
||||
|
||||
query.Interval = uint(120)
|
||||
query, err = svc.ModifyScheduledQuery(ctx, query)
|
||||
assert.Equal(t, uint(120), query.Interval)
|
||||
|
||||
queryVerify, err := svc.GetScheduledQuery(ctx, sq1.ID)
|
||||
require.Nil(t, err)
|
||||
assert.Equal(t, uint(120), queryVerify.Interval)
|
||||
}
|
||||
|
||||
func TestDeleteScheduledQuery(t *testing.T) {
|
||||
ds, err := inmem.New(config.TestConfig())
|
||||
assert.Nil(t, err)
|
||||
svc, err := newTestService(ds, nil)
|
||||
assert.Nil(t, err)
|
||||
ctx := context.Background()
|
||||
|
||||
u1 := test.NewUser(t, ds, "Admin", "admin", "admin@kolide.co", true)
|
||||
q1 := test.NewQuery(t, ds, "foo", "select * from time;", u1.ID, true)
|
||||
p1 := test.NewPack(t, ds, "baz")
|
||||
sq1 := test.NewScheduledQuery(t, ds, p1.ID, q1.ID, 60, false, false)
|
||||
|
||||
query, err := svc.GetScheduledQuery(ctx, sq1.ID)
|
||||
require.Nil(t, err)
|
||||
assert.Equal(t, uint(60), query.Interval)
|
||||
|
||||
err = svc.DeleteScheduledQuery(ctx, sq1.ID)
|
||||
require.Nil(t, err)
|
||||
|
||||
_, err = svc.GetScheduledQuery(ctx, sq1.ID)
|
||||
require.NotNil(t, err)
|
||||
}
|
||||
|
|
@ -57,46 +57,6 @@ func decodeListPacksRequest(ctx context.Context, r *http.Request) (interface{},
|
|||
return listPacksRequest{ListOptions: opt}, nil
|
||||
}
|
||||
|
||||
func decodeAddQueryToPackRequest(ctx context.Context, r *http.Request) (interface{}, error) {
|
||||
qid, err := idFromRequest(r, "qid")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pid, err := idFromRequest(r, "pid")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var req addQueryToPackRequest
|
||||
req.PackID = pid
|
||||
req.QueryID = qid
|
||||
return req, nil
|
||||
}
|
||||
|
||||
func decodeGetQueriesInPackRequest(ctx context.Context, r *http.Request) (interface{}, error) {
|
||||
id, err := idFromRequest(r, "id")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var req getQueriesInPackRequest
|
||||
req.ID = id
|
||||
return req, nil
|
||||
}
|
||||
|
||||
func decodeDeleteQueryFromPackRequest(ctx context.Context, r *http.Request) (interface{}, error) {
|
||||
qid, err := idFromRequest(r, "qid")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pid, err := idFromRequest(r, "pid")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var req deleteQueryFromPackRequest
|
||||
req.PackID = pid
|
||||
req.QueryID = qid
|
||||
return req, nil
|
||||
}
|
||||
|
||||
func decodeAddLabelToPackRequest(ctx context.Context, r *http.Request) (interface{}, error) {
|
||||
lid, err := idFromRequest(r, "lid")
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -89,53 +89,3 @@ func TestDecodeGetPackRequest(t *testing.T) {
|
|||
httptest.NewRequest("GET", "/api/v1/kolide/packs/1", nil),
|
||||
)
|
||||
}
|
||||
|
||||
func TestDecodeAddQueryToPackRequest(t *testing.T) {
|
||||
router := mux.NewRouter()
|
||||
router.HandleFunc("/api/v1/kolide/packs/{pid}/queries/{qid}", func(writer http.ResponseWriter, request *http.Request) {
|
||||
r, err := decodeAddQueryToPackRequest(context.Background(), request)
|
||||
assert.Nil(t, err)
|
||||
|
||||
params := r.(addQueryToPackRequest)
|
||||
assert.Equal(t, uint(1), params.PackID)
|
||||
assert.Equal(t, uint(2), params.QueryID)
|
||||
}).Methods("GET")
|
||||
|
||||
router.ServeHTTP(
|
||||
httptest.NewRecorder(),
|
||||
httptest.NewRequest("GET", "/api/v1/kolide/packs/1/queries/2", nil),
|
||||
)
|
||||
}
|
||||
|
||||
func TestDecodeGetQueriesInPackRequest(t *testing.T) {
|
||||
router := mux.NewRouter()
|
||||
router.HandleFunc("/api/v1/kolide/packs/{id}/queries", func(writer http.ResponseWriter, request *http.Request) {
|
||||
r, err := decodeGetQueriesInPackRequest(context.Background(), request)
|
||||
assert.Nil(t, err)
|
||||
|
||||
params := r.(getQueriesInPackRequest)
|
||||
assert.Equal(t, uint(1), params.ID)
|
||||
}).Methods("GET")
|
||||
|
||||
router.ServeHTTP(
|
||||
httptest.NewRecorder(),
|
||||
httptest.NewRequest("GET", "/api/v1/kolide/packs/1/queries", nil),
|
||||
)
|
||||
}
|
||||
|
||||
func TestDecodeDeleteQueryFromPackRequest(t *testing.T) {
|
||||
router := mux.NewRouter()
|
||||
router.HandleFunc("/api/v1/kolide/packs/{pid}/queries/{qid}", func(writer http.ResponseWriter, request *http.Request) {
|
||||
r, err := decodeDeleteQueryFromPackRequest(context.Background(), request)
|
||||
assert.Nil(t, err)
|
||||
|
||||
params := r.(deleteQueryFromPackRequest)
|
||||
assert.Equal(t, uint(1), params.PackID)
|
||||
assert.Equal(t, uint(2), params.QueryID)
|
||||
}).Methods("DELETE")
|
||||
|
||||
router.ServeHTTP(
|
||||
httptest.NewRecorder(),
|
||||
httptest.NewRequest("DELETE", "/api/v1/kolide/packs/1/queries/2", nil),
|
||||
)
|
||||
}
|
||||
|
|
|
|||
63
server/service/transport_scheduled_queries.go
Normal file
63
server/service/transport_scheduled_queries.go
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
package service
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
func decodeScheduleQueriesRequest(ctx context.Context, r *http.Request) (interface{}, error) {
|
||||
var req scheduleQueriesRequest
|
||||
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return req, nil
|
||||
}
|
||||
|
||||
func decodeModifyScheduledQueryRequest(ctx context.Context, r *http.Request) (interface{}, error) {
|
||||
id, err := idFromRequest(r, "id")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var req modifyScheduledQueryRequest
|
||||
|
||||
if err := json.NewDecoder(r.Body).Decode(&req.payload); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req.ID = id
|
||||
return req, nil
|
||||
}
|
||||
|
||||
func decodeDeleteScheduledQueryRequest(ctx context.Context, r *http.Request) (interface{}, error) {
|
||||
id, err := idFromRequest(r, "id")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var req deleteScheduledQueryRequest
|
||||
req.ID = id
|
||||
return req, nil
|
||||
}
|
||||
|
||||
func decodeGetScheduledQueryRequest(ctx context.Context, r *http.Request) (interface{}, error) {
|
||||
id, err := idFromRequest(r, "id")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var req getScheduledQueryRequest
|
||||
req.ID = id
|
||||
return req, nil
|
||||
}
|
||||
|
||||
func decodeGetScheduledQueriesInPackRequest(ctx context.Context, r *http.Request) (interface{}, error) {
|
||||
id, err := idFromRequest(r, "id")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var req getScheduledQueriesInPackRequest
|
||||
req.ID = id
|
||||
return req, nil
|
||||
}
|
||||
156
server/service/transport_scheduled_queries_test.go
Normal file
156
server/service/transport_scheduled_queries_test.go
Normal file
|
|
@ -0,0 +1,156 @@
|
|||
package service
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
func TestDecodeScheduleQueriesRequest(t *testing.T) {
|
||||
router := mux.NewRouter()
|
||||
router.HandleFunc("/api/v1/kolide/schedule", func(writer http.ResponseWriter, request *http.Request) {
|
||||
r, err := decodeScheduleQueriesRequest(context.Background(), request)
|
||||
require.Nil(t, err)
|
||||
|
||||
params := r.(scheduleQueriesRequest)
|
||||
require.Len(t, params.Options, 2)
|
||||
|
||||
accessed := struct {
|
||||
Five bool
|
||||
Six bool
|
||||
}{}
|
||||
|
||||
for _, q := range params.Options {
|
||||
switch q.PackID {
|
||||
case uint(5):
|
||||
accessed.Five = true
|
||||
assert.Equal(t, uint(60), q.Interval)
|
||||
assert.Equal(t, true, *q.Snapshot)
|
||||
assert.Nil(t, q.Removed)
|
||||
assert.Len(t, q.QueryIDs, 1)
|
||||
assert.Equal(t, q.QueryIDs[0], uint(1))
|
||||
case uint(6):
|
||||
accessed.Six = true
|
||||
assert.Equal(t, uint(120), q.Interval)
|
||||
assert.Nil(t, q.Removed)
|
||||
assert.Nil(t, q.Snapshot)
|
||||
assert.Len(t, q.QueryIDs, 3)
|
||||
default:
|
||||
t.Errorf("Found an unexpected pack_id: %d", q.PackID)
|
||||
}
|
||||
}
|
||||
|
||||
if !accessed.Five {
|
||||
t.Error("Create scheduled query for pack 5 not read")
|
||||
}
|
||||
|
||||
if !accessed.Six {
|
||||
t.Error("Create scheduled query for pack 6 not read")
|
||||
}
|
||||
|
||||
}).Methods("POST")
|
||||
|
||||
var body bytes.Buffer
|
||||
body.Write([]byte(`{
|
||||
"options": [{
|
||||
"pack_id": 5,
|
||||
"interval": 60,
|
||||
"snapshot": true,
|
||||
"query_ids": [1]
|
||||
},{
|
||||
"pack_id": 6,
|
||||
"interval": 120,
|
||||
"query_ids": [1, 2, 3]
|
||||
}]
|
||||
}`))
|
||||
|
||||
router.ServeHTTP(
|
||||
httptest.NewRecorder(),
|
||||
httptest.NewRequest("POST", "/api/v1/kolide/schedule", &body),
|
||||
)
|
||||
}
|
||||
|
||||
func TestDecodeModifyScheduledQueryRequest(t *testing.T) {
|
||||
router := mux.NewRouter()
|
||||
router.HandleFunc("/api/v1/kolide/scheduled/{id}", func(writer http.ResponseWriter, request *http.Request) {
|
||||
r, err := decodeModifyScheduledQueryRequest(context.Background(), request)
|
||||
assert.Nil(t, err)
|
||||
|
||||
params := r.(modifyScheduledQueryRequest)
|
||||
assert.Equal(t, uint(1), params.ID)
|
||||
assert.Equal(t, uint(5), params.payload.PackID)
|
||||
assert.Equal(t, uint(6), params.payload.QueryID)
|
||||
assert.Equal(t, true, *params.payload.Removed)
|
||||
assert.Equal(t, uint(60), params.payload.Interval)
|
||||
assert.Equal(t, uint(1), *params.payload.Shard)
|
||||
}).Methods("PATCH")
|
||||
|
||||
var body bytes.Buffer
|
||||
body.Write([]byte(`{
|
||||
"pack_id": 5,
|
||||
"query_id": 6,
|
||||
"removed": true,
|
||||
"interval": 60,
|
||||
"shard": 1
|
||||
}`))
|
||||
|
||||
router.ServeHTTP(
|
||||
httptest.NewRecorder(),
|
||||
httptest.NewRequest("PATCH", "/api/v1/kolide/scheduled/1", &body),
|
||||
)
|
||||
}
|
||||
|
||||
func TestDecodeDeleteScheduledQueryRequest(t *testing.T) {
|
||||
router := mux.NewRouter()
|
||||
router.HandleFunc("/api/v1/kolide/scheduled/{id}", func(writer http.ResponseWriter, request *http.Request) {
|
||||
r, err := decodeDeleteScheduledQueryRequest(context.Background(), request)
|
||||
assert.Nil(t, err)
|
||||
|
||||
params := r.(deleteScheduledQueryRequest)
|
||||
assert.Equal(t, uint(1), params.ID)
|
||||
}).Methods("DELETE")
|
||||
|
||||
router.ServeHTTP(
|
||||
httptest.NewRecorder(),
|
||||
httptest.NewRequest("DELETE", "/api/v1/kolide/scheduled/1", nil),
|
||||
)
|
||||
}
|
||||
|
||||
func TestDecodeGetScheduledQueryRequest(t *testing.T) {
|
||||
router := mux.NewRouter()
|
||||
router.HandleFunc("/api/v1/kolide/scheduled/{id}", func(writer http.ResponseWriter, request *http.Request) {
|
||||
r, err := decodeGetScheduledQueryRequest(context.Background(), request)
|
||||
assert.Nil(t, err)
|
||||
|
||||
params := r.(getScheduledQueryRequest)
|
||||
assert.Equal(t, uint(1), params.ID)
|
||||
}).Methods("GET")
|
||||
|
||||
router.ServeHTTP(
|
||||
httptest.NewRecorder(),
|
||||
httptest.NewRequest("GET", "/api/v1/kolide/scheduled/1", nil),
|
||||
)
|
||||
}
|
||||
|
||||
func TestDecodeGetScheduledQueriesInPackRequest(t *testing.T) {
|
||||
router := mux.NewRouter()
|
||||
router.HandleFunc("/api/v1/kolide/packs/{id}/scheduled", func(writer http.ResponseWriter, request *http.Request) {
|
||||
r, err := decodeGetScheduledQueriesInPackRequest(context.Background(), request)
|
||||
assert.Nil(t, err)
|
||||
|
||||
params := r.(getScheduledQueriesInPackRequest)
|
||||
assert.Equal(t, uint(1), params.ID)
|
||||
}).Methods("GET")
|
||||
|
||||
router.ServeHTTP(
|
||||
httptest.NewRecorder(),
|
||||
httptest.NewRequest("GET", "/api/v1/kolide/packs/1/scheduled", nil),
|
||||
)
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package datastore
|
||||
package test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
|
@ -8,7 +8,7 @@ import (
|
|||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func newQuery(t *testing.T, ds kolide.Datastore, name, q string, authorID uint, saved bool) *kolide.Query {
|
||||
func NewQuery(t *testing.T, ds kolide.Datastore, name, q string, authorID uint, saved bool) *kolide.Query {
|
||||
query, err := ds.NewQuery(&kolide.Query{
|
||||
Name: name,
|
||||
Query: q,
|
||||
|
|
@ -24,7 +24,7 @@ func newQuery(t *testing.T, ds kolide.Datastore, name, q string, authorID uint,
|
|||
return query
|
||||
}
|
||||
|
||||
func newPack(t *testing.T, ds kolide.Datastore, name string) *kolide.Pack {
|
||||
func NewPack(t *testing.T, ds kolide.Datastore, name string) *kolide.Pack {
|
||||
pack, err := ds.NewPack(&kolide.Pack{
|
||||
Name: name,
|
||||
})
|
||||
|
|
@ -37,12 +37,7 @@ func newPack(t *testing.T, ds kolide.Datastore, name string) *kolide.Pack {
|
|||
return pack
|
||||
}
|
||||
|
||||
func addQueryToPack(t *testing.T, ds kolide.Datastore, queryID, packID uint) {
|
||||
err := ds.AddQueryToPack(queryID, packID)
|
||||
require.Nil(t, err)
|
||||
}
|
||||
|
||||
func newCampaign(t *testing.T, ds kolide.Datastore, queryID uint, status kolide.DistributedQueryStatus, now time.Time) *kolide.DistributedQueryCampaign {
|
||||
func NewCampaign(t *testing.T, ds kolide.Datastore, queryID uint, status kolide.DistributedQueryStatus, now time.Time) *kolide.DistributedQueryCampaign {
|
||||
campaign, err := ds.NewDistributedQueryCampaign(&kolide.DistributedQueryCampaign{
|
||||
UpdateCreateTimestamps: kolide.UpdateCreateTimestamps{
|
||||
CreateTimestamp: kolide.CreateTimestamp{
|
||||
|
|
@ -61,7 +56,7 @@ func newCampaign(t *testing.T, ds kolide.Datastore, queryID uint, status kolide.
|
|||
return campaign
|
||||
}
|
||||
|
||||
func addHostToCampaign(t *testing.T, ds kolide.Datastore, campaignID, hostID uint) {
|
||||
func AddHostToCampaign(t *testing.T, ds kolide.Datastore, campaignID, hostID uint) {
|
||||
_, err := ds.NewDistributedQueryCampaignTarget(
|
||||
&kolide.DistributedQueryCampaignTarget{
|
||||
Type: kolide.TargetHost,
|
||||
|
|
@ -71,7 +66,7 @@ func addHostToCampaign(t *testing.T, ds kolide.Datastore, campaignID, hostID uin
|
|||
require.Nil(t, err)
|
||||
}
|
||||
|
||||
func addLabelToCampaign(t *testing.T, ds kolide.Datastore, campaignID, labelID uint) {
|
||||
func AddLabelToCampaign(t *testing.T, ds kolide.Datastore, campaignID, labelID uint) {
|
||||
_, err := ds.NewDistributedQueryCampaignTarget(
|
||||
&kolide.DistributedQueryCampaignTarget{
|
||||
Type: kolide.TargetLabel,
|
||||
|
|
@ -81,7 +76,7 @@ func addLabelToCampaign(t *testing.T, ds kolide.Datastore, campaignID, labelID u
|
|||
require.Nil(t, err)
|
||||
}
|
||||
|
||||
func newExecution(t *testing.T, ds kolide.Datastore, campaignID uint, hostID uint) *kolide.DistributedQueryExecution {
|
||||
func NewExecution(t *testing.T, ds kolide.Datastore, campaignID uint, hostID uint) *kolide.DistributedQueryExecution {
|
||||
execution, err := ds.NewDistributedQueryExecution(&kolide.DistributedQueryExecution{
|
||||
HostID: hostID,
|
||||
DistributedQueryCampaignID: campaignID,
|
||||
|
|
@ -91,7 +86,7 @@ func newExecution(t *testing.T, ds kolide.Datastore, campaignID uint, hostID uin
|
|||
return execution
|
||||
}
|
||||
|
||||
func newHost(t *testing.T, ds kolide.Datastore, name, ip, key, uuid string, now time.Time) *kolide.Host {
|
||||
func NewHost(t *testing.T, ds kolide.Datastore, name, ip, key, uuid string, now time.Time) *kolide.Host {
|
||||
osqueryHostID, _ := kolide.RandomText(10)
|
||||
h, err := ds.NewHost(&kolide.Host{
|
||||
HostName: name,
|
||||
|
|
@ -108,7 +103,7 @@ func newHost(t *testing.T, ds kolide.Datastore, name, ip, key, uuid string, now
|
|||
return h
|
||||
}
|
||||
|
||||
func newLabel(t *testing.T, ds kolide.Datastore, name, query string) *kolide.Label {
|
||||
func NewLabel(t *testing.T, ds kolide.Datastore, name, query string) *kolide.Label {
|
||||
l, err := ds.NewLabel(&kolide.Label{Name: name, Query: query})
|
||||
|
||||
require.Nil(t, err)
|
||||
|
|
@ -117,7 +112,7 @@ func newLabel(t *testing.T, ds kolide.Datastore, name, query string) *kolide.Lab
|
|||
return l
|
||||
}
|
||||
|
||||
func newUser(t *testing.T, ds kolide.Datastore, name, username, email string, admin bool) *kolide.User {
|
||||
func NewUser(t *testing.T, ds kolide.Datastore, name, username, email string, admin bool) *kolide.User {
|
||||
u, err := ds.NewUser(&kolide.User{
|
||||
Password: []byte("garbage"),
|
||||
Salt: "garbage",
|
||||
|
|
@ -132,3 +127,17 @@ func newUser(t *testing.T, ds kolide.Datastore, name, username, email string, ad
|
|||
|
||||
return u
|
||||
}
|
||||
|
||||
func NewScheduledQuery(t *testing.T, ds kolide.Datastore, pid, qid, interval uint, snapshot, removed bool) *kolide.ScheduledQuery {
|
||||
sq, err := ds.NewScheduledQuery(&kolide.ScheduledQuery{
|
||||
PackID: pid,
|
||||
QueryID: qid,
|
||||
Interval: interval,
|
||||
Snapshot: &snapshot,
|
||||
Removed: &removed,
|
||||
})
|
||||
require.Nil(t, err)
|
||||
require.NotZero(t, sq.ID)
|
||||
|
||||
return sq
|
||||
}
|
||||
Loading…
Reference in a new issue