influxdb/kapacitor/client_test.go

746 lines
17 KiB
Go

package kapacitor
import (
"context"
"fmt"
"reflect"
"testing"
"github.com/influxdata/chronograf"
client "github.com/influxdata/kapacitor/client/v1"
)
type MockKapa struct {
ResTask client.Task
ResTasks []client.Task
Error error
client.CreateTaskOptions
client.Link
*client.TaskOptions
*client.ListTasksOptions
client.UpdateTaskOptions
}
func (m *MockKapa) CreateTask(opt client.CreateTaskOptions) (client.Task, error) {
m.CreateTaskOptions = opt
return m.ResTask, m.Error
}
func (m *MockKapa) Task(link client.Link, opt *client.TaskOptions) (client.Task, error) {
m.Link = link
m.TaskOptions = opt
return m.ResTask, m.Error
}
func (m *MockKapa) ListTasks(opt *client.ListTasksOptions) ([]client.Task, error) {
m.ListTasksOptions = opt
return m.ResTasks, m.Error
}
func (m *MockKapa) UpdateTask(link client.Link, opt client.UpdateTaskOptions) (client.Task, error) {
m.Link = link
m.UpdateTaskOptions = opt
return m.ResTask, m.Error
}
func (m *MockKapa) DeleteTask(link client.Link) error {
m.Link = link
return m.Error
}
func TestClient_AllStatus(t *testing.T) {
type fields struct {
URL string
Username string
Password string
ID chronograf.ID
Ticker chronograf.Ticker
kapaClient func(url, username, password string) (KapaClient, error)
}
type args struct {
ctx context.Context
}
kapa := &MockKapa{}
tests := []struct {
name string
fields fields
args args
want map[string]string
wantErr bool
resTask client.Task
resTasks []client.Task
resError error
createTaskOptions client.CreateTaskOptions
link client.Link
taskOptions *client.TaskOptions
listTasksOptions *client.ListTasksOptions
updateTaskOptions client.UpdateTaskOptions
}{
{
name: "return no tasks",
fields: fields{
URL: "http://hill-valley-preservation-society.org",
Username: "ElsaRaven",
Password: "save the clock tower",
kapaClient: func(url, username, password string) (KapaClient, error) {
return kapa, nil
},
},
listTasksOptions: &client.ListTasksOptions{
Fields: []string{"status"},
},
want: map[string]string{},
},
{
name: "return two tasks",
fields: fields{
URL: "http://hill-valley-preservation-society.org",
Username: "ElsaRaven",
Password: "save the clock tower",
kapaClient: func(url, username, password string) (KapaClient, error) {
return kapa, nil
},
},
listTasksOptions: &client.ListTasksOptions{
Fields: []string{"status"},
},
resTasks: []client.Task{
client.Task{
ID: "howdy",
Status: client.Enabled,
},
client.Task{
ID: "doody",
Status: client.Disabled,
},
},
want: map[string]string{
"howdy": "enabled",
"doody": "disabled",
},
},
{
name: "list task error",
fields: fields{
URL: "http://hill-valley-preservation-society.org",
Username: "ElsaRaven",
Password: "save the clock tower",
kapaClient: func(url, username, password string) (KapaClient, error) {
return kapa, nil
},
},
listTasksOptions: &client.ListTasksOptions{
Fields: []string{"status"},
},
resError: fmt.Errorf("this is an error"),
wantErr: true,
},
}
for _, tt := range tests {
kapa.ResTask = tt.resTask
kapa.ResTasks = tt.resTasks
kapa.Error = tt.resError
t.Run(tt.name, func(t *testing.T) {
c := &Client{
URL: tt.fields.URL,
Username: tt.fields.Username,
Password: tt.fields.Password,
ID: tt.fields.ID,
Ticker: tt.fields.Ticker,
kapaClient: tt.fields.kapaClient,
}
got, err := c.AllStatus(tt.args.ctx)
if (err != nil) != tt.wantErr {
t.Errorf("Client.AllStatus() error = %v, wantErr %v", err, tt.wantErr)
return
}
if !reflect.DeepEqual(got, tt.want) {
t.Errorf("Client.AllStatus() = %v, want %v", got, tt.want)
}
if !reflect.DeepEqual(kapa.CreateTaskOptions, tt.createTaskOptions) {
t.Errorf("Client.AllStatus() = createTaskOptions %v, want %v", kapa.CreateTaskOptions, tt.createTaskOptions)
}
if !reflect.DeepEqual(kapa.ListTasksOptions, tt.listTasksOptions) {
t.Errorf("Client.AllStatus() = listTasksOptions %v, want %v", kapa.ListTasksOptions, tt.listTasksOptions)
}
if !reflect.DeepEqual(kapa.TaskOptions, tt.taskOptions) {
t.Errorf("Client.AllStatus() = taskOptions %v, want %v", kapa.TaskOptions, tt.taskOptions)
}
if !reflect.DeepEqual(kapa.ListTasksOptions, tt.listTasksOptions) {
t.Errorf("Client.AllStatus() = listTasksOptions %v, want %v", kapa.ListTasksOptions, tt.listTasksOptions)
}
if !reflect.DeepEqual(kapa.Link, tt.link) {
t.Errorf("Client.AllStatus() = Link %v, want %v", kapa.Link, tt.link)
}
})
}
}
func TestClient_All(t *testing.T) {
type fields struct {
URL string
Username string
Password string
ID chronograf.ID
Ticker chronograf.Ticker
kapaClient func(url, username, password string) (KapaClient, error)
}
type args struct {
ctx context.Context
}
kapa := &MockKapa{}
tests := []struct {
name string
fields fields
args args
want map[string]chronograf.AlertRule
wantErr bool
resTask client.Task
resTasks []client.Task
resError error
createTaskOptions client.CreateTaskOptions
link client.Link
taskOptions *client.TaskOptions
listTasksOptions *client.ListTasksOptions
updateTaskOptions client.UpdateTaskOptions
}{
{
name: "return no tasks",
fields: fields{
kapaClient: func(url, username, password string) (KapaClient, error) {
return kapa, nil
},
},
listTasksOptions: &client.ListTasksOptions{},
want: map[string]chronograf.AlertRule{},
},
{
name: "return a non-reversible task",
fields: fields{
kapaClient: func(url, username, password string) (KapaClient, error) {
return kapa, nil
},
},
listTasksOptions: &client.ListTasksOptions{},
resTasks: []client.Task{
client.Task{
ID: "howdy",
Status: client.Enabled,
},
},
want: map[string]chronograf.AlertRule{
"howdy": chronograf.AlertRule{
ID: "howdy",
Name: "howdy",
TICKScript: "",
},
},
},
{
name: "return a reversible task",
fields: fields{
kapaClient: func(url, username, password string) (KapaClient, error) {
return kapa, nil
},
},
listTasksOptions: &client.ListTasksOptions{},
resTasks: []client.Task{
client.Task{
ID: "rule 1",
Status: client.Enabled,
TICKscript: `var db = '_internal'
var rp = 'monitor'
var measurement = 'cq'
var groupBy = []
var whereFilter = lambda: TRUE
var name = 'rule 1'
var idVar = name + ':{{.Group}}'
var message = ''
var idTag = 'alertID'
var levelTag = 'level'
var messageField = 'message'
var durationField = 'duration'
var outputDB = 'chronograf'
var outputRP = 'autogen'
var outputMeasurement = 'alerts'
var triggerType = 'threshold'
var crit = 90000
var data = stream
|from()
.database(db)
.retentionPolicy(rp)
.measurement(measurement)
.groupBy(groupBy)
.where(whereFilter)
|eval(lambda: "queryOk")
.as('value')
var trigger = data
|alert()
.crit(lambda: "value" > crit)
.stateChangesOnly()
.message(message)
.id(idVar)
.idTag(idTag)
.levelTag(levelTag)
.messageField(messageField)
.durationField(durationField)
trigger
|influxDBOut()
.create()
.database(outputDB)
.retentionPolicy(outputRP)
.measurement(outputMeasurement)
.tag('alertName', name)
.tag('triggerType', triggerType)
trigger
|httpOut('output')
`,
},
},
want: map[string]chronograf.AlertRule{
"rule 1": chronograf.AlertRule{
ID: "rule 1",
Name: "rule 1",
TICKScript: `var db = '_internal'
var rp = 'monitor'
var measurement = 'cq'
var groupBy = []
var whereFilter = lambda: TRUE
var name = 'rule 1'
var idVar = name + ':{{.Group}}'
var message = ''
var idTag = 'alertID'
var levelTag = 'level'
var messageField = 'message'
var durationField = 'duration'
var outputDB = 'chronograf'
var outputRP = 'autogen'
var outputMeasurement = 'alerts'
var triggerType = 'threshold'
var crit = 90000
var data = stream
|from()
.database(db)
.retentionPolicy(rp)
.measurement(measurement)
.groupBy(groupBy)
.where(whereFilter)
|eval(lambda: "queryOk")
.as('value')
var trigger = data
|alert()
.crit(lambda: "value" > crit)
.stateChangesOnly()
.message(message)
.id(idVar)
.idTag(idTag)
.levelTag(levelTag)
.messageField(messageField)
.durationField(durationField)
trigger
|influxDBOut()
.create()
.database(outputDB)
.retentionPolicy(outputRP)
.measurement(outputMeasurement)
.tag('alertName', name)
.tag('triggerType', triggerType)
trigger
|httpOut('output')
`,
Trigger: "threshold",
Alerts: []string{},
TriggerValues: chronograf.TriggerValues{
Operator: "greater than",
Value: "90000",
},
Query: &chronograf.QueryConfig{
Database: "_internal",
RetentionPolicy: "monitor",
Measurement: "cq",
Fields: []chronograf.Field{
{
Field: "queryOk",
Funcs: []string{},
},
},
GroupBy: chronograf.GroupBy{
Tags: []string{},
},
AreTagsAccepted: false,
},
},
},
},
}
for _, tt := range tests {
kapa.ResTask = tt.resTask
kapa.ResTasks = tt.resTasks
kapa.Error = tt.resError
t.Run(tt.name, func(t *testing.T) {
c := &Client{
URL: tt.fields.URL,
Username: tt.fields.Username,
Password: tt.fields.Password,
ID: tt.fields.ID,
Ticker: tt.fields.Ticker,
kapaClient: tt.fields.kapaClient,
}
got, err := c.All(tt.args.ctx)
if (err != nil) != tt.wantErr {
t.Errorf("Client.All() error = %v, wantErr %v", err, tt.wantErr)
return
}
if !reflect.DeepEqual(got, tt.want) {
t.Errorf("Client.All() = %#v, want %#v", got, tt.want)
}
if !reflect.DeepEqual(kapa.CreateTaskOptions, tt.createTaskOptions) {
t.Errorf("Client.All() = createTaskOptions %v, want %v", kapa.CreateTaskOptions, tt.createTaskOptions)
}
if !reflect.DeepEqual(kapa.ListTasksOptions, tt.listTasksOptions) {
t.Errorf("Client.All() = listTasksOptions %v, want %v", kapa.ListTasksOptions, tt.listTasksOptions)
}
if !reflect.DeepEqual(kapa.TaskOptions, tt.taskOptions) {
t.Errorf("Client.All() = taskOptions %v, want %v", kapa.TaskOptions, tt.taskOptions)
}
if !reflect.DeepEqual(kapa.ListTasksOptions, tt.listTasksOptions) {
t.Errorf("Client.All() = listTasksOptions %v, want %v", kapa.ListTasksOptions, tt.listTasksOptions)
}
if !reflect.DeepEqual(kapa.Link, tt.link) {
t.Errorf("Client.All() = Link %v, want %v", kapa.Link, tt.link)
}
})
}
}
func TestClient_Get(t *testing.T) {
type fields struct {
URL string
Username string
Password string
ID chronograf.ID
Ticker chronograf.Ticker
kapaClient func(url, username, password string) (KapaClient, error)
}
type args struct {
ctx context.Context
id string
}
kapa := &MockKapa{}
tests := []struct {
name string
fields fields
args args
want chronograf.AlertRule
wantErr bool
resTask client.Task
resTasks []client.Task
resError error
createTaskOptions client.CreateTaskOptions
link client.Link
taskOptions *client.TaskOptions
listTasksOptions *client.ListTasksOptions
updateTaskOptions client.UpdateTaskOptions
}{
{
name: "return no task",
fields: fields{
kapaClient: func(url, username, password string) (KapaClient, error) {
return kapa, nil
},
},
args: args{
id: "myid",
},
taskOptions: nil,
wantErr: true,
resError: fmt.Errorf("No such task"),
link: client.Link{
Href: "/kapacitor/v1/tasks/myid",
},
},
{
name: "return non-reversible task",
fields: fields{
kapaClient: func(url, username, password string) (KapaClient, error) {
return kapa, nil
},
},
args: args{
id: "myid",
},
taskOptions: nil,
resTask: client.Task{
ID: "myid",
},
want: chronograf.AlertRule{
ID: "myid",
Name: "myid",
},
link: client.Link{
Href: "/kapacitor/v1/tasks/myid",
},
},
{
name: "return reversible task",
fields: fields{
kapaClient: func(url, username, password string) (KapaClient, error) {
return kapa, nil
},
},
args: args{
id: "rule 1",
},
taskOptions: nil,
resTask: client.Task{
ID: "rule 1",
TICKscript: `var db = '_internal'
var rp = 'monitor'
var measurement = 'cq'
var groupBy = []
var whereFilter = lambda: TRUE
var name = 'rule 1'
var idVar = name + ':{{.Group}}'
var message = ''
var idTag = 'alertID'
var levelTag = 'level'
var messageField = 'message'
var durationField = 'duration'
var outputDB = 'chronograf'
var outputRP = 'autogen'
var outputMeasurement = 'alerts'
var triggerType = 'threshold'
var crit = 90000
var data = stream
|from()
.database(db)
.retentionPolicy(rp)
.measurement(measurement)
.groupBy(groupBy)
.where(whereFilter)
|eval(lambda: "queryOk")
.as('value')
var trigger = data
|alert()
.crit(lambda: "value" > crit)
.stateChangesOnly()
.message(message)
.id(idVar)
.idTag(idTag)
.levelTag(levelTag)
.messageField(messageField)
.durationField(durationField)
trigger
|influxDBOut()
.create()
.database(outputDB)
.retentionPolicy(outputRP)
.measurement(outputMeasurement)
.tag('alertName', name)
.tag('triggerType', triggerType)
trigger
|httpOut('output')
`,
},
want: chronograf.AlertRule{
ID: "rule 1",
Name: "rule 1",
TICKScript: `var db = '_internal'
var rp = 'monitor'
var measurement = 'cq'
var groupBy = []
var whereFilter = lambda: TRUE
var name = 'rule 1'
var idVar = name + ':{{.Group}}'
var message = ''
var idTag = 'alertID'
var levelTag = 'level'
var messageField = 'message'
var durationField = 'duration'
var outputDB = 'chronograf'
var outputRP = 'autogen'
var outputMeasurement = 'alerts'
var triggerType = 'threshold'
var crit = 90000
var data = stream
|from()
.database(db)
.retentionPolicy(rp)
.measurement(measurement)
.groupBy(groupBy)
.where(whereFilter)
|eval(lambda: "queryOk")
.as('value')
var trigger = data
|alert()
.crit(lambda: "value" > crit)
.stateChangesOnly()
.message(message)
.id(idVar)
.idTag(idTag)
.levelTag(levelTag)
.messageField(messageField)
.durationField(durationField)
trigger
|influxDBOut()
.create()
.database(outputDB)
.retentionPolicy(outputRP)
.measurement(outputMeasurement)
.tag('alertName', name)
.tag('triggerType', triggerType)
trigger
|httpOut('output')
`,
Trigger: "threshold",
Alerts: []string{},
TriggerValues: chronograf.TriggerValues{
Operator: "greater than",
Value: "90000",
},
Query: &chronograf.QueryConfig{
Database: "_internal",
RetentionPolicy: "monitor",
Measurement: "cq",
Fields: []chronograf.Field{
{
Field: "queryOk",
Funcs: []string{},
},
},
GroupBy: chronograf.GroupBy{
Tags: []string{},
},
AreTagsAccepted: false,
},
},
link: client.Link{
Href: "/kapacitor/v1/tasks/rule 1",
},
},
}
for _, tt := range tests {
kapa.ResTask = tt.resTask
kapa.ResTasks = tt.resTasks
kapa.Error = tt.resError
t.Run(tt.name, func(t *testing.T) {
c := &Client{
URL: tt.fields.URL,
Username: tt.fields.Username,
Password: tt.fields.Password,
ID: tt.fields.ID,
Ticker: tt.fields.Ticker,
kapaClient: tt.fields.kapaClient,
}
got, err := c.Get(tt.args.ctx, tt.args.id)
if (err != nil) != tt.wantErr {
t.Errorf("Client.Get() error = %v, wantErr %v", err, tt.wantErr)
return
}
if !reflect.DeepEqual(got, tt.want) {
t.Errorf("Client.Get() =\n%#v\nwant\n%#v", got, tt.want)
}
if !reflect.DeepEqual(kapa.CreateTaskOptions, tt.createTaskOptions) {
t.Errorf("Client.Get() = createTaskOptions %v, want %v", kapa.CreateTaskOptions, tt.createTaskOptions)
}
if !reflect.DeepEqual(kapa.ListTasksOptions, tt.listTasksOptions) {
t.Errorf("Client.Get() = listTasksOptions %v, want %v", kapa.ListTasksOptions, tt.listTasksOptions)
}
if !reflect.DeepEqual(kapa.TaskOptions, tt.taskOptions) {
t.Errorf("Client.Get() = taskOptions %v, want %v", kapa.TaskOptions, tt.taskOptions)
}
if !reflect.DeepEqual(kapa.ListTasksOptions, tt.listTasksOptions) {
t.Errorf("Client.Get() = listTasksOptions %v, want %v", kapa.ListTasksOptions, tt.listTasksOptions)
}
if !reflect.DeepEqual(kapa.Link, tt.link) {
t.Errorf("Client.Get() = Link %v, want %v", kapa.Link, tt.link)
}
})
}
}