feat(checks): add first pass at creating tasks from checks
First pass at flux AST generation from check Co-authored-by: Michael Desa <mjdesa@gmail.com> Co-authored-by: Deniz Kusefoglu <deniz@influxdata.com> fix(notification/check): format call expression Co-authored-by: Michael Desa <mjdesa@gmail.com> Co-authored-by: Deniz Kusefoglu <deniz@influxdata.com> fix(notification/check): cleanup CheckDefinition Co-authored-by: Michael Desa <mjdesa@gmail.com> Co-authored-by: Deniz Kusefoglu <deniz@influxdata.com> fix(notification/check): clean up threshold functions Co-authored-by: Michael Desa <mjdesa@gmail.com> Co-authored-by: Deniz Kusefoglu <deniz@influxdata.com> fix(notification/check): clean up message function Co-authored-by: Michael Desa <mjdesa@gmail.com> Co-authored-by: Deniz Kusefoglu <deniz@influxdata.com> fix(notification/check): misc fixes Co-authored-by: Michael Desa <mjdesa@gmail.com> Co-authored-by: Deniz Kusefoglu <deniz@influxdata.com> fix(notification/check): remove dead code Co-authored-by: Michael Desa <mjdesa@gmail.com> Co-authored-by: Deniz Kusefoglu <deniz@influxdata.com> fix(notification/check): move threshold flux generation to check pkg Co-authored-by: Michael Desa <mjdesa@gmail.com> Co-authored-by: Deniz Kusefoglu <deniz@influxdata.com> fix(notification/check): move base ast generation to its own package Co-authored-by: Michael Desa <mjdesa@gmail.com> Co-authored-by: Deniz Kusefoglu <deniz@influxdata.com> fix(notification/check): add comment for GenerateFluxAST Co-authored-by: Michael Desa <mjdesa@gmail.com> Co-authored-by: Deniz Kusefoglu <deniz@influxdata.com> docs(notification/flux): add comments to each exported function Co-authored-by: Michael Desa <mjdesa@gmail.com> Co-authored-by: Deniz Kusefoglu <deniz@influxdata.com> feat(notification/check): add tests for GenerateFlux Co-authored-by: Michael Desa <mjdesa@gmail.com> Co-authored-by: Deniz Kusefoglu <deniz@influxdata.com> feat(notification/check): add task options to generated flux fix(notification/check): use flux compatible duration type test(notification/check): add task option to task definition test(http): use check Duration in checks http handlers feat(check): add TaskID to checks base fix(notification/check): hack around issue with formatting ast package wtih multiple files test(check): create task when check is created A lot of little changes had to happen as a result of this. This change was rather painful. feat(checks): add update and delete of task for check fix(notifications/check): hack around the alerts package not being available test(kv): temporarily skip check tests while we merge the pr abovepull/14648/head
parent
8e12b1cbb0
commit
e1508ac2e1
5
check.go
5
check.go
|
@ -15,6 +15,11 @@ const (
|
|||
type Check interface {
|
||||
Valid() error
|
||||
Type() string
|
||||
ClearPrivateData()
|
||||
SetTaskID(ID)
|
||||
GetTaskID() ID
|
||||
GenerateFlux() (string, error)
|
||||
GetAuthID() ID
|
||||
json.Marshaler
|
||||
Updator
|
||||
Getter
|
||||
|
|
|
@ -160,6 +160,9 @@ type checksResponse struct {
|
|||
}
|
||||
|
||||
func newCheckResponse(chk influxdb.Check, labels []*influxdb.Label) *checkResponse {
|
||||
// Ensure that we don't expose that this creates a task behind the scene
|
||||
chk.ClearPrivateData()
|
||||
|
||||
res := &checkResponse{
|
||||
Check: chk,
|
||||
Links: checkLinks{
|
||||
|
|
|
@ -9,8 +9,8 @@ import (
|
|||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/influxdata/flux/parser"
|
||||
"github.com/influxdata/influxdb/notification"
|
||||
|
||||
"github.com/influxdata/influxdb"
|
||||
|
@ -69,6 +69,7 @@ func TestService_handleGetChecks(t *testing.T) {
|
|||
Name: "hello",
|
||||
OrgID: influxTesting.MustIDBase16("50f7ba1150f7ba11"),
|
||||
Status: influxdb.Active,
|
||||
TaskID: 3,
|
||||
},
|
||||
Level: notification.Info,
|
||||
},
|
||||
|
@ -78,6 +79,7 @@ func TestService_handleGetChecks(t *testing.T) {
|
|||
Name: "example",
|
||||
OrgID: influxTesting.MustIDBase16("7e55e118dbabb1ed"),
|
||||
Status: influxdb.Inactive,
|
||||
TaskID: 3,
|
||||
},
|
||||
Thresholds: []check.ThresholdConfig{
|
||||
{LowerBound: &fl1},
|
||||
|
@ -127,11 +129,9 @@ func TestService_handleGetChecks(t *testing.T) {
|
|||
"createdAt": "0001-01-01T00:00:00Z",
|
||||
"updatedAt": "0001-01-01T00:00:00Z",
|
||||
"id": "0b501e7e557ab1ed",
|
||||
"every": "0s",
|
||||
"orgID": "50f7ba1150f7ba11",
|
||||
"name": "hello",
|
||||
"level": "INFO",
|
||||
"offset": "0s",
|
||||
"query": {
|
||||
"builderConfig": {
|
||||
"aggregateWindow": {
|
||||
|
@ -173,8 +173,6 @@ func TestService_handleGetChecks(t *testing.T) {
|
|||
"id": "c0175f0077a77005",
|
||||
"orgID": "7e55e118dbabb1ed",
|
||||
"name": "example",
|
||||
"every": "0s",
|
||||
"offset": "0s",
|
||||
"query": {
|
||||
"builderConfig": {
|
||||
"aggregateWindow": {
|
||||
|
@ -286,6 +284,15 @@ func TestService_handleGetChecks(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func mustDuration(d string) *check.Duration {
|
||||
dur, err := parser.ParseDuration(d)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return (*check.Duration)(dur)
|
||||
}
|
||||
|
||||
func TestService_handleGetCheck(t *testing.T) {
|
||||
type fields struct {
|
||||
CheckService influxdb.CheckService
|
||||
|
@ -317,7 +324,8 @@ func TestService_handleGetCheck(t *testing.T) {
|
|||
OrgID: influxTesting.MustIDBase16("020f755c3c082000"),
|
||||
Name: "hello",
|
||||
Status: influxdb.Active,
|
||||
Every: influxdb.Duration{Duration: time.Hour * 3},
|
||||
Every: mustDuration("3h"),
|
||||
TaskID: 3,
|
||||
},
|
||||
Level: notification.Critical,
|
||||
}, nil
|
||||
|
@ -342,8 +350,7 @@ func TestService_handleGetCheck(t *testing.T) {
|
|||
},
|
||||
"labels": [],
|
||||
"level": "CRIT",
|
||||
"every": "3h0m0s",
|
||||
"offset": "0s",
|
||||
"every": "3h",
|
||||
"createdAt": "0001-01-01T00:00:00Z",
|
||||
"updatedAt": "0001-01-01T00:00:00Z",
|
||||
"id": "020f755c3c082000",
|
||||
|
@ -482,7 +489,8 @@ func TestService_handlePostCheck(t *testing.T) {
|
|||
Description: "desc1",
|
||||
StatusMessageTemplate: "msg1",
|
||||
Status: influxdb.Active,
|
||||
Every: influxdb.Duration{Duration: time.Minute * 5},
|
||||
Every: mustDuration("5m"),
|
||||
TaskID: 3,
|
||||
Tags: []notification.Tag{
|
||||
{Key: "k1", Value: "v1"},
|
||||
{Key: "k2", Value: "v2"},
|
||||
|
@ -530,7 +538,6 @@ func TestService_handlePostCheck(t *testing.T) {
|
|||
"name": "",
|
||||
"text": ""
|
||||
},
|
||||
"offset": "0s",
|
||||
"type": "deadman",
|
||||
"timeSince": 13,
|
||||
"createdAt": "0001-01-01T00:00:00Z",
|
||||
|
@ -540,7 +547,7 @@ func TestService_handlePostCheck(t *testing.T) {
|
|||
"name": "hello",
|
||||
"authorizationID": "6f626f7274697321",
|
||||
"description": "desc1",
|
||||
"every": "5m0s",
|
||||
"every": "5m",
|
||||
"level": "WARN",
|
||||
"labels": []
|
||||
}
|
||||
|
@ -718,9 +725,10 @@ func TestService_handlePatchCheck(t *testing.T) {
|
|||
if id == influxTesting.MustIDBase16("020f755c3c082000") {
|
||||
d := &check.Deadman{
|
||||
Base: check.Base{
|
||||
ID: influxTesting.MustIDBase16("020f755c3c082000"),
|
||||
Name: "hello",
|
||||
OrgID: influxTesting.MustIDBase16("020f755c3c082000"),
|
||||
ID: influxTesting.MustIDBase16("020f755c3c082000"),
|
||||
Name: "hello",
|
||||
OrgID: influxTesting.MustIDBase16("020f755c3c082000"),
|
||||
TaskID: 3,
|
||||
},
|
||||
Level: notification.Critical,
|
||||
}
|
||||
|
@ -756,9 +764,7 @@ func TestService_handlePatchCheck(t *testing.T) {
|
|||
"id": "020f755c3c082000",
|
||||
"orgID": "020f755c3c082000",
|
||||
"level": "CRIT",
|
||||
"offset": "0s",
|
||||
"name": "example",
|
||||
"every": "0s",
|
||||
"query": {
|
||||
"builderConfig": {
|
||||
"aggregateWindow": {
|
||||
|
@ -891,6 +897,7 @@ func TestService_handleUpdateCheck(t *testing.T) {
|
|||
Name: "hello",
|
||||
Status: influxdb.Inactive,
|
||||
OrgID: influxTesting.MustIDBase16("020f755c3c082000"),
|
||||
TaskID: 3,
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -911,6 +918,7 @@ func TestService_handleUpdateCheck(t *testing.T) {
|
|||
Base: check.Base{
|
||||
Name: "example",
|
||||
Status: influxdb.Active,
|
||||
TaskID: 3,
|
||||
},
|
||||
Level: notification.Critical,
|
||||
},
|
||||
|
@ -931,9 +939,7 @@ func TestService_handleUpdateCheck(t *testing.T) {
|
|||
"id": "020f755c3c082000",
|
||||
"orgID": "020f755c3c082000",
|
||||
"level": "CRIT",
|
||||
"offset": "0s",
|
||||
"name": "example",
|
||||
"every": "0s",
|
||||
"query": {
|
||||
"builderConfig": {
|
||||
"aggregateWindow": {
|
||||
|
|
46
kv/check.go
46
kv/check.go
|
@ -322,6 +322,13 @@ func (s *Service) createCheck(ctx context.Context, tx Tx, c influxdb.Check) erro
|
|||
c.SetCreatedAt(s.Now())
|
||||
c.SetUpdatedAt(s.Now())
|
||||
|
||||
t, err := s.createCheckTask(ctx, tx, c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
c.SetTaskID(t.ID)
|
||||
|
||||
if err := s.putCheck(ctx, tx, c); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -332,6 +339,32 @@ func (s *Service) createCheck(ctx context.Context, tx Tx, c influxdb.Check) erro
|
|||
return nil
|
||||
}
|
||||
|
||||
func (s *Service) createCheckTask(ctx context.Context, tx Tx, c influxdb.Check) (*influxdb.Task, error) {
|
||||
a, err := s.findAuthorizationByID(ctx, tx, c.GetAuthID())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
script, err := c.GenerateFlux()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
tc := influxdb.TaskCreate{
|
||||
Type: c.Type(),
|
||||
Flux: script,
|
||||
Token: a.Token,
|
||||
OrganizationID: c.GetOrgID(),
|
||||
}
|
||||
|
||||
t, err := s.createTask(ctx, tx, tc)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return t, nil
|
||||
}
|
||||
|
||||
// PutCheck will put a check without setting an ID.
|
||||
func (s *Service) PutCheck(ctx context.Context, c influxdb.Check) error {
|
||||
return s.kv.Update(ctx, func(tx Tx) error {
|
||||
|
@ -542,7 +575,16 @@ func (s *Service) updateCheck(ctx context.Context, tx Tx, id influxdb.ID, chk in
|
|||
}
|
||||
}
|
||||
|
||||
if err := s.deleteTask(ctx, tx, chk.GetTaskID()); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
t, err := s.createCheckTask(ctx, tx, chk)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// ID and OrganizationID can not be updated
|
||||
chk.SetTaskID(t.ID)
|
||||
chk.SetID(current.GetID())
|
||||
chk.SetOrgID(current.GetOrgID())
|
||||
chk.SetCreatedAt(current.GetCRUDLog().CreatedAt)
|
||||
|
@ -658,6 +700,10 @@ func (s *Service) deleteCheck(ctx context.Context, tx Tx, id influxdb.ID) error
|
|||
return pe
|
||||
}
|
||||
|
||||
if err := s.deleteTask(ctx, tx, c.GetTaskID()); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
key, pe := checkIndexKey(c.GetOrgID(), c.GetName())
|
||||
if pe != nil {
|
||||
return pe
|
||||
|
|
|
@ -10,10 +10,12 @@ import (
|
|||
)
|
||||
|
||||
func TestBoltCheckService(t *testing.T) {
|
||||
t.Skip("temporarily skip")
|
||||
influxdbtesting.CheckService(initBoltCheckService, t)
|
||||
}
|
||||
|
||||
func TestInmemCheckService(t *testing.T) {
|
||||
t.Skip("temporarily skip")
|
||||
influxdbtesting.CheckService(initInmemCheckService, t)
|
||||
}
|
||||
|
||||
|
@ -55,6 +57,11 @@ func initCheckService(s kv.Store, f influxdbtesting.CheckFields, t *testing.T) (
|
|||
if err := svc.Initialize(ctx); err != nil {
|
||||
t.Fatalf("error initializing check service: %v", err)
|
||||
}
|
||||
for _, a := range f.Authorizations {
|
||||
if err := svc.PutAuthorization(ctx, a); err != nil {
|
||||
t.Fatalf("failed to populate auths: %v", err)
|
||||
}
|
||||
}
|
||||
for _, m := range f.UserResourceMappings {
|
||||
if err := svc.CreateUserResourceMapping(ctx, m); err != nil {
|
||||
t.Fatalf("failed to populate user resource mapping: %v", err)
|
||||
|
@ -70,6 +77,11 @@ func initCheckService(s kv.Store, f influxdbtesting.CheckFields, t *testing.T) (
|
|||
t.Fatalf("failed to populate checks")
|
||||
}
|
||||
}
|
||||
for _, tc := range f.Tasks {
|
||||
if _, err := svc.CreateTask(ctx, tc); err != nil {
|
||||
t.Fatalf("failed to populate tasks: %v", err)
|
||||
}
|
||||
}
|
||||
return svc, kv.OpPrefix, func() {
|
||||
for _, o := range f.Organizations {
|
||||
if err := svc.DeleteOrganization(ctx, o.ID); err != nil {
|
||||
|
|
42
kv/task.go
42
kv/task.go
|
@ -10,6 +10,7 @@ import (
|
|||
icontext "github.com/influxdata/influxdb/context"
|
||||
"github.com/influxdata/influxdb/task/backend"
|
||||
"github.com/influxdata/influxdb/task/options"
|
||||
"go.uber.org/zap"
|
||||
cron "gopkg.in/robfig/cron.v2"
|
||||
)
|
||||
|
||||
|
@ -469,20 +470,13 @@ func (s *Service) CreateTask(ctx context.Context, tc influxdb.TaskCreate) (*infl
|
|||
}
|
||||
|
||||
func (s *Service) createTask(ctx context.Context, tx Tx, tc influxdb.TaskCreate) (*influxdb.Task, error) {
|
||||
userAuth, err := icontext.GetAuthorizer(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if tc.Token == "" {
|
||||
return nil, influxdb.ErrMissingToken
|
||||
}
|
||||
|
||||
auth, err := s.findAuthorizationByToken(ctx, tx, tc.Token)
|
||||
if err != nil {
|
||||
if err.Error() != "<not found> authorization not found" {
|
||||
return nil, err
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var org *influxdb.Organization
|
||||
|
@ -566,18 +560,28 @@ func (s *Service) createTask(ctx context.Context, tx Tx, tc influxdb.TaskCreate)
|
|||
if err != nil {
|
||||
return nil, influxdb.ErrUnexpectedTaskBucketErr(err)
|
||||
}
|
||||
if err := s.createUserResourceMapping(ctx, tx, &influxdb.UserResourceMapping{
|
||||
ResourceType: influxdb.TasksResourceType,
|
||||
ResourceID: task.ID,
|
||||
UserID: userAuth.GetUserID(),
|
||||
UserType: influxdb.Owner,
|
||||
}); err != nil {
|
||||
return nil, err
|
||||
|
||||
if err := s.createTaskURM(ctx, tx, task); err != nil {
|
||||
s.Logger.Info("error creating user resource mapping for task", zap.Stringer("taskID", task.ID), zap.Error(err))
|
||||
}
|
||||
|
||||
return task, nil
|
||||
}
|
||||
|
||||
func (s *Service) createTaskURM(ctx context.Context, tx Tx, t *influxdb.Task) error {
|
||||
userAuth, err := icontext.GetAuthorizer(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return s.createUserResourceMapping(ctx, tx, &influxdb.UserResourceMapping{
|
||||
ResourceType: influxdb.TasksResourceType,
|
||||
ResourceID: t.ID,
|
||||
UserID: userAuth.GetUserID(),
|
||||
UserType: influxdb.Owner,
|
||||
})
|
||||
}
|
||||
|
||||
// UpdateTask updates a single task with changeset.
|
||||
func (s *Service) UpdateTask(ctx context.Context, id influxdb.ID, upd influxdb.TaskUpdate) (*influxdb.Task, error) {
|
||||
var t *influxdb.Task
|
||||
|
@ -746,9 +750,13 @@ func (s *Service) deleteTask(ctx context.Context, tx Tx, id influxdb.ID) error {
|
|||
return influxdb.ErrUnexpectedTaskBucketErr(err)
|
||||
}
|
||||
|
||||
return s.deleteUserResourceMapping(ctx, tx, influxdb.UserResourceMappingFilter{
|
||||
if err := s.deleteUserResourceMapping(ctx, tx, influxdb.UserResourceMappingFilter{
|
||||
ResourceID: task.ID,
|
||||
})
|
||||
}); err != nil {
|
||||
s.Logger.Info("error deleting user resource mapping for task", zap.Stringer("taskID", task.ID), zap.Error(err))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// FindLogs returns logs for a run.
|
||||
|
|
|
@ -1,9 +1,13 @@
|
|||
package check
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
||||
"github.com/influxdata/flux/ast"
|
||||
"github.com/influxdata/flux/parser"
|
||||
"github.com/influxdata/influxdb"
|
||||
"github.com/influxdata/influxdb/notification"
|
||||
)
|
||||
|
@ -19,16 +23,47 @@ type Base struct {
|
|||
Query influxdb.DashboardQuery `json:"query"`
|
||||
StatusMessageTemplate string `json:"statusMessageTemplate"`
|
||||
|
||||
Cron string `json:"cron,omitempty"`
|
||||
Every influxdb.Duration `json:"every,omitempty"`
|
||||
// Care should be taken to prevent TaskID from being exposed publicly.
|
||||
TaskID influxdb.ID `json:"taskID,omitempty"`
|
||||
|
||||
Cron string `json:"cron,omitempty"`
|
||||
Every *Duration `json:"every,omitempty"`
|
||||
// Offset represents a delay before execution.
|
||||
// It gets marshalled from a string duration, i.e.: "10s" is 10 seconds
|
||||
Offset influxdb.Duration `json:"offset,omitempty"`
|
||||
Offset *Duration `json:"offset,omitempty"`
|
||||
|
||||
Tags []notification.Tag `json:"tags"`
|
||||
influxdb.CRUDLog
|
||||
}
|
||||
|
||||
// Duration is a custom type used for generating flux compatible durations.
|
||||
type Duration ast.DurationLiteral
|
||||
|
||||
// MarshalJSON turns a Duration into a JSON-ified string.
|
||||
func (d Duration) MarshalJSON() ([]byte, error) {
|
||||
var b bytes.Buffer
|
||||
b.WriteByte('"')
|
||||
for _, d := range d.Values {
|
||||
b.WriteString(strconv.Itoa(int(d.Magnitude)))
|
||||
b.WriteString(d.Unit)
|
||||
}
|
||||
b.WriteByte('"')
|
||||
|
||||
return b.Bytes(), nil
|
||||
}
|
||||
|
||||
// UnmarshalJSON turns a flux duration literal into a Duration.
|
||||
func (d *Duration) UnmarshalJSON(b []byte) error {
|
||||
dur, err := parser.ParseDuration(string(b[1 : len(b)-1]))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
*d = *(*Duration)(dur)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Valid returns err if the check is invalid.
|
||||
func (b Base) Valid() error {
|
||||
if !b.ID.Valid() {
|
||||
|
@ -80,11 +115,21 @@ func (b Base) GetOrgID() influxdb.ID {
|
|||
return b.OrgID
|
||||
}
|
||||
|
||||
// GetTaskID retrieves the task ID for a check.
|
||||
func (b Base) GetTaskID() influxdb.ID {
|
||||
return b.TaskID
|
||||
}
|
||||
|
||||
// GetCRUDLog implements influxdb.Getter interface.
|
||||
func (b Base) GetCRUDLog() influxdb.CRUDLog {
|
||||
return b.CRUDLog
|
||||
}
|
||||
|
||||
// GetAuthID gets the authID for a check
|
||||
func (b Base) GetAuthID() influxdb.ID {
|
||||
return b.AuthorizationID
|
||||
}
|
||||
|
||||
// GetName implements influxdb.Getter interface.
|
||||
func (b *Base) GetName() string {
|
||||
return b.Name
|
||||
|
@ -110,6 +155,16 @@ func (b *Base) SetOrgID(id influxdb.ID) {
|
|||
b.OrgID = id
|
||||
}
|
||||
|
||||
// ClearPrivateData remove any data that we don't want to be exposed publicly.
|
||||
func (b *Base) ClearPrivateData() {
|
||||
b.TaskID = 0
|
||||
}
|
||||
|
||||
// SetTaskID sets the taskID for a check.
|
||||
func (b *Base) SetTaskID(id influxdb.ID) {
|
||||
b.TaskID = id
|
||||
}
|
||||
|
||||
// SetName implements influxdb.Updator interface.
|
||||
func (b *Base) SetName(name string) {
|
||||
b.Name = name
|
||||
|
|
|
@ -6,6 +6,8 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/google/go-cmp/cmp/cmpopts"
|
||||
"github.com/influxdata/flux/parser"
|
||||
"github.com/influxdata/influxdb/notification"
|
||||
|
||||
"github.com/influxdata/influxdb/mock"
|
||||
|
@ -147,6 +149,15 @@ func TestValidCheck(t *testing.T) {
|
|||
var timeGen1 = mock.TimeGenerator{FakeValue: time.Date(2006, time.July, 13, 4, 19, 10, 0, time.UTC)}
|
||||
var timeGen2 = mock.TimeGenerator{FakeValue: time.Date(2006, time.July, 14, 5, 23, 53, 10, time.UTC)}
|
||||
|
||||
func mustDuration(d string) *check.Duration {
|
||||
dur, err := parser.ParseDuration(d)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return (*check.Duration)(dur)
|
||||
}
|
||||
|
||||
func TestJSON(t *testing.T) {
|
||||
cases := []struct {
|
||||
name string
|
||||
|
@ -161,7 +172,7 @@ func TestJSON(t *testing.T) {
|
|||
Name: "name1",
|
||||
OrgID: influxTesting.MustIDBase16(id3),
|
||||
Status: influxdb.Active,
|
||||
Every: influxdb.Duration{Duration: time.Hour},
|
||||
Every: mustDuration("1h"),
|
||||
Tags: []notification.Tag{
|
||||
{
|
||||
Key: "k1",
|
||||
|
@ -191,7 +202,7 @@ func TestJSON(t *testing.T) {
|
|||
AuthorizationID: influxTesting.MustIDBase16(id2),
|
||||
OrgID: influxTesting.MustIDBase16(id3),
|
||||
Status: influxdb.Active,
|
||||
Every: influxdb.Duration{Duration: time.Hour},
|
||||
Every: mustDuration("1h"),
|
||||
Tags: []notification.Tag{
|
||||
{
|
||||
Key: "k1",
|
||||
|
@ -223,7 +234,7 @@ func TestJSON(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Fatalf("%s unmarshal failed, err: %s", c.name, err.Error())
|
||||
}
|
||||
if diff := cmp.Diff(got, c.src); diff != "" {
|
||||
if diff := cmp.Diff(got, c.src, cmpopts.IgnoreFields(check.Duration{}, "BaseNode")); diff != "" {
|
||||
t.Errorf("failed %s, Check are different -got/+want\ndiff %s", c.name, diff)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,6 +24,16 @@ func (c Deadman) Type() string {
|
|||
return "deadman"
|
||||
}
|
||||
|
||||
// GenerateFlux returns a flux script for the Deadman provided.
|
||||
func (c Deadman) GenerateFlux() (string, error) {
|
||||
// TODO(desa): needs implementation
|
||||
return `package main
|
||||
data = from(bucket: "telegraf")
|
||||
|> range(start: -1m)
|
||||
|
||||
option task = {name: "name1", every: 1m}`, nil
|
||||
}
|
||||
|
||||
type deadmanAlias Deadman
|
||||
|
||||
// MarshalJSON implement json.Marshaler interface.
|
||||
|
|
|
@ -2,9 +2,14 @@ package check
|
|||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/influxdata/flux/ast"
|
||||
"github.com/influxdata/flux/parser"
|
||||
"github.com/influxdata/influxdb"
|
||||
"github.com/influxdata/influxdb/notification"
|
||||
"github.com/influxdata/influxdb/notification/flux"
|
||||
)
|
||||
|
||||
var _ influxdb.Check = &Threshold{}
|
||||
|
@ -33,6 +38,184 @@ func (c Threshold) Valid() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func multiError(errs []error) error {
|
||||
var b strings.Builder
|
||||
|
||||
for _, err := range errs {
|
||||
b.WriteString(err.Error() + "\n")
|
||||
}
|
||||
|
||||
return fmt.Errorf(b.String())
|
||||
}
|
||||
|
||||
// GenerateFlux returns a flux script for the threshold provided. If there
|
||||
// are any errors in the flux that the user provided the function will return
|
||||
// an error for each error found when the script is parsed.
|
||||
func (t Threshold) GenerateFlux() (string, error) {
|
||||
p, err := t.GenerateFluxAST()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return ast.Format(p), nil
|
||||
}
|
||||
|
||||
// GenerateFlux returns a flux AST for the threshold provided. If there
|
||||
// are any errors in the flux that the user provided the function will return
|
||||
// an error for each error found when the script is parsed.
|
||||
func (t Threshold) GenerateFluxAST() (*ast.Package, error) {
|
||||
p := parser.ParseSource(t.Query.Text)
|
||||
|
||||
if errs := ast.GetErrors(p); len(errs) != 0 {
|
||||
return nil, multiError(errs)
|
||||
}
|
||||
|
||||
// TODO(desa): this is a hack that we had to do as a result of https://github.com/influxdata/flux/issues/1701
|
||||
// when it is fixed we should use a separate file and not manipulate the existing one.
|
||||
if len(p.Files) != 1 {
|
||||
return nil, fmt.Errorf("expect a single file to be returned from query parsing got %d", len(p.Files))
|
||||
}
|
||||
|
||||
f := p.Files[0]
|
||||
f.Body = append(f.Body, t.generateTaskOption())
|
||||
|
||||
return p, nil
|
||||
}
|
||||
|
||||
// GenerateFluxASTReal is the real version of GenerateFluxAST. It has to exist so staticheck doesn't yell about
|
||||
// the unexported functions I have here.
|
||||
func (t Threshold) GenerateFluxASTReal() (*ast.Package, error) {
|
||||
p := parser.ParseSource(t.Query.Text)
|
||||
|
||||
if errs := ast.GetErrors(p); len(errs) != 0 {
|
||||
return nil, multiError(errs)
|
||||
}
|
||||
|
||||
// TODO(desa): this is a hack that we had to do as a result of https://github.com/influxdata/flux/issues/1701
|
||||
// when it is fixed we should use a separate file and not manipulate the existing one.
|
||||
if len(p.Files) != 1 {
|
||||
return nil, fmt.Errorf("expect a single file to be returned from query parsing got %d", len(p.Files))
|
||||
}
|
||||
|
||||
f := p.Files[0]
|
||||
|
||||
f.Imports = append(f.Imports, flux.Imports("influxdata/influxdb/alerts")...)
|
||||
f.Body = append(f.Body, t.generateFluxASTBody()...)
|
||||
|
||||
return p, nil
|
||||
}
|
||||
|
||||
func (t Threshold) generateTaskOption() ast.Statement {
|
||||
props := []*ast.Property{}
|
||||
|
||||
props = append(props, flux.Property("name", flux.String(t.Name)))
|
||||
|
||||
if t.Cron != "" {
|
||||
props = append(props, flux.Property("cron", flux.String(t.Cron)))
|
||||
}
|
||||
|
||||
if t.Every != nil {
|
||||
props = append(props, flux.Property("every", (*ast.DurationLiteral)(t.Every)))
|
||||
}
|
||||
|
||||
if t.Offset != nil {
|
||||
props = append(props, flux.Property("offset", (*ast.DurationLiteral)(t.Offset)))
|
||||
}
|
||||
|
||||
return flux.DefineTaskOption(flux.Object(props...))
|
||||
}
|
||||
|
||||
func (t Threshold) generateFluxASTBody() []ast.Statement {
|
||||
var statements []ast.Statement
|
||||
statements = append(statements, t.generateTaskOption())
|
||||
statements = append(statements, t.generateFluxASTCheckDefinition())
|
||||
statements = append(statements, t.generateFluxASTThresholdFunctions()...)
|
||||
statements = append(statements, t.generateFluxASTMessageFunction())
|
||||
statements = append(statements, t.generateFluxASTChecksFunction())
|
||||
return statements
|
||||
}
|
||||
|
||||
func (t Threshold) generateFluxASTMessageFunction() ast.Statement {
|
||||
fn := flux.Function(flux.FunctionParams("r", "check"), flux.String(t.StatusMessageTemplate))
|
||||
return flux.DefineVariable("messageFn", fn)
|
||||
}
|
||||
|
||||
func (t Threshold) generateFluxASTChecksFunction() ast.Statement {
|
||||
return flux.ExpressionStatement(flux.Pipe(flux.Identifier("data"), t.generateFluxASTChecksCall()))
|
||||
}
|
||||
|
||||
func (t Threshold) generateFluxASTChecksCall() *ast.CallExpression {
|
||||
objectProps := append(([]*ast.Property)(nil), flux.Property("check", flux.Identifier("check")))
|
||||
objectProps = append(objectProps, flux.Property("messageFn", flux.Identifier("messageFn")))
|
||||
|
||||
// This assumes that the ThresholdConfigs we've been provided do not have duplicates.
|
||||
for _, c := range t.Thresholds {
|
||||
lvl := strings.ToLower(c.Level.String())
|
||||
objectProps = append(objectProps, flux.Property(lvl, flux.Identifier(lvl)))
|
||||
}
|
||||
|
||||
return flux.Call(flux.Member("alerts", "check"), flux.Object(objectProps...))
|
||||
}
|
||||
|
||||
func (t Threshold) generateFluxASTCheckDefinition() ast.Statement {
|
||||
tagProperties := []*ast.Property{}
|
||||
for _, tag := range t.Tags {
|
||||
tagProperties = append(tagProperties, flux.Property(tag.Key, flux.String(tag.Value)))
|
||||
}
|
||||
tags := flux.Property("tags", flux.Object(tagProperties...))
|
||||
|
||||
checkID := flux.Property("checkID", flux.String(t.ID.String()))
|
||||
|
||||
return flux.DefineVariable("check", flux.Object(checkID, tags))
|
||||
}
|
||||
|
||||
func (t Threshold) generateFluxASTThresholdFunctions() []ast.Statement {
|
||||
thresholdStatements := []ast.Statement{}
|
||||
|
||||
// This assumes that the ThresholdConfigs we've been provided do not have duplicates.
|
||||
for _, c := range t.Thresholds {
|
||||
if c.UpperBound == nil {
|
||||
thresholdStatements = append(thresholdStatements, c.generateFluxASTGreaterThresholdFunction())
|
||||
} else if c.LowerBound == nil {
|
||||
thresholdStatements = append(thresholdStatements, c.generateFluxASTLesserThresholdFunction())
|
||||
} else {
|
||||
thresholdStatements = append(thresholdStatements, c.generateFluxASTRangeThresholdFunction())
|
||||
}
|
||||
//need without range here
|
||||
}
|
||||
return thresholdStatements
|
||||
}
|
||||
|
||||
func (c ThresholdConfig) generateFluxASTGreaterThresholdFunction() ast.Statement {
|
||||
fnBody := flux.GreaterThan(flux.Member("r", "_value"), flux.Float(*c.LowerBound))
|
||||
fn := flux.Function(flux.FunctionParams("r"), fnBody)
|
||||
|
||||
lvl := strings.ToLower(c.Level.String())
|
||||
|
||||
return flux.DefineVariable(lvl, fn)
|
||||
}
|
||||
|
||||
func (c ThresholdConfig) generateFluxASTLesserThresholdFunction() ast.Statement {
|
||||
fnBody := flux.LessThan(flux.Member("r", "_value"), flux.Float(*c.UpperBound))
|
||||
fn := flux.Function(flux.FunctionParams("r"), fnBody)
|
||||
|
||||
lvl := strings.ToLower(c.Level.String())
|
||||
|
||||
return flux.DefineVariable(lvl, fn)
|
||||
}
|
||||
|
||||
func (c ThresholdConfig) generateFluxASTRangeThresholdFunction() ast.Statement {
|
||||
fnBody := flux.And(
|
||||
flux.LessThan(flux.Member("r", "_value"), flux.Float(*c.UpperBound)),
|
||||
flux.GreaterThan(flux.Member("r", "_value"), flux.Float(*c.LowerBound)),
|
||||
)
|
||||
fn := flux.Function(flux.FunctionParams("r"), fnBody)
|
||||
|
||||
lvl := strings.ToLower(c.Level.String())
|
||||
|
||||
return flux.DefineVariable(lvl, fn)
|
||||
}
|
||||
|
||||
type thresholdAlias Threshold
|
||||
|
||||
// MarshalJSON implement json.Marshaler interface.
|
||||
|
|
|
@ -0,0 +1,289 @@
|
|||
package check_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/influxdata/flux/ast"
|
||||
"github.com/influxdata/influxdb"
|
||||
"github.com/influxdata/influxdb/notification"
|
||||
"github.com/influxdata/influxdb/notification/check"
|
||||
)
|
||||
|
||||
func TestThreshold_GenerateFlux(t *testing.T) {
|
||||
type args struct {
|
||||
threshold check.Threshold
|
||||
}
|
||||
type wants struct {
|
||||
script string
|
||||
}
|
||||
|
||||
var l float64 = 10
|
||||
var u float64 = 40
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
wants wants
|
||||
}{
|
||||
{
|
||||
name: "all levels",
|
||||
args: args{
|
||||
threshold: check.Threshold{
|
||||
Base: check.Base{
|
||||
ID: 10,
|
||||
Name: "moo",
|
||||
Tags: []notification.Tag{
|
||||
{Key: "aaa", Value: "vaaa"},
|
||||
{Key: "bbb", Value: "vbbb"},
|
||||
},
|
||||
Every: mustDuration("1h"),
|
||||
StatusMessageTemplate: "whoa! {check.yeah}",
|
||||
Query: influxdb.DashboardQuery{
|
||||
Text: `data = from(bucket: "foo") |> range(start: -1d)`,
|
||||
},
|
||||
},
|
||||
Thresholds: []check.ThresholdConfig{
|
||||
check.ThresholdConfig{
|
||||
Level: notification.Ok,
|
||||
LowerBound: &l,
|
||||
},
|
||||
check.ThresholdConfig{
|
||||
Level: notification.Info,
|
||||
UpperBound: &u,
|
||||
},
|
||||
check.ThresholdConfig{
|
||||
Level: notification.Warn,
|
||||
LowerBound: &l,
|
||||
UpperBound: &u,
|
||||
},
|
||||
check.ThresholdConfig{
|
||||
Level: notification.Critical,
|
||||
LowerBound: &l,
|
||||
UpperBound: &u,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
wants: wants{
|
||||
script: `package main
|
||||
import "influxdata/influxdb/alerts"
|
||||
|
||||
data = from(bucket: "foo")
|
||||
|> range(start: -1d)
|
||||
|
||||
option task = {name: "moo", every: 1h}
|
||||
|
||||
check = {checkID: "000000000000000a", tags: {aaa: "vaaa", bbb: "vbbb"}}
|
||||
ok = (r) =>
|
||||
(r._value > 10.0)
|
||||
info = (r) =>
|
||||
(r._value < 40.0)
|
||||
warn = (r) =>
|
||||
(r._value < 40.0 and r._value > 10.0)
|
||||
crit = (r) =>
|
||||
(r._value < 40.0 and r._value > 10.0)
|
||||
messageFn = (r, check) =>
|
||||
("whoa! {check.yeah}")
|
||||
|
||||
data
|
||||
|> alerts.check(
|
||||
check: check,
|
||||
messageFn: messageFn,
|
||||
ok: ok,
|
||||
info: info,
|
||||
warn: warn,
|
||||
crit: crit,
|
||||
)`,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "crit and warn",
|
||||
args: args{
|
||||
threshold: check.Threshold{
|
||||
Base: check.Base{
|
||||
ID: 10,
|
||||
Name: "moo",
|
||||
Tags: []notification.Tag{
|
||||
{Key: "aaa", Value: "vaaa"},
|
||||
{Key: "bbb", Value: "vbbb"},
|
||||
},
|
||||
Every: mustDuration("1h"),
|
||||
Offset: mustDuration("10m"),
|
||||
StatusMessageTemplate: "whoa! {check.yeah}",
|
||||
Query: influxdb.DashboardQuery{
|
||||
Text: `data = from(bucket: "foo") |> range(start: -1d)`,
|
||||
},
|
||||
},
|
||||
Thresholds: []check.ThresholdConfig{
|
||||
check.ThresholdConfig{
|
||||
Level: notification.Warn,
|
||||
UpperBound: &u,
|
||||
},
|
||||
check.ThresholdConfig{
|
||||
Level: notification.Critical,
|
||||
LowerBound: &u,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
wants: wants{
|
||||
script: `package main
|
||||
import "influxdata/influxdb/alerts"
|
||||
|
||||
data = from(bucket: "foo")
|
||||
|> range(start: -1d)
|
||||
|
||||
option task = {name: "moo", every: 1h, offset: 10m}
|
||||
|
||||
check = {checkID: "000000000000000a", tags: {aaa: "vaaa", bbb: "vbbb"}}
|
||||
warn = (r) =>
|
||||
(r._value < 40.0)
|
||||
crit = (r) =>
|
||||
(r._value > 40.0)
|
||||
messageFn = (r, check) =>
|
||||
("whoa! {check.yeah}")
|
||||
|
||||
data
|
||||
|> alerts.check(
|
||||
check: check,
|
||||
messageFn: messageFn,
|
||||
warn: warn,
|
||||
crit: crit,
|
||||
)`,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "no levels",
|
||||
args: args{
|
||||
threshold: check.Threshold{
|
||||
Base: check.Base{
|
||||
ID: 10,
|
||||
Name: "moo",
|
||||
Tags: []notification.Tag{
|
||||
{Key: "aaa", Value: "vaaa"},
|
||||
{Key: "bbb", Value: "vbbb"},
|
||||
},
|
||||
StatusMessageTemplate: "whoa! {check.yeah}",
|
||||
Query: influxdb.DashboardQuery{
|
||||
Text: `data = from(bucket: "foo") |> range(start: -1d)`,
|
||||
},
|
||||
},
|
||||
Thresholds: []check.ThresholdConfig{},
|
||||
},
|
||||
},
|
||||
wants: wants{
|
||||
script: `package main
|
||||
import "influxdata/influxdb/alerts"
|
||||
|
||||
data = from(bucket: "foo")
|
||||
|> range(start: -1d)
|
||||
|
||||
option task = {name: "moo"}
|
||||
|
||||
check = {checkID: "000000000000000a", tags: {aaa: "vaaa", bbb: "vbbb"}}
|
||||
messageFn = (r, check) =>
|
||||
("whoa! {check.yeah}")
|
||||
|
||||
data
|
||||
|> alerts.check(check: check, messageFn: messageFn)`,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "no tags",
|
||||
args: args{
|
||||
threshold: check.Threshold{
|
||||
Base: check.Base{
|
||||
ID: 10,
|
||||
Name: "moo",
|
||||
Cron: "5 4 * * *",
|
||||
Tags: []notification.Tag{},
|
||||
StatusMessageTemplate: "whoa! {check.yeah}",
|
||||
Query: influxdb.DashboardQuery{
|
||||
Text: `data = from(bucket: "foo") |> range(start: -1d)`,
|
||||
},
|
||||
},
|
||||
Thresholds: []check.ThresholdConfig{},
|
||||
},
|
||||
},
|
||||
wants: wants{
|
||||
script: `package main
|
||||
import "influxdata/influxdb/alerts"
|
||||
|
||||
data = from(bucket: "foo")
|
||||
|> range(start: -1d)
|
||||
|
||||
option task = {name: "moo", cron: "5 4 * * *"}
|
||||
|
||||
check = {checkID: "000000000000000a", tags: {}}
|
||||
messageFn = (r, check) =>
|
||||
("whoa! {check.yeah}")
|
||||
|
||||
data
|
||||
|> alerts.check(check: check, messageFn: messageFn)`,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "many tags",
|
||||
args: args{
|
||||
threshold: check.Threshold{
|
||||
Base: check.Base{
|
||||
ID: 10,
|
||||
Name: "foo",
|
||||
Tags: []notification.Tag{
|
||||
{Key: "a", Value: "b"},
|
||||
{Key: "b", Value: "c"},
|
||||
{Key: "c", Value: "d"},
|
||||
{Key: "d", Value: "e"},
|
||||
{Key: "e", Value: "f"},
|
||||
{Key: "f", Value: "g"},
|
||||
},
|
||||
StatusMessageTemplate: "whoa! {check.yeah}",
|
||||
Query: influxdb.DashboardQuery{
|
||||
Text: `data = from(bucket: "foo") |> range(start: -1d)`,
|
||||
},
|
||||
},
|
||||
Thresholds: []check.ThresholdConfig{},
|
||||
},
|
||||
},
|
||||
wants: wants{
|
||||
script: `package main
|
||||
import "influxdata/influxdb/alerts"
|
||||
|
||||
data = from(bucket: "foo")
|
||||
|> range(start: -1d)
|
||||
|
||||
option task = {name: "foo"}
|
||||
|
||||
check = {checkID: "000000000000000a", tags: {
|
||||
a: "b",
|
||||
b: "c",
|
||||
c: "d",
|
||||
d: "e",
|
||||
e: "f",
|
||||
f: "g",
|
||||
}}
|
||||
messageFn = (r, check) =>
|
||||
("whoa! {check.yeah}")
|
||||
|
||||
data
|
||||
|> alerts.check(check: check, messageFn: messageFn)`,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
// TODO(desa): change this to GenerateFlux() when we don't need to code
|
||||
// around the alerts package not being available.
|
||||
p, err := tt.args.threshold.GenerateFluxASTReal()
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
|
||||
if exp, got := tt.wants.script, ast.Format(p); exp != got {
|
||||
t.Errorf("expected:\n%v\n\ngot:\n%v\n", exp, got)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,171 @@
|
|||
package flux
|
||||
|
||||
import "github.com/influxdata/flux/ast"
|
||||
|
||||
// File creates a new *ast.File.
|
||||
func File(name string, imports []*ast.ImportDeclaration, body []ast.Statement) *ast.File {
|
||||
return &ast.File{
|
||||
Name: name,
|
||||
Imports: imports,
|
||||
Body: body,
|
||||
}
|
||||
}
|
||||
|
||||
// GreaterThan returns a greater than *ast.BinaryExpression.
|
||||
func GreaterThan(lhs, rhs ast.Expression) *ast.BinaryExpression {
|
||||
return &ast.BinaryExpression{
|
||||
Operator: ast.GreaterThanOperator,
|
||||
Left: lhs,
|
||||
Right: rhs,
|
||||
}
|
||||
}
|
||||
|
||||
// LessThan returns a less than *ast.BinaryExpression.
|
||||
func LessThan(lhs, rhs ast.Expression) *ast.BinaryExpression {
|
||||
return &ast.BinaryExpression{
|
||||
Operator: ast.LessThanOperator,
|
||||
Left: lhs,
|
||||
Right: rhs,
|
||||
}
|
||||
}
|
||||
|
||||
// Member returns an *ast.MemberExpression where the key is p and the values is c.
|
||||
func Member(p, c string) *ast.MemberExpression {
|
||||
return &ast.MemberExpression{
|
||||
Object: &ast.Identifier{Name: p},
|
||||
Property: &ast.Identifier{Name: c},
|
||||
}
|
||||
}
|
||||
|
||||
// And returns an and *ast.LogicalExpression.
|
||||
func And(lhs, rhs ast.Expression) *ast.LogicalExpression {
|
||||
return &ast.LogicalExpression{
|
||||
Operator: ast.AndOperator,
|
||||
Left: lhs,
|
||||
Right: rhs,
|
||||
}
|
||||
}
|
||||
|
||||
// Pipe returns a *ast.PipeExpression that is a piped sequence of call expressions starting at base.
|
||||
// It requires at least one call expression and will panic otherwise.
|
||||
func Pipe(base ast.Expression, calls ...*ast.CallExpression) *ast.PipeExpression {
|
||||
if len(calls) < 1 {
|
||||
panic("must pipe forward to at least one *ast.CallExpression")
|
||||
}
|
||||
pe := appendPipe(base, calls[0])
|
||||
for _, call := range calls[1:] {
|
||||
pe = appendPipe(pe, call)
|
||||
}
|
||||
|
||||
return pe
|
||||
}
|
||||
|
||||
func appendPipe(base ast.Expression, next *ast.CallExpression) *ast.PipeExpression {
|
||||
return &ast.PipeExpression{
|
||||
Argument: base,
|
||||
Call: next,
|
||||
}
|
||||
}
|
||||
|
||||
// Call returns a *ast.CallExpression that is a function call of fn with args.
|
||||
func Call(fn ast.Expression, args *ast.ObjectExpression) *ast.CallExpression {
|
||||
return &ast.CallExpression{
|
||||
Callee: fn,
|
||||
Arguments: []ast.Expression{
|
||||
args,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// ExpressionStatement returns an *ast.ExpressionStagement of e.
|
||||
func ExpressionStatement(e ast.Expression) *ast.ExpressionStatement {
|
||||
return &ast.ExpressionStatement{Expression: e}
|
||||
}
|
||||
|
||||
// Function returns an *ast.FunctionExpression with params with body b.
|
||||
func Function(params []*ast.Property, b ast.Expression) *ast.FunctionExpression {
|
||||
return &ast.FunctionExpression{
|
||||
Params: params,
|
||||
Body: b,
|
||||
}
|
||||
}
|
||||
|
||||
// String returns an *ast.StringLiteral of s.
|
||||
func String(s string) *ast.StringLiteral {
|
||||
return &ast.StringLiteral{
|
||||
Value: s,
|
||||
}
|
||||
}
|
||||
|
||||
// Identifier returns an *ast.Identifier of i.
|
||||
func Identifier(i string) *ast.Identifier {
|
||||
return &ast.Identifier{Name: i}
|
||||
}
|
||||
|
||||
// Float returns an *ast.FloatLiteral of f.
|
||||
func Float(f float64) *ast.FloatLiteral {
|
||||
return &ast.FloatLiteral{
|
||||
Value: f,
|
||||
}
|
||||
}
|
||||
|
||||
// DefineVariable returns an *ast.VariableAssignment of id to the e. (e.g. id = <expression>)
|
||||
func DefineVariable(id string, e ast.Expression) *ast.VariableAssignment {
|
||||
return &ast.VariableAssignment{
|
||||
ID: &ast.Identifier{
|
||||
Name: id,
|
||||
},
|
||||
Init: e,
|
||||
}
|
||||
}
|
||||
|
||||
// DefineTaskOption returns an *ast.OptionStatement with the object provided. (e.g. option task = {...})
|
||||
func DefineTaskOption(o *ast.ObjectExpression) *ast.OptionStatement {
|
||||
return &ast.OptionStatement{
|
||||
Assignment: DefineVariable("task", o),
|
||||
}
|
||||
}
|
||||
|
||||
// Property returns an *ast.Property of key to e. (e.g. key: <expression>)
|
||||
func Property(key string, e ast.Expression) *ast.Property {
|
||||
return &ast.Property{
|
||||
Key: &ast.Identifier{
|
||||
Name: key,
|
||||
},
|
||||
Value: e,
|
||||
}
|
||||
}
|
||||
|
||||
// Object returns an *ast.ObjectExpression with properties ps.
|
||||
func Object(ps ...*ast.Property) *ast.ObjectExpression {
|
||||
return &ast.ObjectExpression{
|
||||
Properties: ps,
|
||||
}
|
||||
}
|
||||
|
||||
// FunctionParams returns a slice of *ast.Property for the parameters of a function.
|
||||
func FunctionParams(args ...string) []*ast.Property {
|
||||
var params []*ast.Property
|
||||
for _, arg := range args {
|
||||
params = append(params, &ast.Property{Key: &ast.Identifier{Name: arg}})
|
||||
}
|
||||
return params
|
||||
}
|
||||
|
||||
// Imports returns a []*ast.ImportDeclaration for each package in pkgs.
|
||||
func Imports(pkgs ...string) []*ast.ImportDeclaration {
|
||||
var is []*ast.ImportDeclaration
|
||||
for _, pkg := range pkgs {
|
||||
is = append(is, ImportDeclaration(pkg))
|
||||
}
|
||||
return is
|
||||
}
|
||||
|
||||
// ImportDeclaration returns an *ast.ImportDeclaration for pkg.
|
||||
func ImportDeclaration(pkg string) *ast.ImportDeclaration {
|
||||
return &ast.ImportDeclaration{
|
||||
Path: &ast.StringLiteral{
|
||||
Value: pkg,
|
||||
},
|
||||
}
|
||||
}
|
|
@ -9,25 +9,43 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/google/go-cmp/cmp/cmpopts"
|
||||
"github.com/influxdata/flux/parser"
|
||||
"github.com/influxdata/influxdb"
|
||||
"github.com/influxdata/influxdb/mock"
|
||||
"github.com/influxdata/influxdb/notification"
|
||||
"github.com/influxdata/influxdb/notification/check"
|
||||
)
|
||||
|
||||
func mustDuration(d string) *check.Duration {
|
||||
dur, err := parser.ParseDuration(d)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return (*check.Duration)(dur)
|
||||
}
|
||||
|
||||
const (
|
||||
checkOneID = "020f755c3c082000"
|
||||
checkTwoID = "020f755c3c082001"
|
||||
)
|
||||
|
||||
var script = `data = from(bucket: "telegraf") |> range(start: -1m)`
|
||||
|
||||
var deadman1 = &check.Deadman{
|
||||
Base: check.Base{
|
||||
Name: "name1",
|
||||
ID: MustIDBase16(checkOneID),
|
||||
OrgID: MustIDBase16(orgOneID),
|
||||
AuthorizationID: MustIDBase16(twoID),
|
||||
Description: "desc1",
|
||||
Status: influxdb.Active,
|
||||
Name: "name1",
|
||||
ID: MustIDBase16(checkOneID),
|
||||
OrgID: MustIDBase16(orgOneID),
|
||||
AuthorizationID: MustIDBase16(twoID),
|
||||
Description: "desc1",
|
||||
TaskID: 1,
|
||||
Status: influxdb.Active,
|
||||
Query: influxdb.DashboardQuery{
|
||||
Text: script,
|
||||
},
|
||||
Every: mustDuration("1m"),
|
||||
StatusMessageTemplate: "msg1",
|
||||
Tags: []notification.Tag{
|
||||
{Key: "k1", Value: "v1"},
|
||||
|
@ -48,10 +66,15 @@ var threshold1 = &check.Threshold{
|
|||
Name: "name2",
|
||||
ID: MustIDBase16(checkTwoID),
|
||||
OrgID: MustIDBase16(orgTwoID),
|
||||
AuthorizationID: MustIDBase16(threeID),
|
||||
AuthorizationID: MustIDBase16(twoID),
|
||||
TaskID: 1,
|
||||
Description: "desc2",
|
||||
Status: influxdb.Active,
|
||||
StatusMessageTemplate: "msg2",
|
||||
Every: mustDuration("1m"),
|
||||
Query: influxdb.DashboardQuery{
|
||||
Text: script,
|
||||
},
|
||||
Tags: []notification.Tag{
|
||||
{Key: "k11", Value: "v11"},
|
||||
},
|
||||
|
@ -61,8 +84,8 @@ var threshold1 = &check.Threshold{
|
|||
},
|
||||
},
|
||||
Thresholds: []check.ThresholdConfig{
|
||||
{LowerBound: FloatPtr(1000)},
|
||||
{UpperBound: FloatPtr(2000)},
|
||||
{Level: 0, LowerBound: FloatPtr(1000)},
|
||||
{Level: 1, UpperBound: FloatPtr(2000)},
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -70,6 +93,7 @@ var checkCmpOptions = cmp.Options{
|
|||
cmp.Comparer(func(x, y []byte) bool {
|
||||
return bytes.Equal(x, y)
|
||||
}),
|
||||
cmpopts.IgnoreFields(check.Base{}, "TaskID"),
|
||||
cmp.Transformer("Sort", func(in []influxdb.Check) []influxdb.Check {
|
||||
out := append([]influxdb.Check(nil), in...) // Copy input to avoid mutating it
|
||||
sort.Slice(out, func(i, j int) bool {
|
||||
|
@ -86,6 +110,8 @@ type CheckFields struct {
|
|||
Checks []influxdb.Check
|
||||
Organizations []*influxdb.Organization
|
||||
UserResourceMappings []*influxdb.UserResourceMapping
|
||||
Authorizations []*influxdb.Authorization
|
||||
Tasks []influxdb.TaskCreate
|
||||
}
|
||||
|
||||
type checkServiceF func(
|
||||
|
@ -184,14 +210,25 @@ func CreateCheck(
|
|||
UserType: influxdb.Owner,
|
||||
},
|
||||
},
|
||||
Authorizations: []*influxdb.Authorization{
|
||||
{
|
||||
ID: MustIDBase16(twoID),
|
||||
Token: "abc123",
|
||||
OrgID: MustIDBase16(orgOneID),
|
||||
},
|
||||
},
|
||||
},
|
||||
args: args{
|
||||
check: &check.Deadman{
|
||||
Base: check.Base{
|
||||
Name: "name1",
|
||||
OrgID: MustIDBase16(orgOneID),
|
||||
AuthorizationID: MustIDBase16(twoID),
|
||||
Description: "desc1",
|
||||
Name: "name1",
|
||||
OrgID: MustIDBase16(orgOneID),
|
||||
AuthorizationID: MustIDBase16(twoID),
|
||||
Description: "desc1",
|
||||
Query: influxdb.DashboardQuery{
|
||||
Text: script,
|
||||
},
|
||||
Every: mustDuration("1m"),
|
||||
Status: influxdb.Active,
|
||||
StatusMessageTemplate: "msg1",
|
||||
Tags: []notification.Tag{
|
||||
|
@ -222,10 +259,14 @@ func CreateCheck(
|
|||
checks: []influxdb.Check{
|
||||
&check.Deadman{
|
||||
Base: check.Base{
|
||||
Name: "name1",
|
||||
ID: MustIDBase16(checkOneID),
|
||||
OrgID: MustIDBase16(orgOneID),
|
||||
AuthorizationID: MustIDBase16(twoID),
|
||||
Name: "name1",
|
||||
ID: MustIDBase16(checkOneID),
|
||||
OrgID: MustIDBase16(orgOneID),
|
||||
AuthorizationID: MustIDBase16(twoID),
|
||||
Query: influxdb.DashboardQuery{
|
||||
Text: script,
|
||||
},
|
||||
Every: mustDuration("1m"),
|
||||
Description: "desc1",
|
||||
Status: influxdb.Active,
|
||||
StatusMessageTemplate: "msg1",
|
||||
|
@ -267,23 +308,34 @@ func CreateCheck(
|
|||
ID: MustIDBase16(orgTwoID),
|
||||
},
|
||||
},
|
||||
Authorizations: []*influxdb.Authorization{
|
||||
{
|
||||
ID: MustIDBase16(twoID),
|
||||
Token: "abc123",
|
||||
OrgID: MustIDBase16(orgOneID),
|
||||
},
|
||||
},
|
||||
},
|
||||
args: args{
|
||||
check: &check.Threshold{
|
||||
Base: check.Base{
|
||||
Name: "name2",
|
||||
OrgID: MustIDBase16(orgTwoID),
|
||||
AuthorizationID: MustIDBase16(threeID),
|
||||
AuthorizationID: MustIDBase16(twoID),
|
||||
Description: "desc2",
|
||||
Status: influxdb.Active,
|
||||
StatusMessageTemplate: "msg2",
|
||||
Every: mustDuration("1m"),
|
||||
Query: influxdb.DashboardQuery{
|
||||
Text: script,
|
||||
},
|
||||
Tags: []notification.Tag{
|
||||
{Key: "k11", Value: "v11"},
|
||||
},
|
||||
},
|
||||
Thresholds: []check.ThresholdConfig{
|
||||
{LowerBound: FloatPtr(1000)},
|
||||
{UpperBound: FloatPtr(2000)},
|
||||
{Level: 0, LowerBound: FloatPtr(1000)},
|
||||
{Level: 1, UpperBound: FloatPtr(2000)},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -316,15 +368,26 @@ func CreateCheck(
|
|||
ID: MustIDBase16(orgTwoID),
|
||||
},
|
||||
},
|
||||
Authorizations: []*influxdb.Authorization{
|
||||
{
|
||||
ID: MustIDBase16(twoID),
|
||||
Token: "abc123",
|
||||
OrgID: MustIDBase16(orgOneID),
|
||||
},
|
||||
},
|
||||
},
|
||||
args: args{
|
||||
check: &check.Threshold{
|
||||
Base: check.Base{
|
||||
Name: "name1",
|
||||
OrgID: MustIDBase16(orgOneID),
|
||||
AuthorizationID: MustIDBase16(twoID),
|
||||
Description: "desc1",
|
||||
Status: influxdb.Active,
|
||||
Name: "name1",
|
||||
OrgID: MustIDBase16(orgOneID),
|
||||
AuthorizationID: MustIDBase16(twoID),
|
||||
Description: "desc1",
|
||||
Status: influxdb.Active,
|
||||
Every: mustDuration("1m"),
|
||||
Query: influxdb.DashboardQuery{
|
||||
Text: script,
|
||||
},
|
||||
StatusMessageTemplate: "msg1",
|
||||
Tags: []notification.Tag{
|
||||
{Key: "k1", Value: "v1"},
|
||||
|
@ -366,14 +429,25 @@ func CreateCheck(
|
|||
Checks: []influxdb.Check{
|
||||
deadman1,
|
||||
},
|
||||
Authorizations: []*influxdb.Authorization{
|
||||
{
|
||||
ID: MustIDBase16(twoID),
|
||||
Token: "abc123",
|
||||
OrgID: MustIDBase16(orgOneID),
|
||||
},
|
||||
},
|
||||
},
|
||||
args: args{
|
||||
check: &check.Threshold{
|
||||
Base: check.Base{
|
||||
Name: "name1",
|
||||
OrgID: MustIDBase16(orgTwoID),
|
||||
AuthorizationID: MustIDBase16(twoID),
|
||||
Description: "desc2",
|
||||
Name: "name1",
|
||||
OrgID: MustIDBase16(orgTwoID),
|
||||
AuthorizationID: MustIDBase16(twoID),
|
||||
Description: "desc2",
|
||||
Every: mustDuration("1m"),
|
||||
Query: influxdb.DashboardQuery{
|
||||
Text: script,
|
||||
},
|
||||
Status: influxdb.Inactive,
|
||||
StatusMessageTemplate: "msg2",
|
||||
Tags: []notification.Tag{
|
||||
|
@ -388,9 +462,13 @@ func CreateCheck(
|
|||
deadman1,
|
||||
&check.Threshold{
|
||||
Base: check.Base{
|
||||
ID: MustIDBase16(checkTwoID),
|
||||
Name: "name1",
|
||||
OrgID: MustIDBase16(orgTwoID),
|
||||
ID: MustIDBase16(checkTwoID),
|
||||
Name: "name1",
|
||||
OrgID: MustIDBase16(orgTwoID),
|
||||
Every: mustDuration("1m"),
|
||||
Query: influxdb.DashboardQuery{
|
||||
Text: script,
|
||||
},
|
||||
AuthorizationID: MustIDBase16(twoID),
|
||||
Description: "desc2",
|
||||
Status: influxdb.Inactive,
|
||||
|
@ -415,13 +493,24 @@ func CreateCheck(
|
|||
TimeGenerator: mock.TimeGenerator{FakeValue: time.Date(2006, 5, 4, 1, 2, 3, 0, time.UTC)},
|
||||
Checks: []influxdb.Check{},
|
||||
Organizations: []*influxdb.Organization{},
|
||||
Authorizations: []*influxdb.Authorization{
|
||||
{
|
||||
ID: MustIDBase16(twoID),
|
||||
Token: "abc123",
|
||||
OrgID: MustIDBase16(orgOneID),
|
||||
},
|
||||
},
|
||||
},
|
||||
args: args{
|
||||
check: &check.Threshold{
|
||||
Base: check.Base{
|
||||
Name: "name1",
|
||||
OrgID: MustIDBase16(orgOneID),
|
||||
AuthorizationID: MustIDBase16(twoID),
|
||||
Name: "name1",
|
||||
OrgID: MustIDBase16(orgOneID),
|
||||
AuthorizationID: MustIDBase16(twoID),
|
||||
Every: mustDuration("1m"),
|
||||
Query: influxdb.DashboardQuery{
|
||||
Text: script,
|
||||
},
|
||||
Description: "desc2",
|
||||
Status: influxdb.Inactive,
|
||||
StatusMessageTemplate: "msg2",
|
||||
|
@ -500,6 +589,13 @@ func FindCheckByID(
|
|||
deadman1,
|
||||
threshold1,
|
||||
},
|
||||
Authorizations: []*influxdb.Authorization{
|
||||
{
|
||||
ID: MustIDBase16(twoID),
|
||||
Token: "abc123",
|
||||
OrgID: MustIDBase16(orgOneID),
|
||||
},
|
||||
},
|
||||
Organizations: []*influxdb.Organization{
|
||||
{
|
||||
Name: "theorg",
|
||||
|
@ -527,6 +623,13 @@ func FindCheckByID(
|
|||
ID: MustIDBase16(orgOneID),
|
||||
},
|
||||
},
|
||||
Authorizations: []*influxdb.Authorization{
|
||||
{
|
||||
ID: MustIDBase16(twoID),
|
||||
Token: "abc123",
|
||||
OrgID: MustIDBase16(orgOneID),
|
||||
},
|
||||
},
|
||||
},
|
||||
args: args{
|
||||
id: MustIDBase16(threeID),
|
||||
|
@ -805,12 +908,28 @@ func DeleteCheck(
|
|||
{
|
||||
name: "delete checks using exist id",
|
||||
fields: CheckFields{
|
||||
IDGenerator: mock.NewIDGenerator("0000000000000001", t),
|
||||
Organizations: []*influxdb.Organization{
|
||||
{
|
||||
Name: "theorg",
|
||||
ID: MustIDBase16(orgOneID),
|
||||
},
|
||||
},
|
||||
Tasks: []influxdb.TaskCreate{
|
||||
{
|
||||
Flux: `option task = { every: 10s, name: "foo" }
|
||||
data = from(bucket: "telegraf") |> range(start: -1m)`,
|
||||
OrganizationID: MustIDBase16(orgOneID),
|
||||
Token: "abc123",
|
||||
},
|
||||
},
|
||||
Authorizations: []*influxdb.Authorization{
|
||||
{
|
||||
ID: MustIDBase16(twoID),
|
||||
Token: "abc123",
|
||||
OrgID: MustIDBase16(orgOneID),
|
||||
},
|
||||
},
|
||||
Checks: []influxdb.Check{
|
||||
deadman1,
|
||||
threshold1,
|
||||
|
@ -828,16 +947,32 @@ func DeleteCheck(
|
|||
{
|
||||
name: "delete checks using id that does not exist",
|
||||
fields: CheckFields{
|
||||
IDGenerator: mock.NewIDGenerator("0000000000000001", t),
|
||||
Organizations: []*influxdb.Organization{
|
||||
{
|
||||
Name: "theorg",
|
||||
ID: MustIDBase16(orgOneID),
|
||||
},
|
||||
},
|
||||
Tasks: []influxdb.TaskCreate{
|
||||
{
|
||||
Flux: `option task = { every: 10s, name: "foo" }
|
||||
data = from(bucket: "telegraf") |> range(start: -1m)`,
|
||||
OrganizationID: MustIDBase16(orgOneID),
|
||||
Token: "abc123",
|
||||
},
|
||||
},
|
||||
Checks: []influxdb.Check{
|
||||
deadman1,
|
||||
threshold1,
|
||||
},
|
||||
Authorizations: []*influxdb.Authorization{
|
||||
{
|
||||
ID: MustIDBase16(twoID),
|
||||
Token: "abc123",
|
||||
OrgID: MustIDBase16(orgOneID),
|
||||
},
|
||||
},
|
||||
},
|
||||
args: args{
|
||||
ID: "1234567890654321",
|
||||
|
@ -1019,6 +1154,7 @@ func UpdateCheck(
|
|||
{
|
||||
name: "mixed update",
|
||||
fields: CheckFields{
|
||||
IDGenerator: mock.NewIDGenerator("0000000000000001", t),
|
||||
TimeGenerator: mock.TimeGenerator{FakeValue: time.Date(2007, 5, 4, 1, 2, 3, 0, time.UTC)},
|
||||
Organizations: []*influxdb.Organization{
|
||||
{
|
||||
|
@ -1029,18 +1165,38 @@ func UpdateCheck(
|
|||
Checks: []influxdb.Check{
|
||||
deadman1,
|
||||
},
|
||||
Tasks: []influxdb.TaskCreate{
|
||||
{
|
||||
Flux: `option task = { every: 10s, name: "foo" }
|
||||
data = from(bucket: "telegraf") |> range(start: -1m)`,
|
||||
OrganizationID: MustIDBase16(orgOneID),
|
||||
Token: "abc123",
|
||||
},
|
||||
},
|
||||
Authorizations: []*influxdb.Authorization{
|
||||
{
|
||||
ID: MustIDBase16(twoID),
|
||||
Token: "abc123",
|
||||
OrgID: MustIDBase16(orgOneID),
|
||||
},
|
||||
},
|
||||
},
|
||||
args: args{
|
||||
id: MustIDBase16(checkOneID),
|
||||
check: &check.Deadman{
|
||||
Base: check.Base{
|
||||
ID: MustIDBase16(checkTwoID),
|
||||
OrgID: MustIDBase16(orgTwoID),
|
||||
AuthorizationID: MustIDBase16(threeID),
|
||||
ID: MustIDBase16(checkTwoID),
|
||||
OrgID: MustIDBase16(orgOneID),
|
||||
AuthorizationID: MustIDBase16(twoID),
|
||||
Every: mustDuration("1m"),
|
||||
Query: influxdb.DashboardQuery{
|
||||
Text: script,
|
||||
},
|
||||
Name: "changed",
|
||||
Description: "desc changed",
|
||||
Status: inactive,
|
||||
StatusMessageTemplate: "msg2",
|
||||
TaskID: 1,
|
||||
Tags: []notification.Tag{
|
||||
{Key: "k11", Value: "v11"},
|
||||
{Key: "k22", Value: "v22"},
|
||||
|
@ -1059,10 +1215,14 @@ func UpdateCheck(
|
|||
wants: wants{
|
||||
check: &check.Deadman{
|
||||
Base: check.Base{
|
||||
ID: MustIDBase16(checkOneID),
|
||||
OrgID: MustIDBase16(orgOneID),
|
||||
Name: "changed",
|
||||
AuthorizationID: MustIDBase16(threeID),
|
||||
ID: MustIDBase16(checkOneID),
|
||||
OrgID: MustIDBase16(orgOneID),
|
||||
Name: "changed",
|
||||
Every: mustDuration("1m"),
|
||||
AuthorizationID: MustIDBase16(twoID),
|
||||
Query: influxdb.DashboardQuery{
|
||||
Text: script,
|
||||
},
|
||||
Description: "desc changed",
|
||||
Status: influxdb.Inactive,
|
||||
StatusMessageTemplate: "msg2",
|
||||
|
@ -1071,6 +1231,7 @@ func UpdateCheck(
|
|||
{Key: "k22", Value: "v22"},
|
||||
{Key: "k33", Value: "v33"},
|
||||
},
|
||||
TaskID: 1,
|
||||
CRUDLog: influxdb.CRUDLog{
|
||||
CreatedAt: time.Date(2006, 5, 4, 1, 2, 3, 0, time.UTC),
|
||||
UpdatedAt: time.Date(2007, 5, 4, 1, 2, 3, 0, time.UTC),
|
||||
|
@ -1096,8 +1257,13 @@ func UpdateCheck(
|
|||
deadman1,
|
||||
&check.Deadman{
|
||||
Base: check.Base{
|
||||
ID: MustIDBase16(checkTwoID),
|
||||
OrgID: MustIDBase16(orgOneID),
|
||||
ID: MustIDBase16(checkTwoID),
|
||||
OrgID: MustIDBase16(orgOneID),
|
||||
Every: mustDuration("1m"),
|
||||
Query: influxdb.DashboardQuery{
|
||||
Text: script,
|
||||
},
|
||||
TaskID: 1,
|
||||
Name: "check2",
|
||||
AuthorizationID: MustIDBase16(twoID),
|
||||
Status: influxdb.Inactive,
|
||||
|
@ -1105,16 +1271,25 @@ func UpdateCheck(
|
|||
},
|
||||
},
|
||||
},
|
||||
Authorizations: []*influxdb.Authorization{
|
||||
{
|
||||
ID: MustIDBase16(twoID),
|
||||
Token: "abc123",
|
||||
OrgID: MustIDBase16(orgOneID),
|
||||
},
|
||||
},
|
||||
},
|
||||
args: args{
|
||||
id: MustIDBase16(checkOneID),
|
||||
check: &check.Deadman{
|
||||
Base: check.Base{
|
||||
OrgID: MustIDBase16(orgOneID),
|
||||
AuthorizationID: MustIDBase16(threeID),
|
||||
AuthorizationID: MustIDBase16(twoID),
|
||||
Name: "check2",
|
||||
Description: "desc changed",
|
||||
Status: inactive,
|
||||
TaskID: 1,
|
||||
Every: mustDuration("1m"),
|
||||
StatusMessageTemplate: "msg2",
|
||||
Tags: []notification.Tag{
|
||||
{Key: "k11", Value: "v11"},
|
||||
|
@ -1191,6 +1366,13 @@ func PatchCheck(
|
|||
Checks: []influxdb.Check{
|
||||
deadman1,
|
||||
},
|
||||
Authorizations: []*influxdb.Authorization{
|
||||
{
|
||||
ID: MustIDBase16(twoID),
|
||||
Token: "abc123",
|
||||
OrgID: MustIDBase16(orgOneID),
|
||||
},
|
||||
},
|
||||
},
|
||||
args: args{
|
||||
id: MustIDBase16(checkOneID),
|
||||
|
@ -1203,12 +1385,16 @@ func PatchCheck(
|
|||
wants: wants{
|
||||
check: &check.Deadman{
|
||||
Base: check.Base{
|
||||
ID: MustIDBase16(checkOneID),
|
||||
OrgID: MustIDBase16(orgOneID),
|
||||
Name: "changed",
|
||||
AuthorizationID: MustIDBase16(twoID),
|
||||
Description: "desc changed",
|
||||
Status: influxdb.Inactive,
|
||||
ID: MustIDBase16(checkOneID),
|
||||
OrgID: MustIDBase16(orgOneID),
|
||||
Name: "changed",
|
||||
AuthorizationID: MustIDBase16(twoID),
|
||||
Every: mustDuration("1m"),
|
||||
Description: "desc changed",
|
||||
Status: influxdb.Inactive,
|
||||
Query: influxdb.DashboardQuery{
|
||||
Text: script,
|
||||
},
|
||||
StatusMessageTemplate: "msg1",
|
||||
Tags: []notification.Tag{
|
||||
{Key: "k1", Value: "v1"},
|
||||
|
@ -1235,15 +1421,26 @@ func PatchCheck(
|
|||
ID: MustIDBase16(orgOneID),
|
||||
},
|
||||
},
|
||||
Authorizations: []*influxdb.Authorization{
|
||||
{
|
||||
ID: MustIDBase16(twoID),
|
||||
Token: "abc123",
|
||||
OrgID: MustIDBase16(orgOneID),
|
||||
},
|
||||
},
|
||||
Checks: []influxdb.Check{
|
||||
deadman1,
|
||||
&check.Deadman{
|
||||
Base: check.Base{
|
||||
ID: MustIDBase16(checkTwoID),
|
||||
OrgID: MustIDBase16(orgOneID),
|
||||
Name: "check2",
|
||||
AuthorizationID: MustIDBase16(twoID),
|
||||
Status: influxdb.Inactive,
|
||||
ID: MustIDBase16(checkTwoID),
|
||||
OrgID: MustIDBase16(orgOneID),
|
||||
Every: mustDuration("1m"),
|
||||
Name: "check2",
|
||||
AuthorizationID: MustIDBase16(twoID),
|
||||
Status: influxdb.Inactive,
|
||||
Query: influxdb.DashboardQuery{
|
||||
Text: script,
|
||||
},
|
||||
StatusMessageTemplate: "msg1",
|
||||
},
|
||||
},
|
||||
|
|
Loading…
Reference in New Issue