2019-07-23 22:35:19 +00:00
package rule
import (
"encoding/json"
2019-08-29 11:24:42 +00:00
"fmt"
2019-07-23 22:35:19 +00:00
2019-08-29 11:24:42 +00:00
"github.com/influxdata/flux/ast"
2019-07-23 22:35:19 +00:00
"github.com/influxdata/influxdb"
2019-08-29 11:24:42 +00:00
"github.com/influxdata/influxdb/notification/endpoint"
"github.com/influxdata/influxdb/notification/flux"
2019-07-23 22:35:19 +00:00
)
// PagerDuty is the rule config of pagerduty notification.
type PagerDuty struct {
Base
2019-08-27 17:29:49 +00:00
MessageTemplate string ` json:"messageTemplate" `
2019-07-23 22:35:19 +00:00
}
type pagerDutyAlias PagerDuty
// MarshalJSON implement json.Marshaler interface.
2019-09-04 22:30:47 +00:00
func ( s PagerDuty ) MarshalJSON ( ) ( [ ] byte , error ) {
2019-07-23 22:35:19 +00:00
return json . Marshal (
struct {
pagerDutyAlias
Type string ` json:"type" `
} {
2019-09-04 22:30:47 +00:00
pagerDutyAlias : pagerDutyAlias ( s ) ,
Type : s . Type ( ) ,
2019-07-23 22:35:19 +00:00
} )
}
// Valid returns where the config is valid.
2019-09-04 22:30:47 +00:00
func ( s PagerDuty ) Valid ( ) error {
if err := s . Base . valid ( ) ; err != nil {
2019-07-23 22:35:19 +00:00
return err
}
2019-09-04 22:30:47 +00:00
if s . MessageTemplate == "" {
2019-07-23 22:35:19 +00:00
return & influxdb . Error {
Code : influxdb . EInvalid ,
Msg : "pagerduty invalid message template" ,
}
}
return nil
}
// Type returns the type of the rule config.
2019-09-04 22:30:47 +00:00
func ( s PagerDuty ) Type ( ) string {
2019-07-23 22:35:19 +00:00
return "pagerduty"
}
2019-08-29 11:24:42 +00:00
// GenerateFlux generates a flux script for the pagerduty notification rule.
func ( s * PagerDuty ) GenerateFlux ( e influxdb . NotificationEndpoint ) ( string , error ) {
pagerdutyEndpoint , ok := e . ( * endpoint . PagerDuty )
if ! ok {
return "" , fmt . Errorf ( "endpoint provided is a %s, not an PagerDuty endpoint" , e . Type ( ) )
}
p , err := s . GenerateFluxAST ( pagerdutyEndpoint )
if err != nil {
return "" , err
}
return ast . Format ( p ) , nil
}
// GenerateFluxAST generates a flux AST for the pagerduty notification rule.
func ( s * PagerDuty ) GenerateFluxAST ( e * endpoint . PagerDuty ) ( * ast . Package , error ) {
f := flux . File (
s . Name ,
flux . Imports ( "influxdata/influxdb/monitor" , "pagerduty" , "influxdata/influxdb/secrets" ) ,
s . generateFluxASTBody ( e ) ,
)
return & ast . Package { Package : "main" , Files : [ ] * ast . File { f } } , nil
}
func ( s * PagerDuty ) generateFluxASTBody ( e * endpoint . PagerDuty ) [ ] ast . Statement {
var statements [ ] ast . Statement
statements = append ( statements , s . generateTaskOption ( ) )
statements = append ( statements , s . generateFluxASTSecrets ( e ) )
statements = append ( statements , s . generateFluxASTEndpoint ( e ) )
statements = append ( statements , s . generateFluxASTNotificationDefinition ( e ) )
statements = append ( statements , s . generateFluxASTStatuses ( ) )
2019-09-09 23:09:35 +00:00
statements = append ( statements , s . generateFluxASTNotifyPipe ( e . ClientURL ) )
2019-08-29 11:24:42 +00:00
return statements
}
func ( s * PagerDuty ) generateFluxASTSecrets ( e * endpoint . PagerDuty ) ast . Statement {
call := flux . Call ( flux . Member ( "secrets" , "get" ) , flux . Object ( flux . Property ( "key" , flux . String ( e . RoutingKey . Key ) ) ) )
return flux . DefineVariable ( "pagerduty_secret" , call )
}
func ( s * PagerDuty ) generateFluxASTEndpoint ( e * endpoint . PagerDuty ) ast . Statement {
call := flux . Call ( flux . Member ( "pagerduty" , "endpoint" ) ,
2019-09-07 04:07:37 +00:00
flux . Object ( ) ,
2019-08-29 11:24:42 +00:00
)
return flux . DefineVariable ( "pagerduty_endpoint" , call )
}
2019-09-04 22:30:47 +00:00
func ( s * PagerDuty ) generateFluxASTNotifyPipe ( url string ) ast . Statement {
2019-08-29 11:24:42 +00:00
endpointProps := [ ] * ast . Property { }
2019-09-04 22:30:47 +00:00
// routing_key:
// required
// string
// A version 4 UUID expressed as a 32-digit hexadecimal number. This is the Integration Key for an integration on any given service.
endpointProps = append ( endpointProps , flux . Property ( "routingKey" , flux . Identifier ( "pagerduty_secret" ) ) )
// client:
// optional
// string
// name of the client sending the alert.
2019-09-06 23:21:41 +00:00
endpointProps = append ( endpointProps , flux . Property ( "client" , flux . String ( "influxdata" ) ) )
2019-09-04 22:30:47 +00:00
// clientURL
// optional
// string
// url of the client sending the alert.
endpointProps = append ( endpointProps , flux . Property ( "clientURL" , flux . String ( url ) ) )
// class:
// optional
// string
// The class/type of the event, for example ping failure or cpu load
endpointProps = append ( endpointProps , flux . Property ( "class" , flux . Identifier ( "r._check_name" ) ) )
// group:
// optional
// string
// Logical grouping of components of a service, for example app-stack
2019-09-06 23:21:41 +00:00
endpointProps = append ( endpointProps , flux . Property ( "group" , flux . Member ( "r" , "_source_measurement" ) ) )
2019-09-04 22:30:47 +00:00
// severity:
// required
// string
// The perceived severity of the status the event is describing with respect to the affected system. This can be critical, error, warning or info.
2019-09-06 23:21:41 +00:00
endpointProps = append ( endpointProps , flux . Property ( "severity" , severityFromLevel ( ) ) )
// event_action:
// required
// string trigger
// The type of event. Can be trigger, acknowledge or resolve. See Event Action.
endpointProps = append ( endpointProps , flux . Property ( "eventAction" , actionFromLevel ( ) ) )
2019-09-04 22:30:47 +00:00
// source:
// required
// string
// The unique location of the affected system, preferably a hostname or FQDN
2019-09-07 02:27:09 +00:00
endpointProps = append ( endpointProps , flux . Property ( "source" , flux . Member ( "notification" , "_notification_rule_name" ) ) )
2019-09-04 22:30:47 +00:00
// summary:
// required
// string
// A brief text summary of the event, used to generate the summaries/titles of any associated alerts. The maximum permitted length of this property is 1024 characters.
2019-09-06 23:21:41 +00:00
endpointProps = append ( endpointProps , flux . Property ( "summary" , flux . Member ( "r" , "_message" ) ) )
2019-09-04 22:30:47 +00:00
// timestamp:
// optional
// timestamp (rfc3339 milliseconds)
// The time at which the emitting tool detected or generated the event.
2019-09-06 23:21:41 +00:00
endpointProps = append ( endpointProps , flux . Property ( "timestamp" , generateTime ( ) ) )
2019-09-04 22:30:47 +00:00
2019-08-29 11:24:42 +00:00
endpointFn := flux . Function ( flux . FunctionParams ( "r" ) , flux . Object ( endpointProps ... ) )
props := [ ] * ast . Property { }
props = append ( props , flux . Property ( "data" , flux . Identifier ( "notification" ) ) )
props = append ( props , flux . Property ( "endpoint" ,
flux . Call ( flux . Identifier ( "pagerduty_endpoint" ) , flux . Object ( flux . Property ( "mapFn" , endpointFn ) ) ) ) )
call := flux . Call ( flux . Member ( "monitor" , "notify" ) , flux . Object ( props ... ) )
return flux . ExpressionStatement ( flux . Pipe ( flux . Identifier ( "statuses" ) , call ) )
}
2019-09-06 23:21:41 +00:00
func severityFromLevel ( ) * ast . CallExpression {
2019-09-07 02:27:09 +00:00
return flux . Call (
2019-09-06 23:21:41 +00:00
flux . Member ( "pagerduty" , "severityFromLevel" ) ,
2019-09-07 02:27:09 +00:00
flux . Object (
flux . Property ( "level" , flux . Member ( "r" , "_level" ) ) ,
) ,
2019-09-06 23:21:41 +00:00
)
}
func actionFromLevel ( ) * ast . CallExpression {
2019-09-07 02:27:09 +00:00
return flux . Call (
2019-09-06 23:21:41 +00:00
flux . Member ( "pagerduty" , "actionFromLevel" ) ,
2019-09-07 02:27:09 +00:00
flux . Object (
flux . Property ( "level" , flux . Member ( "r" , "_level" ) ) ,
) ,
2019-09-06 23:21:41 +00:00
)
}
func generateTime ( ) * ast . CallExpression {
props := [ ] * ast . Property {
flux . Property ( "v" , flux . Member ( "r" , "_source_timestamp" ) ) ,
}
return flux . Call ( flux . Identifier ( "time" ) , flux . Object ( props ... ) )
}