2019-07-25 10:30:25 +00:00
|
|
|
package http
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"context"
|
|
|
|
"encoding/json"
|
|
|
|
"fmt"
|
|
|
|
"io/ioutil"
|
|
|
|
"net/http"
|
|
|
|
"net/http/httptest"
|
|
|
|
"testing"
|
|
|
|
|
2019-08-07 22:34:07 +00:00
|
|
|
"github.com/influxdata/flux/parser"
|
2019-08-16 04:00:55 +00:00
|
|
|
pcontext "github.com/influxdata/influxdb/context"
|
2019-07-25 10:30:25 +00:00
|
|
|
"github.com/influxdata/influxdb/notification"
|
|
|
|
|
|
|
|
"github.com/influxdata/influxdb"
|
|
|
|
"github.com/influxdata/influxdb/mock"
|
|
|
|
"github.com/influxdata/influxdb/notification/check"
|
|
|
|
influxTesting "github.com/influxdata/influxdb/testing"
|
|
|
|
"github.com/julienschmidt/httprouter"
|
|
|
|
"go.uber.org/zap"
|
|
|
|
)
|
|
|
|
|
|
|
|
// NewMockCheckBackend returns a CheckBackend with mock services.
|
|
|
|
func NewMockCheckBackend() *CheckBackend {
|
|
|
|
return &CheckBackend{
|
|
|
|
Logger: zap.NewNop().With(zap.String("handler", "check")),
|
|
|
|
|
|
|
|
CheckService: mock.NewCheckService(),
|
|
|
|
UserResourceMappingService: mock.NewUserResourceMappingService(),
|
|
|
|
LabelService: mock.NewLabelService(),
|
|
|
|
UserService: mock.NewUserService(),
|
|
|
|
OrganizationService: mock.NewOrganizationService(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestService_handleGetChecks(t *testing.T) {
|
|
|
|
type fields struct {
|
|
|
|
CheckService influxdb.CheckService
|
|
|
|
LabelService influxdb.LabelService
|
|
|
|
}
|
|
|
|
type args struct {
|
|
|
|
queryParams map[string][]string
|
|
|
|
}
|
|
|
|
type wants struct {
|
|
|
|
statusCode int
|
|
|
|
contentType string
|
|
|
|
body string
|
|
|
|
}
|
|
|
|
|
|
|
|
fl1 := 100.32
|
|
|
|
fl2 := 200.64
|
2019-08-15 20:51:03 +00:00
|
|
|
fl4 := 100.1
|
|
|
|
fl5 := 3023.2
|
2019-07-25 10:30:25 +00:00
|
|
|
|
|
|
|
tests := []struct {
|
|
|
|
name string
|
|
|
|
fields fields
|
|
|
|
args args
|
|
|
|
wants wants
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
name: "get all checks",
|
|
|
|
fields: fields{
|
|
|
|
&mock.CheckService{
|
|
|
|
FindChecksFn: func(ctx context.Context, filter influxdb.CheckFilter, opts ...influxdb.FindOptions) ([]influxdb.Check, int, error) {
|
|
|
|
return []influxdb.Check{
|
|
|
|
&check.Deadman{
|
|
|
|
Base: check.Base{
|
|
|
|
ID: influxTesting.MustIDBase16("0b501e7e557ab1ed"),
|
|
|
|
Name: "hello",
|
|
|
|
OrgID: influxTesting.MustIDBase16("50f7ba1150f7ba11"),
|
2019-08-07 22:34:07 +00:00
|
|
|
TaskID: 3,
|
2019-07-25 10:30:25 +00:00
|
|
|
},
|
|
|
|
Level: notification.Info,
|
|
|
|
},
|
|
|
|
&check.Threshold{
|
|
|
|
Base: check.Base{
|
|
|
|
ID: influxTesting.MustIDBase16("c0175f0077a77005"),
|
|
|
|
Name: "example",
|
|
|
|
OrgID: influxTesting.MustIDBase16("7e55e118dbabb1ed"),
|
2019-08-07 22:34:07 +00:00
|
|
|
TaskID: 3,
|
2019-07-25 10:30:25 +00:00
|
|
|
},
|
|
|
|
Thresholds: []check.ThresholdConfig{
|
2019-08-15 20:51:03 +00:00
|
|
|
&check.Greater{
|
|
|
|
Value: fl1,
|
|
|
|
ThresholdConfigBase: check.ThresholdConfigBase{Level: notification.Critical},
|
|
|
|
},
|
|
|
|
&check.Lesser{
|
|
|
|
Value: fl2,
|
|
|
|
ThresholdConfigBase: check.ThresholdConfigBase{Level: notification.Info},
|
|
|
|
},
|
|
|
|
&check.Range{Min: fl4, Max: fl5, Within: true},
|
2019-07-25 10:30:25 +00:00
|
|
|
},
|
|
|
|
},
|
|
|
|
}, 2, nil
|
|
|
|
},
|
|
|
|
},
|
|
|
|
&mock.LabelService{
|
|
|
|
FindResourceLabelsFn: func(ctx context.Context, f influxdb.LabelMappingFilter) ([]*influxdb.Label, error) {
|
|
|
|
labels := []*influxdb.Label{
|
|
|
|
{
|
|
|
|
ID: influxTesting.MustIDBase16("fc3dc670a4be9b9a"),
|
|
|
|
Name: "label",
|
|
|
|
Properties: map[string]string{
|
|
|
|
"color": "fff000",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
return labels, nil
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
map[string][]string{
|
|
|
|
"limit": {"1"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
wants: wants{
|
|
|
|
statusCode: http.StatusOK,
|
|
|
|
contentType: "application/json; charset=utf-8",
|
|
|
|
body: `
|
|
|
|
{
|
|
|
|
"links": {
|
|
|
|
"self": "/api/v2/checks?descending=false&limit=1&offset=0",
|
|
|
|
"next": "/api/v2/checks?descending=false&limit=1&offset=1"
|
|
|
|
},
|
|
|
|
"checks": [
|
|
|
|
{
|
|
|
|
"links": {
|
|
|
|
"self": "/api/v2/checks/0b501e7e557ab1ed",
|
|
|
|
"labels": "/api/v2/checks/0b501e7e557ab1ed/labels",
|
|
|
|
"owners": "/api/v2/checks/0b501e7e557ab1ed/owners",
|
|
|
|
"members": "/api/v2/checks/0b501e7e557ab1ed/members"
|
|
|
|
},
|
2019-09-18 20:19:51 +00:00
|
|
|
"createdAt": "0001-01-01T00:00:00Z",
|
|
|
|
"updatedAt": "0001-01-01T00:00:00Z",
|
2019-07-25 10:30:25 +00:00
|
|
|
"id": "0b501e7e557ab1ed",
|
2019-09-18 20:19:51 +00:00
|
|
|
"orgID": "50f7ba1150f7ba11",
|
|
|
|
"name": "hello",
|
|
|
|
"level": "INFO",
|
|
|
|
"query": {
|
|
|
|
"builderConfig": {
|
|
|
|
"aggregateWindow": {
|
|
|
|
"period": ""
|
|
|
|
},
|
|
|
|
"buckets": null,
|
|
|
|
"functions": null,
|
|
|
|
"tags": null
|
|
|
|
},
|
|
|
|
"editMode": "",
|
|
|
|
"name": "",
|
|
|
|
"text": ""
|
|
|
|
},
|
|
|
|
"reportZero": false,
|
|
|
|
"statusMessageTemplate": "",
|
|
|
|
"tags": null,
|
|
|
|
"type": "deadman",
|
2019-07-25 10:30:25 +00:00
|
|
|
"labels": [
|
|
|
|
{
|
|
|
|
"id": "fc3dc670a4be9b9a",
|
|
|
|
"name": "label",
|
|
|
|
"properties": {
|
|
|
|
"color": "fff000"
|
|
|
|
}
|
|
|
|
}
|
2019-09-18 20:19:51 +00:00
|
|
|
],
|
|
|
|
"status": "active"
|
2019-07-25 10:30:25 +00:00
|
|
|
},
|
|
|
|
{
|
|
|
|
"links": {
|
|
|
|
"self": "/api/v2/checks/c0175f0077a77005",
|
|
|
|
"labels": "/api/v2/checks/c0175f0077a77005/labels",
|
|
|
|
"members": "/api/v2/checks/c0175f0077a77005/members",
|
|
|
|
"owners": "/api/v2/checks/c0175f0077a77005/owners"
|
|
|
|
},
|
2019-09-18 20:19:51 +00:00
|
|
|
"createdAt": "0001-01-01T00:00:00Z",
|
|
|
|
"updatedAt": "0001-01-01T00:00:00Z",
|
2019-07-25 10:30:25 +00:00
|
|
|
"id": "c0175f0077a77005",
|
|
|
|
"orgID": "7e55e118dbabb1ed",
|
|
|
|
"name": "example",
|
2019-09-18 20:19:51 +00:00
|
|
|
"query": {
|
|
|
|
"builderConfig": {
|
|
|
|
"aggregateWindow": {
|
|
|
|
"period": ""
|
|
|
|
},
|
|
|
|
"buckets": null,
|
|
|
|
"functions": null,
|
|
|
|
"tags": null
|
|
|
|
},
|
|
|
|
"editMode": "",
|
|
|
|
"name": "",
|
|
|
|
"text": ""
|
|
|
|
},
|
|
|
|
"statusMessageTemplate": "",
|
|
|
|
"tags": null,
|
|
|
|
"thresholds": [
|
|
|
|
{
|
|
|
|
"allValues": false,
|
|
|
|
"level": "CRIT",
|
|
|
|
"type": "greater",
|
|
|
|
"value": 100.32
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"allValues": false,
|
|
|
|
"level": "INFO",
|
|
|
|
"type": "lesser",
|
|
|
|
"value": 200.64
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"allValues": false,
|
|
|
|
"level": "UNKNOWN",
|
|
|
|
"max": 3023.2,
|
|
|
|
"min": 100.1,
|
|
|
|
"type": "range",
|
|
|
|
"within": true
|
|
|
|
}
|
|
|
|
],
|
|
|
|
"type": "threshold",
|
|
|
|
"labels": [
|
|
|
|
{
|
|
|
|
"id": "fc3dc670a4be9b9a",
|
|
|
|
"name": "label",
|
|
|
|
"properties": {
|
|
|
|
"color": "fff000"
|
|
|
|
}
|
|
|
|
}
|
|
|
|
],
|
|
|
|
"status": "active"
|
|
|
|
}
|
|
|
|
]
|
2019-07-25 10:30:25 +00:00
|
|
|
}
|
|
|
|
`,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "get all checks when there are none",
|
|
|
|
fields: fields{
|
|
|
|
&mock.CheckService{
|
|
|
|
FindChecksFn: func(ctx context.Context, filter influxdb.CheckFilter, opts ...influxdb.FindOptions) ([]influxdb.Check, int, error) {
|
|
|
|
return []influxdb.Check{}, 0, nil
|
|
|
|
},
|
|
|
|
},
|
|
|
|
&mock.LabelService{},
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
map[string][]string{
|
|
|
|
"limit": {"1"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
wants: wants{
|
|
|
|
statusCode: http.StatusOK,
|
|
|
|
contentType: "application/json; charset=utf-8",
|
|
|
|
body: `
|
|
|
|
{
|
|
|
|
"links": {
|
|
|
|
"self": "/api/v2/checks?descending=false&limit=1&offset=0"
|
|
|
|
},
|
|
|
|
"checks": []
|
|
|
|
}`,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, tt := range tests {
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
checkBackend := NewMockCheckBackend()
|
|
|
|
checkBackend.CheckService = tt.fields.CheckService
|
|
|
|
checkBackend.LabelService = tt.fields.LabelService
|
2019-09-18 20:19:51 +00:00
|
|
|
checkBackend.TaskService = &mock.TaskService{
|
|
|
|
FindTaskByIDFn: func(ctx context.Context, id influxdb.ID) (*influxdb.Task, error) {
|
|
|
|
return &influxdb.Task{Status: "active"}, nil
|
|
|
|
},
|
|
|
|
}
|
2019-07-25 10:30:25 +00:00
|
|
|
h := NewCheckHandler(checkBackend)
|
|
|
|
|
|
|
|
r := httptest.NewRequest("GET", "http://any.url", nil)
|
|
|
|
|
|
|
|
qp := r.URL.Query()
|
|
|
|
for k, vs := range tt.args.queryParams {
|
|
|
|
for _, v := range vs {
|
|
|
|
qp.Add(k, v)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
r.URL.RawQuery = qp.Encode()
|
2019-10-21 18:11:08 +00:00
|
|
|
r = r.WithContext(pcontext.SetAuthorizer(r.Context(), &influxdb.Session{UserID: influxTesting.MustIDBase16("6f626f7274697321")}))
|
2019-07-25 10:30:25 +00:00
|
|
|
|
|
|
|
w := httptest.NewRecorder()
|
|
|
|
|
|
|
|
h.handleGetChecks(w, r)
|
|
|
|
|
|
|
|
res := w.Result()
|
|
|
|
content := res.Header.Get("Content-Type")
|
|
|
|
body, _ := ioutil.ReadAll(res.Body)
|
|
|
|
|
|
|
|
if res.StatusCode != tt.wants.statusCode {
|
|
|
|
t.Errorf("%q. handleGetChecks() = %v, want %v", tt.name, res.StatusCode, tt.wants.statusCode)
|
|
|
|
}
|
|
|
|
if tt.wants.contentType != "" && content != tt.wants.contentType {
|
|
|
|
t.Errorf("%q. handleGetChecks() = %v, want %v", tt.name, content, tt.wants.contentType)
|
|
|
|
}
|
|
|
|
if eq, diff, err := jsonEqual(string(body), tt.wants.body); err != nil || tt.wants.body != "" && !eq {
|
2019-09-18 20:19:51 +00:00
|
|
|
t.Errorf("%v", err)
|
2019-07-25 10:30:25 +00:00
|
|
|
t.Errorf("%q. handleGetChecks() = ***%v***", tt.name, diff)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-08-16 19:43:15 +00:00
|
|
|
func mustDuration(d string) *notification.Duration {
|
2019-08-07 22:34:07 +00:00
|
|
|
dur, err := parser.ParseDuration(d)
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
|
2019-08-16 19:43:15 +00:00
|
|
|
return (*notification.Duration)(dur)
|
2019-08-07 22:34:07 +00:00
|
|
|
}
|
|
|
|
|
2019-08-22 16:18:02 +00:00
|
|
|
func TestService_handleGetCheckQuery(t *testing.T) {
|
|
|
|
type fields struct {
|
|
|
|
CheckService influxdb.CheckService
|
|
|
|
}
|
|
|
|
var l float64 = 10
|
|
|
|
var u float64 = 40
|
|
|
|
type args struct {
|
|
|
|
id string
|
|
|
|
}
|
|
|
|
type wants struct {
|
|
|
|
statusCode int
|
|
|
|
contentType string
|
|
|
|
body string
|
|
|
|
}
|
|
|
|
tests := []struct {
|
|
|
|
name string
|
|
|
|
fields fields
|
|
|
|
args args
|
|
|
|
wants wants
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
name: "get a check query by id",
|
|
|
|
fields: fields{
|
|
|
|
&mock.CheckService{
|
|
|
|
FindCheckByIDFn: func(ctx context.Context, id influxdb.ID) (influxdb.Check, error) {
|
|
|
|
if id == influxTesting.MustIDBase16("020f755c3c082000") {
|
|
|
|
return &check.Threshold{
|
|
|
|
Base: check.Base{
|
|
|
|
ID: influxTesting.MustIDBase16("020f755c3c082000"),
|
|
|
|
OrgID: influxTesting.MustIDBase16("020f755c3c082000"),
|
|
|
|
Name: "hello",
|
|
|
|
TaskID: 3,
|
2019-08-28 16:25:54 +00:00
|
|
|
Tags: []influxdb.Tag{
|
2019-08-22 16:18:02 +00:00
|
|
|
{Key: "aaa", Value: "vaaa"},
|
|
|
|
{Key: "bbb", Value: "vbbb"},
|
|
|
|
},
|
|
|
|
Every: mustDuration("1h"),
|
|
|
|
StatusMessageTemplate: "whoa! {check.yeah}",
|
|
|
|
Query: influxdb.DashboardQuery{
|
|
|
|
Text: `from(bucket: "foo") |> range(start: -1d, stop: now()) |> aggregateWindow(every: 1m, fn: mean) |> yield()`,
|
2019-08-27 17:29:49 +00:00
|
|
|
BuilderConfig: influxdb.BuilderConfig{
|
|
|
|
Tags: []struct {
|
|
|
|
Key string `json:"key"`
|
|
|
|
Values []string `json:"values"`
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
Key: "_field",
|
|
|
|
Values: []string{"usage_user"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
2019-08-22 16:18:02 +00:00
|
|
|
},
|
|
|
|
},
|
|
|
|
Thresholds: []check.ThresholdConfig{
|
|
|
|
check.Greater{
|
|
|
|
ThresholdConfigBase: check.ThresholdConfigBase{
|
|
|
|
Level: notification.Ok,
|
|
|
|
},
|
|
|
|
Value: l,
|
|
|
|
},
|
|
|
|
check.Lesser{
|
|
|
|
ThresholdConfigBase: check.ThresholdConfigBase{
|
|
|
|
Level: notification.Info,
|
|
|
|
},
|
|
|
|
Value: u,
|
|
|
|
},
|
|
|
|
check.Range{
|
|
|
|
ThresholdConfigBase: check.ThresholdConfigBase{
|
|
|
|
Level: notification.Warn,
|
|
|
|
},
|
|
|
|
Min: l,
|
|
|
|
Max: u,
|
|
|
|
Within: true,
|
|
|
|
},
|
|
|
|
check.Range{
|
|
|
|
ThresholdConfigBase: check.ThresholdConfigBase{
|
|
|
|
Level: notification.Critical,
|
|
|
|
},
|
|
|
|
Min: l,
|
|
|
|
Max: u,
|
|
|
|
Within: true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}, nil
|
|
|
|
}
|
|
|
|
return nil, fmt.Errorf("not found")
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
id: "020f755c3c082000",
|
|
|
|
},
|
|
|
|
wants: wants{
|
|
|
|
statusCode: http.StatusOK,
|
|
|
|
contentType: "application/json; charset=utf-8",
|
2019-08-30 14:54:16 +00:00
|
|
|
body: `{"flux":"package main\nimport \"influxdata/influxdb/monitor\"\nimport \"influxdata/influxdb/v1\"\n\ndata = from(bucket: \"foo\")\n\t|\u003e range(start: -1h)\n\t|\u003e aggregateWindow(every: 1h, fn: mean, createEmpty: false)\n\noption task = {name: \"hello\", every: 1h}\n\ncheck = {\n\t_check_id: \"020f755c3c082000\",\n\t_check_name: \"hello\",\n\t_type: \"threshold\",\n\ttags: {aaa: \"vaaa\", bbb: \"vbbb\"},\n}\nok = (r) =\u003e\n\t(r.usage_user \u003e 10.0)\ninfo = (r) =\u003e\n\t(r.usage_user \u003c 40.0)\nwarn = (r) =\u003e\n\t(r.usage_user \u003c 40.0 and r.usage_user \u003e 10.0)\ncrit = (r) =\u003e\n\t(r.usage_user \u003c 40.0 and r.usage_user \u003e 10.0)\nmessageFn = (r) =\u003e\n\t(\"whoa! {check.yeah}\")\n\ndata\n\t|\u003e v1.fieldsAsCols()\n\t|\u003e monitor.check(\n\t\tdata: check,\n\t\tmessageFn: messageFn,\n\t\tok: ok,\n\t\tinfo: info,\n\t\twarn: warn,\n\t\tcrit: crit,\n\t)"}`,
|
2019-08-22 16:18:02 +00:00
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
checkBackend := NewMockCheckBackend()
|
|
|
|
checkBackend.HTTPErrorHandler = ErrorHandler(0)
|
|
|
|
checkBackend.CheckService = tt.fields.CheckService
|
2019-09-18 20:19:51 +00:00
|
|
|
checkBackend.TaskService = &mock.TaskService{
|
|
|
|
FindTaskByIDFn: func(ctx context.Context, id influxdb.ID) (*influxdb.Task, error) {
|
|
|
|
return &influxdb.Task{}, nil
|
|
|
|
},
|
|
|
|
}
|
2019-08-22 16:18:02 +00:00
|
|
|
h := NewCheckHandler(checkBackend)
|
|
|
|
|
|
|
|
r := httptest.NewRequest("GET", "http://any.url", nil)
|
|
|
|
|
|
|
|
r = r.WithContext(context.WithValue(
|
|
|
|
context.Background(),
|
|
|
|
httprouter.ParamsKey,
|
|
|
|
httprouter.Params{
|
|
|
|
{
|
|
|
|
Key: "id",
|
|
|
|
Value: tt.args.id,
|
|
|
|
},
|
|
|
|
}))
|
|
|
|
|
|
|
|
w := httptest.NewRecorder()
|
|
|
|
|
|
|
|
h.handleGetCheckQuery(w, r)
|
|
|
|
|
|
|
|
res := w.Result()
|
|
|
|
content := res.Header.Get("Content-Type")
|
|
|
|
body, _ := ioutil.ReadAll(res.Body)
|
|
|
|
|
|
|
|
if res.StatusCode != tt.wants.statusCode {
|
|
|
|
t.Errorf("%q. handleGetCheckQuery() = %v, want %v", tt.name, res.StatusCode, tt.wants.statusCode)
|
|
|
|
}
|
|
|
|
if tt.wants.contentType != "" && content != tt.wants.contentType {
|
|
|
|
t.Errorf("%q. handleGetCheckQuery() = %v, want %v", tt.name, content, tt.wants.contentType)
|
|
|
|
}
|
|
|
|
if eq, diff, err := jsonEqual(string(body), tt.wants.body); err != nil || tt.wants.body != "" && !eq {
|
|
|
|
t.Errorf("%q. handleGetChecks() = ***%v***", tt.name, diff)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-07-25 10:30:25 +00:00
|
|
|
func TestService_handleGetCheck(t *testing.T) {
|
|
|
|
type fields struct {
|
|
|
|
CheckService influxdb.CheckService
|
|
|
|
}
|
|
|
|
type args struct {
|
|
|
|
id string
|
|
|
|
}
|
|
|
|
type wants struct {
|
|
|
|
statusCode int
|
|
|
|
contentType string
|
|
|
|
body string
|
|
|
|
}
|
|
|
|
|
|
|
|
tests := []struct {
|
|
|
|
name string
|
|
|
|
fields fields
|
|
|
|
args args
|
|
|
|
wants wants
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
name: "get a check by id",
|
|
|
|
fields: fields{
|
|
|
|
&mock.CheckService{
|
|
|
|
FindCheckByIDFn: func(ctx context.Context, id influxdb.ID) (influxdb.Check, error) {
|
|
|
|
if id == influxTesting.MustIDBase16("020f755c3c082000") {
|
|
|
|
return &check.Deadman{
|
|
|
|
Base: check.Base{
|
|
|
|
ID: influxTesting.MustIDBase16("020f755c3c082000"),
|
|
|
|
OrgID: influxTesting.MustIDBase16("020f755c3c082000"),
|
|
|
|
Name: "hello",
|
2019-08-07 22:34:07 +00:00
|
|
|
Every: mustDuration("3h"),
|
|
|
|
TaskID: 3,
|
2019-07-25 10:30:25 +00:00
|
|
|
},
|
|
|
|
Level: notification.Critical,
|
|
|
|
}, nil
|
|
|
|
}
|
|
|
|
return nil, fmt.Errorf("not found")
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
id: "020f755c3c082000",
|
|
|
|
},
|
|
|
|
wants: wants{
|
|
|
|
statusCode: http.StatusOK,
|
|
|
|
contentType: "application/json; charset=utf-8",
|
|
|
|
body: `
|
|
|
|
{
|
|
|
|
"links": {
|
|
|
|
"self": "/api/v2/checks/020f755c3c082000",
|
|
|
|
"labels": "/api/v2/checks/020f755c3c082000/labels",
|
|
|
|
"members": "/api/v2/checks/020f755c3c082000/members",
|
|
|
|
"owners": "/api/v2/checks/020f755c3c082000/owners"
|
|
|
|
},
|
|
|
|
"labels": [],
|
|
|
|
"level": "CRIT",
|
2019-08-07 22:34:07 +00:00
|
|
|
"every": "3h",
|
2019-07-25 10:30:25 +00:00
|
|
|
"createdAt": "0001-01-01T00:00:00Z",
|
|
|
|
"updatedAt": "0001-01-01T00:00:00Z",
|
|
|
|
"id": "020f755c3c082000",
|
|
|
|
"query": {
|
|
|
|
"builderConfig": {
|
|
|
|
"aggregateWindow": {
|
|
|
|
"period": ""
|
|
|
|
},
|
|
|
|
"buckets": null,
|
|
|
|
"functions": null,
|
|
|
|
"tags": null
|
|
|
|
},
|
|
|
|
"editMode": "",
|
|
|
|
"name": "",
|
|
|
|
"text": ""
|
|
|
|
},
|
|
|
|
"reportZero": false,
|
|
|
|
"status": "active",
|
|
|
|
"statusMessageTemplate": "",
|
|
|
|
"tags": null,
|
|
|
|
"type": "deadman",
|
|
|
|
"orgID": "020f755c3c082000",
|
2019-09-18 20:19:51 +00:00
|
|
|
"name": "hello",
|
|
|
|
"status": "active"
|
2019-07-25 10:30:25 +00:00
|
|
|
}
|
|
|
|
`,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "not found",
|
|
|
|
fields: fields{
|
|
|
|
&mock.CheckService{
|
|
|
|
FindCheckByIDFn: func(ctx context.Context, id influxdb.ID) (influxdb.Check, error) {
|
|
|
|
return nil, &influxdb.Error{
|
|
|
|
Code: influxdb.ENotFound,
|
|
|
|
Msg: "check not found",
|
|
|
|
}
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
id: "020f755c3c082000",
|
|
|
|
},
|
|
|
|
wants: wants{
|
|
|
|
statusCode: http.StatusNotFound,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, tt := range tests {
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
checkBackend := NewMockCheckBackend()
|
|
|
|
checkBackend.HTTPErrorHandler = ErrorHandler(0)
|
|
|
|
checkBackend.CheckService = tt.fields.CheckService
|
2019-09-18 20:19:51 +00:00
|
|
|
checkBackend.TaskService = &mock.TaskService{
|
|
|
|
FindTaskByIDFn: func(ctx context.Context, id influxdb.ID) (*influxdb.Task, error) {
|
|
|
|
return &influxdb.Task{Status: "active"}, nil
|
|
|
|
},
|
|
|
|
}
|
2019-07-25 10:30:25 +00:00
|
|
|
h := NewCheckHandler(checkBackend)
|
|
|
|
|
|
|
|
r := httptest.NewRequest("GET", "http://any.url", nil)
|
|
|
|
|
|
|
|
r = r.WithContext(context.WithValue(
|
|
|
|
context.Background(),
|
|
|
|
httprouter.ParamsKey,
|
|
|
|
httprouter.Params{
|
|
|
|
{
|
|
|
|
Key: "id",
|
|
|
|
Value: tt.args.id,
|
|
|
|
},
|
|
|
|
}))
|
|
|
|
|
|
|
|
w := httptest.NewRecorder()
|
|
|
|
|
|
|
|
h.handleGetCheck(w, r)
|
|
|
|
|
|
|
|
res := w.Result()
|
|
|
|
content := res.Header.Get("Content-Type")
|
|
|
|
body, _ := ioutil.ReadAll(res.Body)
|
|
|
|
t.Logf(res.Header.Get("X-Influx-Error"))
|
|
|
|
|
|
|
|
if res.StatusCode != tt.wants.statusCode {
|
|
|
|
t.Errorf("%q. handleGetCheck() = %v, want %v", tt.name, res.StatusCode, tt.wants.statusCode)
|
|
|
|
}
|
|
|
|
if tt.wants.contentType != "" && content != tt.wants.contentType {
|
|
|
|
t.Errorf("%q. handleGetCheck() = %v, want %v", tt.name, content, tt.wants.contentType)
|
|
|
|
}
|
|
|
|
if tt.wants.body != "" {
|
|
|
|
if eq, diff, err := jsonEqual(string(body), tt.wants.body); err != nil {
|
|
|
|
t.Errorf("%q, handleGetCheck(). error unmarshaling json %v", tt.name, err)
|
|
|
|
} else if !eq {
|
|
|
|
t.Errorf("%q. handleGetCheck() = ***%s***", tt.name, diff)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestService_handlePostCheck(t *testing.T) {
|
|
|
|
type fields struct {
|
|
|
|
CheckService influxdb.CheckService
|
|
|
|
OrganizationService influxdb.OrganizationService
|
|
|
|
}
|
|
|
|
type args struct {
|
2019-08-16 04:00:55 +00:00
|
|
|
userID influxdb.ID
|
|
|
|
check influxdb.Check
|
2019-07-25 10:30:25 +00:00
|
|
|
}
|
|
|
|
type wants struct {
|
|
|
|
statusCode int
|
|
|
|
contentType string
|
|
|
|
body string
|
|
|
|
}
|
|
|
|
|
|
|
|
tests := []struct {
|
|
|
|
name string
|
|
|
|
fields fields
|
|
|
|
args args
|
|
|
|
wants wants
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
name: "create a new check",
|
|
|
|
fields: fields{
|
|
|
|
CheckService: &mock.CheckService{
|
2019-09-18 20:19:51 +00:00
|
|
|
CreateCheckFn: func(ctx context.Context, c influxdb.CheckCreate, userID influxdb.ID) error {
|
2019-07-25 10:30:25 +00:00
|
|
|
c.SetID(influxTesting.MustIDBase16("020f755c3c082000"))
|
2019-08-16 04:00:55 +00:00
|
|
|
c.SetOwnerID(userID)
|
2019-07-25 10:30:25 +00:00
|
|
|
return nil
|
|
|
|
},
|
|
|
|
},
|
|
|
|
OrganizationService: &mock.OrganizationService{
|
|
|
|
FindOrganizationF: func(ctx context.Context, f influxdb.OrganizationFilter) (*influxdb.Organization, error) {
|
|
|
|
return &influxdb.Organization{ID: influxTesting.MustIDBase16("6f626f7274697320")}, nil
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
args: args{
|
2019-08-16 04:00:55 +00:00
|
|
|
userID: influxTesting.MustIDBase16("6f626f7274697321"),
|
2019-07-25 10:30:25 +00:00
|
|
|
check: &check.Deadman{
|
|
|
|
Base: check.Base{
|
|
|
|
Name: "hello",
|
|
|
|
OrgID: influxTesting.MustIDBase16("6f626f7274697320"),
|
2019-08-16 11:12:28 +00:00
|
|
|
OwnerID: influxTesting.MustIDBase16("6f626f7274697321"),
|
2019-07-25 10:30:25 +00:00
|
|
|
Description: "desc1",
|
|
|
|
StatusMessageTemplate: "msg1",
|
2019-08-07 22:34:07 +00:00
|
|
|
Every: mustDuration("5m"),
|
|
|
|
TaskID: 3,
|
2019-08-28 16:25:54 +00:00
|
|
|
Tags: []influxdb.Tag{
|
2019-07-25 10:30:25 +00:00
|
|
|
{Key: "k1", Value: "v1"},
|
|
|
|
{Key: "k2", Value: "v2"},
|
|
|
|
},
|
|
|
|
},
|
2019-08-28 14:16:38 +00:00
|
|
|
TimeSince: mustDuration("13s"),
|
2019-07-25 10:30:25 +00:00
|
|
|
ReportZero: true,
|
|
|
|
Level: notification.Warn,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
wants: wants{
|
|
|
|
statusCode: http.StatusCreated,
|
|
|
|
contentType: "application/json; charset=utf-8",
|
|
|
|
body: `
|
|
|
|
{
|
|
|
|
"links": {
|
|
|
|
"self": "/api/v2/checks/020f755c3c082000",
|
|
|
|
"labels": "/api/v2/checks/020f755c3c082000/labels",
|
|
|
|
"members": "/api/v2/checks/020f755c3c082000/members",
|
|
|
|
"owners": "/api/v2/checks/020f755c3c082000/owners"
|
|
|
|
},
|
|
|
|
"reportZero": true,
|
|
|
|
"statusMessageTemplate": "msg1",
|
|
|
|
"tags": [
|
|
|
|
{
|
|
|
|
"key": "k1",
|
|
|
|
"value": "v1"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"key": "k2",
|
|
|
|
"value": "v2"
|
|
|
|
}
|
|
|
|
],
|
|
|
|
"query": {
|
|
|
|
"builderConfig": {
|
|
|
|
"aggregateWindow": {
|
|
|
|
"period": ""
|
|
|
|
},
|
|
|
|
"buckets": null,
|
|
|
|
"functions": null,
|
|
|
|
"tags": null
|
|
|
|
},
|
|
|
|
"editMode": "",
|
|
|
|
"name": "",
|
|
|
|
"text": ""
|
|
|
|
},
|
|
|
|
"type": "deadman",
|
2019-08-28 14:16:38 +00:00
|
|
|
"timeSince": "13s",
|
2019-07-25 10:30:25 +00:00
|
|
|
"createdAt": "0001-01-01T00:00:00Z",
|
|
|
|
"updatedAt": "0001-01-01T00:00:00Z",
|
|
|
|
"id": "020f755c3c082000",
|
|
|
|
"orgID": "6f626f7274697320",
|
|
|
|
"name": "hello",
|
2019-08-16 04:00:55 +00:00
|
|
|
"ownerID": "6f626f7274697321",
|
2019-07-25 10:30:25 +00:00
|
|
|
"description": "desc1",
|
2019-08-07 22:34:07 +00:00
|
|
|
"every": "5m",
|
2019-07-25 10:30:25 +00:00
|
|
|
"level": "WARN",
|
2019-09-18 20:19:51 +00:00
|
|
|
"labels": [],
|
|
|
|
"status": "active"
|
2019-07-25 10:30:25 +00:00
|
|
|
}
|
|
|
|
`,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, tt := range tests {
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
checkBackend := NewMockCheckBackend()
|
|
|
|
checkBackend.CheckService = tt.fields.CheckService
|
|
|
|
checkBackend.OrganizationService = tt.fields.OrganizationService
|
2019-09-18 20:19:51 +00:00
|
|
|
checkBackend.TaskService = &mock.TaskService{
|
|
|
|
FindTaskByIDFn: func(ctx context.Context, id influxdb.ID) (*influxdb.Task, error) {
|
|
|
|
return &influxdb.Task{Status: "active"}, nil
|
|
|
|
},
|
|
|
|
}
|
2019-07-25 10:30:25 +00:00
|
|
|
h := NewCheckHandler(checkBackend)
|
|
|
|
|
|
|
|
b, err := json.Marshal(tt.args.check)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("failed to unmarshal check: %v", err)
|
|
|
|
}
|
|
|
|
r := httptest.NewRequest("GET", "http://any.url?org=30", bytes.NewReader(b))
|
|
|
|
w := httptest.NewRecorder()
|
2019-08-16 04:00:55 +00:00
|
|
|
r = r.WithContext(pcontext.SetAuthorizer(r.Context(), &influxdb.Session{UserID: tt.args.userID}))
|
2019-07-25 10:30:25 +00:00
|
|
|
|
|
|
|
h.handlePostCheck(w, r)
|
|
|
|
|
|
|
|
res := w.Result()
|
|
|
|
content := res.Header.Get("Content-Type")
|
|
|
|
body, _ := ioutil.ReadAll(res.Body)
|
|
|
|
|
|
|
|
if res.StatusCode != tt.wants.statusCode {
|
|
|
|
t.Errorf("%q. handlePostCheck() = %v, want %v", tt.name, res.StatusCode, tt.wants.statusCode)
|
|
|
|
}
|
|
|
|
if tt.wants.contentType != "" && content != tt.wants.contentType {
|
|
|
|
t.Errorf("%q. handlePostCheck() = %v, want %v", tt.name, content, tt.wants.contentType)
|
|
|
|
}
|
|
|
|
if tt.wants.body != "" {
|
|
|
|
if eq, diff, err := jsonEqual(string(body), tt.wants.body); err != nil {
|
|
|
|
t.Errorf("%q, handlePostCheck(). error unmarshaling json %v", tt.name, err)
|
|
|
|
} else if !eq {
|
|
|
|
t.Errorf("%q. handlePostCheck() = ***%s***", tt.name, diff)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestService_handleDeleteCheck(t *testing.T) {
|
|
|
|
type fields struct {
|
|
|
|
CheckService influxdb.CheckService
|
|
|
|
}
|
|
|
|
type args struct {
|
|
|
|
id string
|
|
|
|
}
|
|
|
|
type wants struct {
|
|
|
|
statusCode int
|
|
|
|
contentType string
|
|
|
|
body string
|
|
|
|
}
|
|
|
|
|
|
|
|
tests := []struct {
|
|
|
|
name string
|
|
|
|
fields fields
|
|
|
|
args args
|
|
|
|
wants wants
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
name: "remove a check by id",
|
|
|
|
fields: fields{
|
|
|
|
&mock.CheckService{
|
|
|
|
DeleteCheckFn: func(ctx context.Context, id influxdb.ID) error {
|
|
|
|
if id == influxTesting.MustIDBase16("020f755c3c082000") {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
return fmt.Errorf("wrong id")
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
id: "020f755c3c082000",
|
|
|
|
},
|
|
|
|
wants: wants{
|
|
|
|
statusCode: http.StatusNoContent,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "check not found",
|
|
|
|
fields: fields{
|
|
|
|
&mock.CheckService{
|
|
|
|
DeleteCheckFn: func(ctx context.Context, id influxdb.ID) error {
|
|
|
|
return &influxdb.Error{
|
|
|
|
Code: influxdb.ENotFound,
|
|
|
|
Msg: "check not found",
|
|
|
|
}
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
id: "020f755c3c082000",
|
|
|
|
},
|
|
|
|
wants: wants{
|
|
|
|
statusCode: http.StatusNotFound,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, tt := range tests {
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
checkBackend := NewMockCheckBackend()
|
|
|
|
checkBackend.HTTPErrorHandler = ErrorHandler(0)
|
|
|
|
checkBackend.CheckService = tt.fields.CheckService
|
2019-09-18 20:19:51 +00:00
|
|
|
checkBackend.TaskService = &mock.TaskService{
|
|
|
|
FindTaskByIDFn: func(ctx context.Context, id influxdb.ID) (*influxdb.Task, error) {
|
|
|
|
return &influxdb.Task{}, nil
|
|
|
|
},
|
|
|
|
}
|
2019-07-25 10:30:25 +00:00
|
|
|
h := NewCheckHandler(checkBackend)
|
|
|
|
|
|
|
|
r := httptest.NewRequest("GET", "http://any.url", nil)
|
|
|
|
|
|
|
|
r = r.WithContext(context.WithValue(
|
|
|
|
context.Background(),
|
|
|
|
httprouter.ParamsKey,
|
|
|
|
httprouter.Params{
|
|
|
|
{
|
|
|
|
Key: "id",
|
|
|
|
Value: tt.args.id,
|
|
|
|
},
|
|
|
|
}))
|
|
|
|
|
|
|
|
w := httptest.NewRecorder()
|
|
|
|
|
|
|
|
h.handleDeleteCheck(w, r)
|
|
|
|
|
|
|
|
res := w.Result()
|
|
|
|
content := res.Header.Get("Content-Type")
|
|
|
|
body, _ := ioutil.ReadAll(res.Body)
|
|
|
|
|
|
|
|
if res.StatusCode != tt.wants.statusCode {
|
|
|
|
t.Errorf("%q. handleDeleteCheck() = %v, want %v", tt.name, res.StatusCode, tt.wants.statusCode)
|
|
|
|
}
|
|
|
|
if tt.wants.contentType != "" && content != tt.wants.contentType {
|
|
|
|
t.Errorf("%q. handleDeleteCheck() = %v, want %v", tt.name, content, tt.wants.contentType)
|
|
|
|
}
|
|
|
|
if tt.wants.body != "" {
|
|
|
|
if eq, diff, err := jsonEqual(string(body), tt.wants.body); err != nil {
|
|
|
|
t.Errorf("%q, handleDeleteCheck(). error unmarshaling json %v", tt.name, err)
|
|
|
|
} else if !eq {
|
|
|
|
t.Errorf("%q. handleDeleteCheck() = ***%s***", tt.name, diff)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestService_handlePatchCheck(t *testing.T) {
|
|
|
|
type fields struct {
|
|
|
|
CheckService influxdb.CheckService
|
|
|
|
}
|
|
|
|
type args struct {
|
|
|
|
id string
|
|
|
|
name string
|
|
|
|
}
|
|
|
|
type wants struct {
|
|
|
|
statusCode int
|
|
|
|
contentType string
|
|
|
|
body string
|
|
|
|
}
|
|
|
|
|
|
|
|
tests := []struct {
|
|
|
|
name string
|
|
|
|
fields fields
|
|
|
|
args args
|
|
|
|
wants wants
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
name: "update a check name",
|
|
|
|
fields: fields{
|
|
|
|
&mock.CheckService{
|
|
|
|
PatchCheckFn: func(ctx context.Context, id influxdb.ID, upd influxdb.CheckUpdate) (influxdb.Check, error) {
|
|
|
|
if id == influxTesting.MustIDBase16("020f755c3c082000") {
|
|
|
|
d := &check.Deadman{
|
|
|
|
Base: check.Base{
|
2019-08-07 22:34:07 +00:00
|
|
|
ID: influxTesting.MustIDBase16("020f755c3c082000"),
|
|
|
|
Name: "hello",
|
|
|
|
OrgID: influxTesting.MustIDBase16("020f755c3c082000"),
|
|
|
|
TaskID: 3,
|
2019-07-25 10:30:25 +00:00
|
|
|
},
|
|
|
|
Level: notification.Critical,
|
|
|
|
}
|
|
|
|
|
|
|
|
if upd.Name != nil {
|
|
|
|
d.Name = *upd.Name
|
|
|
|
}
|
|
|
|
|
|
|
|
return d, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil, fmt.Errorf("not found")
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
id: "020f755c3c082000",
|
|
|
|
name: "example",
|
|
|
|
},
|
|
|
|
wants: wants{
|
|
|
|
statusCode: http.StatusOK,
|
|
|
|
contentType: "application/json; charset=utf-8",
|
|
|
|
body: `
|
|
|
|
{
|
|
|
|
"links": {
|
|
|
|
"self": "/api/v2/checks/020f755c3c082000",
|
|
|
|
"labels": "/api/v2/checks/020f755c3c082000/labels",
|
|
|
|
"members": "/api/v2/checks/020f755c3c082000/members",
|
|
|
|
"owners": "/api/v2/checks/020f755c3c082000/owners"
|
|
|
|
},
|
|
|
|
"createdAt": "0001-01-01T00:00:00Z",
|
|
|
|
"updatedAt": "0001-01-01T00:00:00Z",
|
|
|
|
"id": "020f755c3c082000",
|
|
|
|
"orgID": "020f755c3c082000",
|
|
|
|
"level": "CRIT",
|
|
|
|
"name": "example",
|
|
|
|
"query": {
|
2019-09-18 20:19:51 +00:00
|
|
|
"builderConfig": {
|
|
|
|
"aggregateWindow": {
|
|
|
|
"period": ""
|
|
|
|
},
|
|
|
|
"buckets": null,
|
|
|
|
"functions": null,
|
|
|
|
"tags": null
|
|
|
|
},
|
|
|
|
"editMode": "",
|
|
|
|
"name": "",
|
|
|
|
"text": ""
|
|
|
|
},
|
|
|
|
"reportZero": false,
|
|
|
|
"status": "active",
|
|
|
|
"statusMessageTemplate": "",
|
|
|
|
"tags": null,
|
|
|
|
"type": "deadman",
|
|
|
|
"labels": []
|
2019-07-25 10:30:25 +00:00
|
|
|
}
|
|
|
|
`,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "check not found",
|
|
|
|
fields: fields{
|
|
|
|
&mock.CheckService{
|
|
|
|
PatchCheckFn: func(ctx context.Context, id influxdb.ID, upd influxdb.CheckUpdate) (influxdb.Check, error) {
|
|
|
|
return nil, &influxdb.Error{
|
|
|
|
Code: influxdb.ENotFound,
|
|
|
|
Msg: "check not found",
|
|
|
|
}
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
id: "020f755c3c082000",
|
|
|
|
name: "hello",
|
|
|
|
},
|
|
|
|
wants: wants{
|
|
|
|
statusCode: http.StatusNotFound,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, tt := range tests {
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
checkBackend := NewMockCheckBackend()
|
|
|
|
checkBackend.HTTPErrorHandler = ErrorHandler(0)
|
|
|
|
checkBackend.CheckService = tt.fields.CheckService
|
2019-09-18 20:19:51 +00:00
|
|
|
checkBackend.TaskService = &mock.TaskService{
|
|
|
|
FindTaskByIDFn: func(ctx context.Context, id influxdb.ID) (*influxdb.Task, error) {
|
|
|
|
return &influxdb.Task{Status: "active"}, nil
|
|
|
|
},
|
|
|
|
}
|
2019-07-25 10:30:25 +00:00
|
|
|
h := NewCheckHandler(checkBackend)
|
|
|
|
|
|
|
|
upd := influxdb.CheckUpdate{}
|
|
|
|
if tt.args.name != "" {
|
|
|
|
upd.Name = &tt.args.name
|
|
|
|
}
|
|
|
|
|
|
|
|
b, err := json.Marshal(upd)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("failed to unmarshal check update: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
r := httptest.NewRequest("GET", "http://any.url", bytes.NewReader(b))
|
|
|
|
|
|
|
|
r = r.WithContext(context.WithValue(
|
|
|
|
context.Background(),
|
|
|
|
httprouter.ParamsKey,
|
|
|
|
httprouter.Params{
|
|
|
|
{
|
|
|
|
Key: "id",
|
|
|
|
Value: tt.args.id,
|
|
|
|
},
|
|
|
|
}))
|
|
|
|
|
|
|
|
w := httptest.NewRecorder()
|
|
|
|
|
|
|
|
h.handlePatchCheck(w, r)
|
|
|
|
|
|
|
|
res := w.Result()
|
|
|
|
content := res.Header.Get("Content-Type")
|
|
|
|
body, _ := ioutil.ReadAll(res.Body)
|
|
|
|
|
|
|
|
if res.StatusCode != tt.wants.statusCode {
|
|
|
|
t.Errorf("%q. handlePatchCheck() = %v, want %v %v", tt.name, res.StatusCode, tt.wants.statusCode, w.Header())
|
|
|
|
}
|
|
|
|
if tt.wants.contentType != "" && content != tt.wants.contentType {
|
|
|
|
t.Errorf("%q. handlePatchCheck() = %v, want %v", tt.name, content, tt.wants.contentType)
|
|
|
|
}
|
|
|
|
if tt.wants.body != "" {
|
|
|
|
if eq, diff, err := jsonEqual(string(body), tt.wants.body); err != nil {
|
|
|
|
t.Errorf("%q, handlePatchCheck(). error unmarshaling json %v", tt.name, err)
|
|
|
|
} else if !eq {
|
|
|
|
t.Errorf("%q. handlePatchCheck() = ***%s***", tt.name, diff)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestService_handleUpdateCheck(t *testing.T) {
|
|
|
|
type fields struct {
|
|
|
|
CheckService influxdb.CheckService
|
|
|
|
}
|
|
|
|
type args struct {
|
|
|
|
id string
|
|
|
|
chk influxdb.Check
|
|
|
|
}
|
|
|
|
type wants struct {
|
|
|
|
statusCode int
|
|
|
|
contentType string
|
|
|
|
body string
|
|
|
|
}
|
|
|
|
|
|
|
|
tests := []struct {
|
|
|
|
name string
|
|
|
|
fields fields
|
|
|
|
args args
|
|
|
|
wants wants
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
name: "update a check name",
|
|
|
|
fields: fields{
|
2019-08-19 22:56:17 +00:00
|
|
|
CheckService: &mock.CheckService{
|
2019-09-18 20:19:51 +00:00
|
|
|
UpdateCheckFn: func(ctx context.Context, id influxdb.ID, chk influxdb.CheckCreate) (influxdb.Check, error) {
|
2019-07-25 10:30:25 +00:00
|
|
|
if id == influxTesting.MustIDBase16("020f755c3c082000") {
|
|
|
|
d := &check.Deadman{
|
|
|
|
Base: check.Base{
|
|
|
|
ID: influxTesting.MustIDBase16("020f755c3c082000"),
|
|
|
|
Name: "hello",
|
|
|
|
OrgID: influxTesting.MustIDBase16("020f755c3c082000"),
|
2019-08-07 22:34:07 +00:00
|
|
|
TaskID: 3,
|
2019-07-25 10:30:25 +00:00
|
|
|
},
|
|
|
|
}
|
|
|
|
|
2019-09-18 20:19:51 +00:00
|
|
|
d = chk.Check.(*check.Deadman)
|
2019-07-25 10:30:25 +00:00
|
|
|
d.SetID(influxTesting.MustIDBase16("020f755c3c082000"))
|
|
|
|
d.SetOrgID(influxTesting.MustIDBase16("020f755c3c082000"))
|
|
|
|
|
|
|
|
return d, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil, fmt.Errorf("not found")
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
id: "020f755c3c082000",
|
|
|
|
chk: &check.Deadman{
|
|
|
|
Base: check.Base{
|
2019-09-10 14:23:54 +00:00
|
|
|
Name: "example",
|
|
|
|
TaskID: 3,
|
|
|
|
OwnerID: 42,
|
|
|
|
OrgID: influxTesting.MustIDBase16("020f755c3c082000"),
|
2019-07-25 10:30:25 +00:00
|
|
|
},
|
|
|
|
Level: notification.Critical,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
wants: wants{
|
|
|
|
statusCode: http.StatusOK,
|
|
|
|
contentType: "application/json; charset=utf-8",
|
|
|
|
body: `
|
|
|
|
{
|
|
|
|
"links": {
|
|
|
|
"self": "/api/v2/checks/020f755c3c082000",
|
|
|
|
"labels": "/api/v2/checks/020f755c3c082000/labels",
|
|
|
|
"members": "/api/v2/checks/020f755c3c082000/members",
|
|
|
|
"owners": "/api/v2/checks/020f755c3c082000/owners"
|
|
|
|
},
|
|
|
|
"createdAt": "0001-01-01T00:00:00Z",
|
|
|
|
"updatedAt": "0001-01-01T00:00:00Z",
|
|
|
|
"id": "020f755c3c082000",
|
|
|
|
"orgID": "020f755c3c082000",
|
2019-09-10 14:23:54 +00:00
|
|
|
"ownerID": "000000000000002a",
|
2019-07-25 10:30:25 +00:00
|
|
|
"level": "CRIT",
|
|
|
|
"name": "example",
|
|
|
|
"query": {
|
|
|
|
"builderConfig": {
|
|
|
|
"aggregateWindow": {
|
|
|
|
"period": ""
|
|
|
|
},
|
|
|
|
"buckets": null,
|
|
|
|
"functions": null,
|
|
|
|
"tags": null
|
|
|
|
},
|
|
|
|
"editMode": "",
|
|
|
|
"name": "",
|
|
|
|
"text": ""
|
|
|
|
},
|
|
|
|
"reportZero": false,
|
|
|
|
"status": "active",
|
|
|
|
"statusMessageTemplate": "",
|
|
|
|
"tags": null,
|
|
|
|
"type": "deadman",
|
|
|
|
"labels": []
|
|
|
|
}
|
|
|
|
`,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "check not found",
|
|
|
|
fields: fields{
|
2019-08-19 22:56:17 +00:00
|
|
|
CheckService: &mock.CheckService{
|
2019-09-18 20:19:51 +00:00
|
|
|
UpdateCheckFn: func(ctx context.Context, id influxdb.ID, chk influxdb.CheckCreate) (influxdb.Check, error) {
|
2019-07-25 10:30:25 +00:00
|
|
|
return nil, &influxdb.Error{
|
|
|
|
Code: influxdb.ENotFound,
|
|
|
|
Msg: "check not found",
|
|
|
|
}
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
id: "020f755c3c082000",
|
|
|
|
chk: &check.Deadman{
|
|
|
|
Base: check.Base{
|
2019-09-10 14:23:54 +00:00
|
|
|
Name: "example",
|
|
|
|
OwnerID: 42,
|
|
|
|
OrgID: influxTesting.MustIDBase16("020f755c3c082000"),
|
2019-07-25 10:30:25 +00:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
wants: wants{
|
|
|
|
statusCode: http.StatusNotFound,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, tt := range tests {
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
checkBackend := NewMockCheckBackend()
|
|
|
|
checkBackend.HTTPErrorHandler = ErrorHandler(0)
|
|
|
|
checkBackend.CheckService = tt.fields.CheckService
|
2019-09-18 20:19:51 +00:00
|
|
|
checkBackend.TaskService = &mock.TaskService{
|
|
|
|
FindTaskByIDFn: func(ctx context.Context, id influxdb.ID) (*influxdb.Task, error) {
|
|
|
|
return &influxdb.Task{Status: "active"}, nil
|
|
|
|
},
|
|
|
|
}
|
2019-07-25 10:30:25 +00:00
|
|
|
h := NewCheckHandler(checkBackend)
|
|
|
|
|
|
|
|
b, err := json.Marshal(tt.args.chk)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("failed to unmarshal check update: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
r := httptest.NewRequest("GET", "http://any.url", bytes.NewReader(b))
|
|
|
|
|
|
|
|
r = r.WithContext(context.WithValue(
|
|
|
|
context.Background(),
|
|
|
|
httprouter.ParamsKey,
|
|
|
|
httprouter.Params{
|
|
|
|
{
|
|
|
|
Key: "id",
|
|
|
|
Value: tt.args.id,
|
|
|
|
},
|
|
|
|
}))
|
|
|
|
|
|
|
|
w := httptest.NewRecorder()
|
|
|
|
|
|
|
|
h.handlePutCheck(w, r)
|
|
|
|
|
|
|
|
res := w.Result()
|
|
|
|
content := res.Header.Get("Content-Type")
|
|
|
|
body, _ := ioutil.ReadAll(res.Body)
|
|
|
|
|
|
|
|
if res.StatusCode != tt.wants.statusCode {
|
2019-09-10 14:23:54 +00:00
|
|
|
t.Errorf("%q. handlePutCheck() = %v, want %v %v %v", tt.name, res.StatusCode, tt.wants.statusCode, w.Header(), string(body))
|
2019-07-25 10:30:25 +00:00
|
|
|
}
|
|
|
|
if tt.wants.contentType != "" && content != tt.wants.contentType {
|
|
|
|
t.Errorf("%q. handlePutCheck() = %v, want %v", tt.name, content, tt.wants.contentType)
|
|
|
|
}
|
|
|
|
if tt.wants.body != "" {
|
|
|
|
if eq, diff, err := jsonEqual(string(body), tt.wants.body); err != nil {
|
|
|
|
t.Errorf("%q, handlePutCheck(). error unmarshaling json %v", tt.name, err)
|
|
|
|
} else if !eq {
|
|
|
|
t.Errorf("%q. handlePutCheck() = ***%s***", tt.name, diff)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestService_handlePostCheckMember(t *testing.T) {
|
|
|
|
type fields struct {
|
|
|
|
UserService influxdb.UserService
|
|
|
|
}
|
|
|
|
type args struct {
|
|
|
|
checkID string
|
|
|
|
user *influxdb.User
|
|
|
|
}
|
|
|
|
type wants struct {
|
|
|
|
statusCode int
|
|
|
|
contentType string
|
|
|
|
body string
|
|
|
|
}
|
|
|
|
|
|
|
|
tests := []struct {
|
|
|
|
name string
|
|
|
|
fields fields
|
|
|
|
args args
|
|
|
|
wants wants
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
name: "add a check member",
|
|
|
|
fields: fields{
|
|
|
|
UserService: &mock.UserService{
|
|
|
|
FindUserByIDFn: func(ctx context.Context, id influxdb.ID) (*influxdb.User, error) {
|
|
|
|
return &influxdb.User{
|
2019-09-24 22:18:42 +00:00
|
|
|
ID: id,
|
|
|
|
Name: "name",
|
|
|
|
Status: influxdb.Active,
|
2019-07-25 10:30:25 +00:00
|
|
|
}, nil
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
checkID: "020f755c3c082000",
|
|
|
|
user: &influxdb.User{
|
|
|
|
ID: influxTesting.MustIDBase16("6f626f7274697320"),
|
|
|
|
},
|
|
|
|
},
|
|
|
|
wants: wants{
|
|
|
|
statusCode: http.StatusCreated,
|
|
|
|
contentType: "application/json; charset=utf-8",
|
|
|
|
body: `
|
|
|
|
{
|
|
|
|
"links": {
|
|
|
|
"logs": "/api/v2/users/6f626f7274697320/logs",
|
|
|
|
"self": "/api/v2/users/6f626f7274697320"
|
|
|
|
},
|
|
|
|
"role": "member",
|
|
|
|
"id": "6f626f7274697320",
|
2019-09-24 22:18:42 +00:00
|
|
|
"name": "name",
|
|
|
|
"status": "active"
|
2019-07-25 10:30:25 +00:00
|
|
|
}
|
|
|
|
`,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, tt := range tests {
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
checkBackend := NewMockCheckBackend()
|
|
|
|
checkBackend.UserService = tt.fields.UserService
|
2019-09-18 20:19:51 +00:00
|
|
|
checkBackend.TaskService = &mock.TaskService{
|
|
|
|
FindTaskByIDFn: func(ctx context.Context, id influxdb.ID) (*influxdb.Task, error) {
|
|
|
|
return &influxdb.Task{}, nil
|
|
|
|
},
|
|
|
|
}
|
2019-07-25 10:30:25 +00:00
|
|
|
h := NewCheckHandler(checkBackend)
|
|
|
|
|
|
|
|
b, err := json.Marshal(tt.args.user)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("failed to marshal user: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
path := fmt.Sprintf("/api/v2/checks/%s/members", tt.args.checkID)
|
|
|
|
r := httptest.NewRequest("POST", path, bytes.NewReader(b))
|
|
|
|
w := httptest.NewRecorder()
|
|
|
|
|
|
|
|
h.ServeHTTP(w, r)
|
|
|
|
|
|
|
|
res := w.Result()
|
|
|
|
content := res.Header.Get("Content-Type")
|
|
|
|
body, _ := ioutil.ReadAll(res.Body)
|
|
|
|
|
|
|
|
if res.StatusCode != tt.wants.statusCode {
|
|
|
|
t.Errorf("%q. handlePostCheckMember() = %v, want %v", tt.name, res.StatusCode, tt.wants.statusCode)
|
|
|
|
}
|
|
|
|
if tt.wants.contentType != "" && content != tt.wants.contentType {
|
|
|
|
t.Errorf("%q. handlePostCheckMember() = %v, want %v", tt.name, content, tt.wants.contentType)
|
|
|
|
}
|
|
|
|
if eq, diff, err := jsonEqual(string(body), tt.wants.body); err != nil {
|
|
|
|
t.Errorf("%q, handlePostCheckMember(). error unmarshaling json %v", tt.name, err)
|
|
|
|
} else if tt.wants.body != "" && !eq {
|
|
|
|
t.Errorf("%q. handlePostCheckMember() = ***%s***", tt.name, diff)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestService_handlePostCheckOwner(t *testing.T) {
|
|
|
|
type fields struct {
|
|
|
|
UserService influxdb.UserService
|
|
|
|
}
|
|
|
|
type args struct {
|
|
|
|
checkID string
|
|
|
|
user *influxdb.User
|
|
|
|
}
|
|
|
|
type wants struct {
|
|
|
|
statusCode int
|
|
|
|
contentType string
|
|
|
|
body string
|
|
|
|
}
|
|
|
|
|
|
|
|
tests := []struct {
|
|
|
|
name string
|
|
|
|
fields fields
|
|
|
|
args args
|
|
|
|
wants wants
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
name: "add a check owner",
|
|
|
|
fields: fields{
|
|
|
|
UserService: &mock.UserService{
|
|
|
|
FindUserByIDFn: func(ctx context.Context, id influxdb.ID) (*influxdb.User, error) {
|
|
|
|
return &influxdb.User{
|
2019-09-24 22:18:42 +00:00
|
|
|
ID: id,
|
|
|
|
Name: "name",
|
|
|
|
Status: influxdb.Active,
|
2019-07-25 10:30:25 +00:00
|
|
|
}, nil
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
checkID: "020f755c3c082000",
|
|
|
|
user: &influxdb.User{
|
|
|
|
ID: influxTesting.MustIDBase16("6f626f7274697320"),
|
|
|
|
},
|
|
|
|
},
|
|
|
|
wants: wants{
|
|
|
|
statusCode: http.StatusCreated,
|
|
|
|
contentType: "application/json; charset=utf-8",
|
|
|
|
body: `
|
|
|
|
{
|
|
|
|
"links": {
|
|
|
|
"logs": "/api/v2/users/6f626f7274697320/logs",
|
|
|
|
"self": "/api/v2/users/6f626f7274697320"
|
|
|
|
},
|
|
|
|
"role": "owner",
|
|
|
|
"id": "6f626f7274697320",
|
2019-09-24 22:18:42 +00:00
|
|
|
"name": "name",
|
|
|
|
"status": "active"
|
2019-07-25 10:30:25 +00:00
|
|
|
}
|
|
|
|
`,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, tt := range tests {
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
checkBackend := NewMockCheckBackend()
|
|
|
|
checkBackend.UserService = tt.fields.UserService
|
|
|
|
h := NewCheckHandler(checkBackend)
|
|
|
|
|
|
|
|
b, err := json.Marshal(tt.args.user)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("failed to marshal user: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
path := fmt.Sprintf("/api/v2/checks/%s/owners", tt.args.checkID)
|
|
|
|
r := httptest.NewRequest("POST", path, bytes.NewReader(b))
|
|
|
|
w := httptest.NewRecorder()
|
|
|
|
|
|
|
|
h.ServeHTTP(w, r)
|
|
|
|
|
|
|
|
res := w.Result()
|
|
|
|
content := res.Header.Get("Content-Type")
|
|
|
|
body, _ := ioutil.ReadAll(res.Body)
|
|
|
|
|
|
|
|
if res.StatusCode != tt.wants.statusCode {
|
|
|
|
t.Errorf("%q. handlePostCheckOwner() = %v, want %v", tt.name, res.StatusCode, tt.wants.statusCode)
|
|
|
|
}
|
|
|
|
if tt.wants.contentType != "" && content != tt.wants.contentType {
|
|
|
|
t.Errorf("%q. handlePostCheckOwner() = %v, want %v", tt.name, content, tt.wants.contentType)
|
|
|
|
}
|
|
|
|
if eq, diff, err := jsonEqual(string(body), tt.wants.body); err != nil {
|
|
|
|
t.Errorf("%q, handlePostCheckOwner(). error unmarshaling json %v", tt.name, err)
|
|
|
|
} else if tt.wants.body != "" && !eq {
|
|
|
|
t.Errorf("%q. handlePostCheckOwner() = ***%s***", tt.name, diff)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// func initCheckService(f influxTesting.CheckFields, t *testing.T) (influxdb.CheckService, string, func()) {
|
|
|
|
// svc := inmem.NewService()
|
|
|
|
// svc.IDGenerator = f.IDGenerator
|
|
|
|
// svc.TimeGenerator = f.TimeGenerator
|
|
|
|
// if f.TimeGenerator == nil {
|
|
|
|
// svc.TimeGenerator = influxdb.RealTimeGenerator{}
|
|
|
|
// }
|
|
|
|
|
|
|
|
// ctx := context.Background()
|
|
|
|
// for _, o := range f.Organizations {
|
|
|
|
// if err := svc.PutOrganization(ctx, o); err != nil {
|
|
|
|
// t.Fatalf("failed to populate organizations")
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
// for _, b := range f.Checks {
|
|
|
|
// if err := svc.PutCheck(ctx, b); err != nil {
|
|
|
|
// t.Fatalf("failed to populate checks")
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
|
|
|
|
// checkBackend := NewMockCheckBackend()
|
|
|
|
// checkBackend.HTTPErrorHandler = ErrorHandler(0)
|
|
|
|
// checkBackend.CheckService = svc
|
|
|
|
// checkBackend.OrganizationService = svc
|
|
|
|
// handler := NewCheckHandler(checkBackend)
|
|
|
|
// server := httptest.NewServer(handler)
|
|
|
|
// client := CheckService{
|
|
|
|
// Addr: server.URL,
|
|
|
|
// OpPrefix: inmem.OpPrefix,
|
|
|
|
// }
|
|
|
|
// done := server.Close
|
|
|
|
|
|
|
|
// return &client, inmem.OpPrefix, done
|
|
|
|
// }
|
|
|
|
|
|
|
|
// func TestCheckService(t *testing.T) {
|
|
|
|
// influxTestingCheckService(initCheckService, t)
|
|
|
|
// }
|