2016-12-13 22:22:05 +00:00
package mysql
import (
2021-09-14 12:11:07 +00:00
"context"
2018-06-15 14:13:11 +00:00
"database/sql"
2021-07-16 13:15:15 +00:00
"github.com/jmoiron/sqlx"
2021-06-26 04:46:51 +00:00
"github.com/fleetdm/fleet/v4/server/fleet"
2016-12-22 19:29:29 +00:00
"github.com/pkg/errors"
2016-12-13 22:22:05 +00:00
)
2021-09-14 12:11:07 +00:00
func ( d * Datastore ) ListScheduledQueriesInPack ( ctx context . Context , id uint , opts fleet . ListOptions ) ( [ ] * fleet . ScheduledQuery , error ) {
2016-12-22 19:29:29 +00:00
query := `
2018-01-03 19:18:05 +00:00
SELECT
2018-01-10 19:38:20 +00:00
sq . id ,
sq . pack_id ,
2018-06-22 00:06:44 +00:00
sq . name ,
2018-01-10 19:38:20 +00:00
sq . query_name ,
2018-06-22 00:06:44 +00:00
sq . description ,
2018-01-10 19:38:20 +00:00
sq . interval ,
sq . snapshot ,
sq . removed ,
2018-06-22 00:06:44 +00:00
sq . platform ,
2018-01-10 19:38:20 +00:00
sq . version ,
sq . shard ,
2021-01-26 00:26:14 +00:00
sq . denylist ,
2018-01-10 19:38:20 +00:00
q . query ,
2021-10-20 21:35:38 +00:00
q . id AS query_id ,
JSON_EXTRACT ( json_value , "$.user_time_p50" ) as user_time_p50 ,
JSON_EXTRACT ( json_value , "$.user_time_p95" ) as user_time_p95 ,
JSON_EXTRACT ( json_value , "$.system_time_p50" ) as system_time_p50 ,
2021-10-22 20:05:49 +00:00
JSON_EXTRACT ( json_value , "$.system_time_p95" ) as system_time_p95 ,
JSON_EXTRACT ( json_value , "$.total_executions" ) as total_executions
2016-12-13 22:22:05 +00:00
FROM scheduled_queries sq
2021-10-20 21:35:38 +00:00
JOIN queries q ON ( sq . query_name = q . name )
LEFT JOIN aggregated_stats ag ON ( ag . id = sq . id AND ag . type = "scheduled_query" )
2016-12-13 22:22:05 +00:00
WHERE sq . pack_id = ?
`
2016-12-22 19:29:29 +00:00
query = appendListOptionsToSQL ( query , opts )
2021-06-06 22:07:29 +00:00
results := [ ] * fleet . ScheduledQuery { }
2016-12-13 22:22:05 +00:00
2021-09-14 14:44:02 +00:00
if err := sqlx . SelectContext ( ctx , d . reader , & results , query , id ) ; err != nil {
2016-12-22 19:29:29 +00:00
return nil , errors . Wrap ( err , "listing scheduled queries" )
2016-12-13 22:22:05 +00:00
}
return results , nil
}
2018-06-15 14:13:11 +00:00
2021-09-14 12:11:07 +00:00
func ( d * Datastore ) NewScheduledQuery ( ctx context . Context , sq * fleet . ScheduledQuery , opts ... fleet . OptionalArg ) ( * fleet . ScheduledQuery , error ) {
2021-09-14 14:44:02 +00:00
return insertScheduledQueryDB ( ctx , d . writer , sq )
2021-07-16 13:15:15 +00:00
}
2021-09-14 14:44:02 +00:00
func insertScheduledQueryDB ( ctx context . Context , q sqlx . ExtContext , sq * fleet . ScheduledQuery ) ( * fleet . ScheduledQuery , error ) {
2018-06-15 14:13:11 +00:00
// This query looks up the query name using the ID (for backwards
// compatibility with the UI)
query := `
INSERT INTO scheduled_queries (
query_name ,
2021-08-03 13:33:27 +00:00
query_id ,
2018-06-22 00:06:44 +00:00
name ,
2018-06-15 14:13:11 +00:00
pack_id ,
snapshot ,
removed ,
` + " ` interval ` " + ` ,
platform ,
version ,
2021-01-26 00:26:14 +00:00
shard ,
denylist
2018-06-15 14:13:11 +00:00
)
2021-08-03 13:33:27 +00:00
SELECT name , ? , ? , ? , ? , ? , ? , ? , ? , ? , ?
2018-06-15 14:13:11 +00:00
FROM queries
WHERE id = ?
`
2021-09-14 14:44:02 +00:00
result , err := q . ExecContext ( ctx , query , sq . QueryID , sq . Name , sq . PackID , sq . Snapshot , sq . Removed , sq . Interval , sq . Platform , sq . Version , sq . Shard , sq . Denylist , sq . QueryID )
2018-06-15 14:13:11 +00:00
if err != nil {
2021-01-26 00:26:14 +00:00
return nil , errors . Wrap ( err , "insert scheduled query" )
2018-06-15 14:13:11 +00:00
}
id , _ := result . LastInsertId ( )
sq . ID = uint ( id )
query = ` SELECT query, name FROM queries WHERE id = ? LIMIT 1 `
metadata := [ ] struct {
Query string
Name string
} { }
2021-09-14 14:44:02 +00:00
err = sqlx . SelectContext ( ctx , q , & metadata , query , sq . QueryID )
2018-06-15 14:13:11 +00:00
if err != nil && err == sql . ErrNoRows {
return nil , notFound ( "Query" ) . WithID ( sq . QueryID )
} else if err != nil {
return nil , errors . Wrap ( err , "select query by ID" )
}
if len ( metadata ) != 1 {
return nil , errors . Wrap ( err , "wrong number of results returned from database" )
}
sq . Query = metadata [ 0 ] . Query
2021-05-07 04:05:09 +00:00
sq . QueryName = metadata [ 0 ] . Name
2018-06-15 14:13:11 +00:00
return sq , nil
}
2021-09-14 12:11:07 +00:00
func ( d * Datastore ) SaveScheduledQuery ( ctx context . Context , sq * fleet . ScheduledQuery ) ( * fleet . ScheduledQuery , error ) {
2021-09-14 14:44:02 +00:00
return saveScheduledQueryDB ( ctx , d . writer , sq )
2021-07-16 13:15:15 +00:00
}
2021-09-14 14:44:02 +00:00
func saveScheduledQueryDB ( ctx context . Context , exec sqlx . ExecerContext , sq * fleet . ScheduledQuery ) ( * fleet . ScheduledQuery , error ) {
2018-06-15 14:13:11 +00:00
query := `
UPDATE scheduled_queries
2021-01-26 00:26:14 +00:00
SET pack_id = ? , query_id = ? , ` + " ` interval ` " + ` = ? , snapshot = ? , removed = ? , platform = ? , version = ? , shard = ? , denylist = ?
2020-10-22 17:51:26 +00:00
WHERE id = ?
2018-06-15 14:13:11 +00:00
`
2021-09-14 14:44:02 +00:00
result , err := exec . ExecContext ( ctx , query , sq . PackID , sq . QueryID , sq . Interval , sq . Snapshot , sq . Removed , sq . Platform , sq . Version , sq . Shard , sq . Denylist , sq . ID )
2018-06-15 14:13:11 +00:00
if err != nil {
return nil , errors . Wrap ( err , "saving a scheduled query" )
}
rows , err := result . RowsAffected ( )
if err != nil {
return nil , errors . Wrap ( err , "rows affected saving a scheduled query" )
}
if rows == 0 {
return nil , notFound ( "ScheduledQueries" ) . WithID ( sq . ID )
}
return sq , nil
}
2021-09-14 12:11:07 +00:00
func ( d * Datastore ) DeleteScheduledQuery ( ctx context . Context , id uint ) error {
2021-09-20 17:47:06 +00:00
return d . deleteEntity ( ctx , scheduledQueriesTable , id )
2018-06-15 14:13:11 +00:00
}
2021-09-14 12:11:07 +00:00
func ( d * Datastore ) ScheduledQuery ( ctx context . Context , id uint ) ( * fleet . ScheduledQuery , error ) {
2018-06-15 14:13:11 +00:00
query := `
SELECT
sq . id ,
sq . created_at ,
sq . updated_at ,
sq . pack_id ,
sq . interval ,
sq . snapshot ,
sq . removed ,
sq . platform ,
sq . version ,
sq . shard ,
sq . query_name ,
2018-06-22 00:06:44 +00:00
sq . description ,
2021-01-26 00:26:14 +00:00
sq . denylist ,
2018-06-15 14:13:11 +00:00
q . query ,
q . name ,
q . id AS query_id
FROM scheduled_queries sq
JOIN queries q
ON sq . query_name = q . name
WHERE sq . id = ?
`
2021-06-06 22:07:29 +00:00
sq := & fleet . ScheduledQuery { }
2021-09-14 14:44:02 +00:00
if err := sqlx . GetContext ( ctx , d . reader , sq , query , id ) ; err != nil {
2021-01-26 00:26:14 +00:00
return nil , errors . Wrap ( err , "select scheduled query" )
2018-06-15 14:13:11 +00:00
}
return sq , nil
}
2021-08-18 21:30:48 +00:00
2021-09-14 12:11:07 +00:00
func ( d * Datastore ) CleanupOrphanScheduledQueryStats ( ctx context . Context ) error {
2021-09-14 14:44:02 +00:00
_ , err := d . writer . ExecContext ( ctx , ` DELETE FROM scheduled_query_stats where scheduled_query_id not in (select id from scheduled_queries where id=scheduled_query_id) ` )
2021-08-18 21:30:48 +00:00
if err != nil {
return errors . Wrap ( err , "cleaning orphan scheduled_query_stats by scheduled_query" )
}
2021-09-14 14:44:02 +00:00
_ , err = d . writer . ExecContext ( ctx , ` DELETE FROM scheduled_query_stats where host_id not in (select id from hosts where id=host_id) ` )
2021-08-18 21:30:48 +00:00
if err != nil {
return errors . Wrap ( err , "cleaning orphan scheduled_query_stats by host" )
}
return nil
}