From a28d3d64660e7b11194a8c35a15246d3e69d2799 Mon Sep 17 00:00:00 2001 From: Chris Goller Date: Thu, 7 Sep 2017 18:02:52 -0500 Subject: [PATCH] Update kapacitor AlertRule to containe most Kapacitor Task information --- chronograf.go | 35 +++++--- kapacitor/client.go | 50 ++++------- kapacitor/client_test.go | 179 +++++++++++++++++++------------------- server/kapacitors.go | 29 +----- server/kapacitors_test.go | 29 ++++-- 5 files changed, 154 insertions(+), 168 deletions(-) diff --git a/chronograf.go b/chronograf.go index 63c83d622..070862ed5 100644 --- a/chronograf.go +++ b/chronograf.go @@ -441,19 +441,32 @@ type SourcesStore interface { Update(context.Context, Source) error } +type DBRP struct { + DB string `json:"db"` + RP string `json:"rp"` +} + // AlertRule represents rules for building a tickscript alerting task type AlertRule struct { - ID string `json:"id,omitempty"` // ID is the unique ID of the alert - TICKScript TICKScript `json:"tickscript"` // TICKScript is the raw tickscript associated with this Alert - Query *QueryConfig `json:"query"` // Query is the filter of data for the alert. - Every string `json:"every"` // Every how often to check for the alerting criteria - Alerts []string `json:"alerts"` // Alerts name all the services to notify (e.g. pagerduty) - AlertNodes []KapacitorNode `json:"alertNodes,omitempty"` // AlertNodes define additional arguments to alerts - Message string `json:"message"` // Message included with alert - Details string `json:"details"` // Details is generally used for the Email alert. If empty will not be added. - Trigger string `json:"trigger"` // Trigger is a type that defines when to trigger the alert - TriggerValues TriggerValues `json:"values"` // Defines the values that cause the alert to trigger - Name string `json:"name"` // Name is the user-defined name for the alert + ID string `json:"id,omitempty"` // ID is the unique ID of the alert + TICKScript TICKScript `json:"tickscript"` // TICKScript is the raw tickscript associated with this Alert + Query *QueryConfig `json:"query"` // Query is the filter of data for the alert. + Every string `json:"every"` // Every how often to check for the alerting criteria + Alerts []string `json:"alerts"` // Alerts name all the services to notify (e.g. pagerduty) + AlertNodes []KapacitorNode `json:"alertNodes,omitempty"` // AlertNodes define additional arguments to alerts + Message string `json:"message"` // Message included with alert + Details string `json:"details"` // Details is generally used for the Email alert. If empty will not be added. + Trigger string `json:"trigger"` // Trigger is a type that defines when to trigger the alert + TriggerValues TriggerValues `json:"values"` // Defines the values that cause the alert to trigger + Name string `json:"name"` // Name is the user-defined name for the alert + Type string `json:"type"` // Represents the task type where stream is data streamed to kapacitor and batch is queried by kapacitor + DBRPs []DBRP `json:"dbrps"` // List of database retention policy pairs the task is allowed to access + Status string `json:"status"` // Represents if this rule is enabled or disabled in kapacitor + Executing bool `json:"executing"` // Whether the task is currently executing + Error string `json:"error"` // Any error encountered when kapacitor executes the task + Created time.Time `json:"created"` // Date the task was first created + Modified time.Time `json:"modified"` // Date the task was last modified + LastEnabled time.Time `json:"last-enabled,omitempty"` // Date the task was last set to status enabled } // TICKScript task to be used by kapacitor diff --git a/kapacitor/client.go b/kapacitor/client.go index 2f7731fc7..f3d56741a 100644 --- a/kapacitor/client.go +++ b/kapacitor/client.go @@ -3,7 +3,6 @@ package kapacitor import ( "context" "fmt" - "time" "github.com/influxdata/chronograf" "github.com/influxdata/chronograf/uuid" @@ -49,31 +48,18 @@ func NewClient(url, username, password string) *Client { } } -type DBRP struct { - DB string - RP string -} - // Task represents a running kapacitor task type Task struct { - ID string // Kapacitor ID - Type string // Kapacitor type (stream or batch) - DBRPs []DBRP // Databases and RetentionPolicies associated with this task - Status string // Status is the current state of the task - Executing bool - Error string - Created time.Time - Modified time.Time - LastEnabled time.Time - Href string // Kapacitor relative URI - HrefOutput string // Kapacitor relative URI to HTTPOutNode - Rule chronograf.AlertRule // Rule is the rule that represents this Task - TICKScript chronograf.TICKScript // TICKScript is the running script + ID string // Kapacitor ID + Href string // Kapacitor relative URI + HrefOutput string // Kapacitor relative URI to HTTPOutNode + Rule chronograf.AlertRule // Rule is the rule that represents this Task + TICKScript chronograf.TICKScript // TICKScript is the running script } // NewTask creates a task from a kapacitor client task func NewTask(task *client.Task) *Task { - dbrps := make([]DBRP, len(task.DBRPs)) + dbrps := make([]chronograf.DBRP, len(task.DBRPs)) for i := range task.DBRPs { dbrps[i].DB = task.DBRPs[i].Database dbrps[i].RP = task.DBRPs[i].RetentionPolicy @@ -90,19 +76,19 @@ func NewTask(task *client.Task) *Task { rule.ID = task.ID rule.TICKScript = script + rule.Type = task.Type.String() + rule.DBRPs = dbrps + rule.Status = task.Status.String() + rule.Executing = task.Executing + rule.Error = task.Error + rule.Created = task.Created + rule.Modified = task.Modified + rule.LastEnabled = task.LastEnabled return &Task{ - ID: task.ID, - Type: task.Type.String(), - DBRPs: dbrps, - Status: task.Status.String(), - Executing: task.Executing, - Error: task.Error, - Created: task.Created, - Modified: task.Modified, - LastEnabled: task.LastEnabled, - Href: task.Link.Href, - HrefOutput: HrefOutput(task.ID), - Rule: rule, + ID: task.ID, + Href: task.Link.Href, + HrefOutput: HrefOutput(task.ID), + Rule: rule, } } diff --git a/kapacitor/client_test.go b/kapacitor/client_test.go index b75ad681d..7536fa246 100644 --- a/kapacitor/client_test.go +++ b/kapacitor/client_test.go @@ -249,16 +249,17 @@ func TestClient_All(t *testing.T) { }, want: map[string]*Task{ "howdy": &Task{ - ID: "howdy", - Type: "unknown TaskType 0", - Status: "enabled", + ID: "howdy", + HrefOutput: "/kapacitor/v1/tasks/howdy/output", Rule: chronograf.AlertRule{ ID: "howdy", Name: "howdy", TICKScript: "", + Type: "unknown TaskType 0", + Status: "enabled", + DBRPs: []chronograf.DBRP{}, }, - DBRPs: []DBRP{}, TICKScript: "", }, }, @@ -354,19 +355,20 @@ trigger want: map[string]*Task{ "rule 1": &Task{ ID: "rule 1", - DBRPs: []DBRP{ - { - DB: "_internal", - RP: "autogen", - }, - }, - Type: "stream", - Status: "enabled", HrefOutput: "/kapacitor/v1/tasks/rule 1/output", Rule: chronograf.AlertRule{ - ID: "rule 1", - Name: "rule 1", + DBRPs: []chronograf.DBRP{ + { + + DB: "_internal", + RP: "autogen", + }, + }, + Type: "stream", + Status: "enabled", + ID: "rule 1", + Name: "rule 1", TICKScript: `var db = '_internal' var rp = 'monitor' @@ -568,19 +570,18 @@ func TestClient_Get(t *testing.T) { }, want: &Task{ ID: "myid", - Type: "stream", - Status: "enabled", HrefOutput: "/kapacitor/v1/tasks/myid/output", - DBRPs: []DBRP{ - { - - DB: "_internal", - RP: "autogen", - }, - }, Rule: chronograf.AlertRule{ - ID: "myid", - Name: "myid", + Type: "stream", + Status: "enabled", + ID: "myid", + Name: "myid", + DBRPs: []chronograf.DBRP{ + { + DB: "_internal", + RP: "autogen", + }, + }, }, }, link: client.Link{ @@ -677,18 +678,18 @@ trigger `, }, want: &Task{ - ID: "rule 1", - Type: "stream", - Status: "enabled", - DBRPs: []DBRP{ - { - - DB: "_internal", - RP: "autogen", - }, - }, + ID: "rule 1", HrefOutput: "/kapacitor/v1/tasks/rule 1/output", Rule: chronograf.AlertRule{ + Type: "stream", + Status: "enabled", + DBRPs: []chronograf.DBRP{ + { + + DB: "_internal", + RP: "autogen", + }, + }, ID: "rule 1", Name: "rule 1", TICKScript: `var db = '_internal' @@ -881,21 +882,21 @@ func TestClient_updateStatus(t *testing.T) { Status: client.Disabled, }, want: &Task{ - ID: "howdy", - Type: "stream", - DBRPs: []DBRP{ - { - - DB: "db", - RP: "rp", - }, - }, - Status: "disabled", + ID: "howdy", Href: "/kapacitor/v1/tasks/howdy", HrefOutput: "/kapacitor/v1/tasks/howdy/output", Rule: chronograf.AlertRule{ ID: "howdy", Name: "howdy", + Type: "stream", + DBRPs: []chronograf.DBRP{ + { + + DB: "db", + RP: "rp", + }, + }, + Status: "disabled", }, }, }, @@ -951,21 +952,21 @@ func TestClient_updateStatus(t *testing.T) { Status: client.Enabled, }, want: &Task{ - ID: "howdy", - Type: "stream", - DBRPs: []DBRP{ - { - - DB: "db", - RP: "rp", - }, - }, - Status: "enabled", + ID: "howdy", Href: "/kapacitor/v1/tasks/howdy", HrefOutput: "/kapacitor/v1/tasks/howdy/output", Rule: chronograf.AlertRule{ ID: "howdy", Name: "howdy", + Type: "stream", + DBRPs: []chronograf.DBRP{ + { + + DB: "db", + RP: "rp", + }, + }, + Status: "enabled", }, }, }, @@ -1103,21 +1104,21 @@ func TestClient_Update(t *testing.T) { }, }, want: &Task{ - ID: "howdy", - DBRPs: []DBRP{ - { - - DB: "db", - RP: "rp", - }, - }, - Status: "enabled", - Type: "stream", + ID: "howdy", Href: "/kapacitor/v1/tasks/howdy", HrefOutput: "/kapacitor/v1/tasks/howdy/output", Rule: chronograf.AlertRule{ - ID: "howdy", - Name: "howdy", + DBRPs: []chronograf.DBRP{ + { + + DB: "db", + RP: "rp", + }, + }, + Status: "enabled", + Type: "stream", + ID: "howdy", + Name: "howdy", }, }, wantStatus: client.Enabled, @@ -1167,21 +1168,21 @@ func TestClient_Update(t *testing.T) { }, }, want: &Task{ - ID: "howdy", - DBRPs: []DBRP{ - { - - DB: "db", - RP: "rp", - }, - }, - Status: "disabled", - Type: "stream", + ID: "howdy", Href: "/kapacitor/v1/tasks/howdy", HrefOutput: "/kapacitor/v1/tasks/howdy/output", Rule: chronograf.AlertRule{ ID: "howdy", Name: "howdy", + DBRPs: []chronograf.DBRP{ + { + + DB: "db", + RP: "rp", + }, + }, + Status: "disabled", + Type: "stream", }, }, wantStatus: client.Disabled, @@ -1289,21 +1290,21 @@ func TestClient_Create(t *testing.T) { }, }, want: &Task{ - ID: "chronograf-v1-howdy", - Type: "stream", - DBRPs: []DBRP{ - { - - DB: "db", - RP: "rp", - }, - }, - Status: "enabled", + ID: "chronograf-v1-howdy", Href: "/kapacitor/v1/tasks/chronograf-v1-howdy", HrefOutput: "/kapacitor/v1/tasks/chronograf-v1-howdy/output", Rule: chronograf.AlertRule{ - ID: "chronograf-v1-howdy", - Name: "chronograf-v1-howdy", + Type: "stream", + DBRPs: []chronograf.DBRP{ + { + + DB: "db", + RP: "rp", + }, + }, + Status: "enabled", + ID: "chronograf-v1-howdy", + Name: "chronograf-v1-howdy", }, }, }, diff --git a/server/kapacitors.go b/server/kapacitors.go index 208f145d5..a0a838cb3 100644 --- a/server/kapacitors.go +++ b/server/kapacitors.go @@ -5,7 +5,6 @@ import ( "fmt" "net/http" "net/url" - "time" "github.com/bouk/httprouter" "github.com/influxdata/chronograf" @@ -331,22 +330,9 @@ type alertLinks struct { Output string `json:"output"` } -type dbrp struct { - DB string `json:"db"` - RP string `json:"rp"` -} - type alertResponse struct { chronograf.AlertRule - Type string `json:"type"` - DBRPs []dbrp `json:"dbrps"` - Status string `json:"status"` - Executing bool `json:"executing"` - Error string `json:"error"` - Created time.Time `json:"created"` - Modified time.Time `json:"modified"` - LastEnabled time.Time `json:"last-enabled,omitempty"` - Links alertLinks `json:"links"` + Links alertLinks `json:"links"` } // newAlertResponse formats task into an alertResponse @@ -358,19 +344,6 @@ func newAlertResponse(task *kapa.Task, srcID, kapaID int) *alertResponse { Kapacitor: fmt.Sprintf("/chronograf/v1/sources/%d/kapacitors/%d/proxy?path=%s", srcID, kapaID, url.QueryEscape(task.Href)), Output: fmt.Sprintf("/chronograf/v1/sources/%d/kapacitors/%d/proxy?path=%s", srcID, kapaID, url.QueryEscape(task.HrefOutput)), }, - Status: task.Status, - Type: task.Type, - Executing: task.Executing, - Error: task.Error, - Created: task.Created, - Modified: task.Modified, - LastEnabled: task.LastEnabled, - DBRPs: make([]dbrp, len(task.DBRPs)), - } - - for i := range task.DBRPs { - res.DBRPs[i].DB = task.DBRPs[i].DB - res.DBRPs[i].RP = task.DBRPs[i].RP } if res.Alerts == nil { diff --git a/server/kapacitors_test.go b/server/kapacitors_test.go index 8aa7328de..2a55ea637 100644 --- a/server/kapacitors_test.go +++ b/server/kapacitors_test.go @@ -86,15 +86,23 @@ func Test_KapacitorRulesGet(t *testing.T) { "/chronograf/v1/sources/1/kapacitors/1/rules", []chronograf.AlertRule{ { - ID: "cpu_alert", - Name: "cpu_alert", + ID: "cpu_alert", + Name: "cpu_alert", + Status: "enabled", + Type: "stream", + DBRPs: []chronograf.DBRP{{DB: "telegraf", RP: "autogen"}}, + TICKScript: tickScript, }, }, []chronograf.AlertRule{ { - ID: "cpu_alert", - Name: "cpu_alert", - Alerts: []string{}, + ID: "cpu_alert", + Name: "cpu_alert", + Status: "enabled", + Type: "stream", + DBRPs: []chronograf.DBRP{{DB: "telegraf", RP: "autogen"}}, + Alerts: []string{}, + TICKScript: tickScript, }, }, }, @@ -125,6 +133,13 @@ func Test_KapacitorRulesGet(t *testing.T) { "id": task.ID, "script": tickScript, "status": "enabled", + "type": "stream", + "dbrps": []chronograf.DBRP{ + { + DB: "telegraf", + RP: "autogen", + }, + }, "link": map[string]interface{}{ "rel": "self", "href": "/kapacitor/v1/tasks/cpu_alert", @@ -196,9 +211,7 @@ func Test_KapacitorRulesGet(t *testing.T) { frame := struct { Rules []struct { chronograf.AlertRule - TICKScript json.RawMessage `json:"tickscript"` - Status json.RawMessage `json:"status"` - Links json.RawMessage `json:"links"` + Links json.RawMessage `json:"links"` } `json:"rules"` }{}