Define Endpoint types according to Kapacitor expectations

pull/10616/head
deniz kusefoglu 2017-11-13 20:26:15 -08:00
parent b211d0520a
commit 21b2509192
21 changed files with 269 additions and 104 deletions

View File

@ -19,7 +19,7 @@ const EndpointInput = ({
type="text"
placeholder={placeholder}
onChange={handleModifyEndpoint(selectedEndpoint, fieldName)}
value={selectedEndpoint.options[fieldName]}
value={selectedEndpoint[fieldName]}
autoComplete="off"
spellCheck="false"
/>

View File

@ -1,6 +1,6 @@
import React, {Component, PropTypes} from 'react'
import {
HttpConfig,
PostConfig,
TcpConfig,
ExecConfig,
LogConfig,
@ -25,9 +25,9 @@ class EndpointOptions extends Component {
render() {
const {selectedEndpoint, handleModifyEndpoint} = this.props
switch (selectedEndpoint && selectedEndpoint.type) {
case 'http':
case 'post':
return (
<HttpConfig
<PostConfig
selectedEndpoint={selectedEndpoint}
handleModifyEndpoint={handleModifyEndpoint}
/>

View File

@ -16,9 +16,11 @@ const alertNodesToEndpoints = rule => {
const count = _.get(endpointsOfKind, an.name, 0) + 1
endpointsOfKind[an.name] = count
const ep = {
...an.properties,
...an.args,
...an,
alias: an.name + count,
type: an.name,
options: {...an.properties, args: an.args || {}},
}
endpointsOnThisAlert.push(ep)
})
@ -101,15 +103,15 @@ class RuleMessage extends Component {
handleUpdateAllAlerts = () => {
const {rule, actions} = this.props
const {endpointsOnThisAlert} = this.state
actions.updateAlertNodes(rule.id, endpointsOnThisAlert)
actions.updateAlerts(rule.id, endpointsOnThisAlert)
}
handleModifyEndpoint = (selectedEndpoint, fieldName) => e => {
const {endpointsOnThisAlert} = this.state
const modifiedEP = {
...selectedEndpoint,
options: {...selectedEndpoint.options, [fieldName]: e.target.value},
[fieldName]: e.target.value,
}
const remainingEndpoints = _.reject(endpointsOnThisAlert, [
'alias',

View File

@ -9,9 +9,65 @@ const AlertaConfig = ({selectedEndpoint, handleModifyEndpoint}) => {
<EndpointInput
selectedEndpoint={selectedEndpoint}
handleModifyEndpoint={handleModifyEndpoint}
fieldName="script"
fieldDisplay="Alerta TICKscript"
placeholder="alerta()"
fieldName="token"
fieldDisplay="Token"
placeholder="Ex: my_token"
/>
<EndpointInput
selectedEndpoint={selectedEndpoint}
handleModifyEndpoint={handleModifyEndpoint}
fieldName="resource"
fieldDisplay="Resource"
placeholder="Ex: my_resource"
/>
<EndpointInput
selectedEndpoint={selectedEndpoint}
handleModifyEndpoint={handleModifyEndpoint}
fieldName="event"
fieldDisplay="Event"
placeholder="Ex: event"
/>
<EndpointInput
selectedEndpoint={selectedEndpoint}
handleModifyEndpoint={handleModifyEndpoint}
fieldName="environment"
fieldDisplay="Environment"
placeholder="Ex: environment"
/>
<EndpointInput
selectedEndpoint={selectedEndpoint}
handleModifyEndpoint={handleModifyEndpoint}
fieldName="group"
fieldDisplay="Group"
placeholder="Ex: group_name"
/>
<EndpointInput
selectedEndpoint={selectedEndpoint}
handleModifyEndpoint={handleModifyEndpoint}
fieldName="value"
fieldDisplay="Value"
placeholder="Ex: value"
/>
<EndpointInput
selectedEndpoint={selectedEndpoint}
handleModifyEndpoint={handleModifyEndpoint}
fieldName="origin"
fieldDisplay="Origin"
placeholder="Ex: origin"
/>
<EndpointInput
selectedEndpoint={selectedEndpoint}
handleModifyEndpoint={handleModifyEndpoint}
fieldName="service"
fieldDisplay="Service"
placeholder="Ex: my_token"
/>
<EndpointInput
selectedEndpoint={selectedEndpoint}
handleModifyEndpoint={handleModifyEndpoint}
fieldName="timeout"
fieldDisplay="Timeout"
placeholder="Ex: timeout_duration"
/>
</div>
</div>

View File

@ -11,7 +11,7 @@ const ExecConfig = ({selectedEndpoint, handleModifyEndpoint}) => {
handleModifyEndpoint={handleModifyEndpoint}
fieldName="command"
fieldDisplay="Command (arguments separated by spaces):"
placeholder="Ex: woogie boogie"
placeholder="Ex: command argument"
/>
</div>
</div>

View File

@ -9,8 +9,8 @@ const LogConfig = ({selectedEndpoint, handleModifyEndpoint}) => {
<EndpointInput
selectedEndpoint={selectedEndpoint}
handleModifyEndpoint={handleModifyEndpoint}
fieldName="file"
fieldDisplay="Destination of Log File:"
fieldName="filePath"
fieldDisplay="Log File Path:"
placeholder="Ex: /tmp/alerts.log"
/>
</div>

View File

@ -1,9 +1,35 @@
import React, {PropTypes} from 'react'
import EndpointInput from 'src/kapacitor/components/EndpointInput'
const OpsgenieConfig = () => {
return <div>this is OpsgenieConfig</div>
const OpsgenieConfig = ({selectedEndpoint, handleModifyEndpoint}) => {
return (
<div className="rule-section--row rule-section--border-bottom">
<p>Alert Parameters:</p>
<div className="optional-alert-parameters">
<EndpointInput
selectedEndpoint={selectedEndpoint}
handleModifyEndpoint={handleModifyEndpoint}
fieldName="teams"
fieldDisplay="Teams"
placeholder="Ex: teams_name"
/>
<EndpointInput
selectedEndpoint={selectedEndpoint}
handleModifyEndpoint={handleModifyEndpoint}
fieldName="recipients"
fieldDisplay="Recipients"
placeholder="Ex: recipients_name"
/>
</div>
</div>
)
}
OpsgenieConfig.propTypes = {}
const {func, shape} = PropTypes
OpsgenieConfig.propTypes = {
selectedEndpoint: shape({}).isRequired,
handleModifyEndpoint: func.isRequired,
}
export default OpsgenieConfig

View File

@ -10,8 +10,8 @@ const PagerdutyConfig = ({selectedEndpoint, handleModifyEndpoint}) => {
selectedEndpoint={selectedEndpoint}
handleModifyEndpoint={handleModifyEndpoint}
fieldName="serviceKey"
fieldDisplay="Servive Key:"
placeholder="Ex: a_key"
fieldDisplay="Service Key:"
placeholder="Ex: service_key"
/>
</div>
</div>

View File

@ -10,14 +10,7 @@ const HttpConfig = ({selectedEndpoint, handleModifyEndpoint}) => {
selectedEndpoint={selectedEndpoint}
handleModifyEndpoint={handleModifyEndpoint}
fieldName="url"
fieldDisplay="URL"
placeholder="Ex: http://example.com/api/alert"
/>
<EndpointInput
selectedEndpoint={selectedEndpoint}
handleModifyEndpoint={handleModifyEndpoint}
fieldName="url"
fieldDisplay="URL"
fieldDisplay="POST URL"
placeholder="Ex: http://example.com/api/alert"
/>
</div>

View File

@ -6,12 +6,19 @@ const PushoverConfig = ({selectedEndpoint, handleModifyEndpoint}) => {
<div className="rule-section--row rule-section--border-bottom">
<p>Alert Parameters:</p>
<div className="optional-alert-parameters">
<EndpointInput
selectedEndpoint={selectedEndpoint}
handleModifyEndpoint={handleModifyEndpoint}
fieldName="userKey"
fieldDisplay="User Key"
placeholder="Ex: the_key"
/>
<EndpointInput
selectedEndpoint={selectedEndpoint}
handleModifyEndpoint={handleModifyEndpoint}
fieldName="device"
fieldDisplay="Device: (comma separated)"
placeholder="Ex: dv1,dv2"
placeholder="Ex: dv1, dv2"
/>
<EndpointInput
selectedEndpoint={selectedEndpoint}
@ -25,14 +32,14 @@ const PushoverConfig = ({selectedEndpoint, handleModifyEndpoint}) => {
<EndpointInput
selectedEndpoint={selectedEndpoint}
handleModifyEndpoint={handleModifyEndpoint}
fieldName="URL"
fieldName="url"
fieldDisplay="URL:"
placeholder="Ex: https://influxdata.com"
/>
<EndpointInput
selectedEndpoint={selectedEndpoint}
handleModifyEndpoint={handleModifyEndpoint}
fieldName="URLTitle"
fieldName="urlTitle"
fieldDisplay="URL Title:"
placeholder="Ex: InfluxData"
/>

View File

@ -9,7 +9,7 @@ const SmtpConfig = ({selectedEndpoint, handleModifyEndpoint}) => {
<EndpointInput
selectedEndpoint={selectedEndpoint}
handleModifyEndpoint={handleModifyEndpoint}
fieldName="email"
fieldName="to"
fieldDisplay="E-mail Addresses: (separated by spaces)"
placeholder="Ex: bob@domain.com susan@domain.com"
/>

View File

@ -1,9 +1,35 @@
import React, {PropTypes} from 'react'
import EndpointInput from 'src/kapacitor/components/EndpointInput'
const SensuConfig = () => {
return <div>this is SensuConfig</div>
const SensuConfig = ({selectedEndpoint, handleModifyEndpoint}) => {
return (
<div className="rule-section--row rule-section--border-bottom">
<p>Alert Parameters:</p>
<div className="optional-alert-parameters">
<EndpointInput
selectedEndpoint={selectedEndpoint}
handleModifyEndpoint={handleModifyEndpoint}
fieldName="source"
fieldDisplay="Source"
placeholder="Ex: my_source"
/>
<EndpointInput
selectedEndpoint={selectedEndpoint}
handleModifyEndpoint={handleModifyEndpoint}
fieldName="handlers"
fieldDisplay="Handlers"
placeholder="Ex: my_handlers"
/>
</div>
</div>
)
}
SensuConfig.propTypes = {}
const {func, shape} = PropTypes
SensuConfig.propTypes = {
selectedEndpoint: shape({}).isRequired,
handleModifyEndpoint: func.isRequired,
}
export default SensuConfig

View File

@ -11,7 +11,14 @@ const SlackConfig = ({selectedEndpoint, handleModifyEndpoint}) => {
handleModifyEndpoint={handleModifyEndpoint}
fieldName="channel"
fieldDisplay="Channel:"
placeholder="Ex: #My_favorite_channel"
placeholder="Ex: #my_favorite_channel"
/>
<EndpointInput
selectedEndpoint={selectedEndpoint}
handleModifyEndpoint={handleModifyEndpoint}
fieldName="username"
fieldDisplay="Username:"
placeholder="Ex: my_favorite_username"
/>
<EndpointInput
selectedEndpoint={selectedEndpoint}
@ -20,13 +27,6 @@ const SlackConfig = ({selectedEndpoint, handleModifyEndpoint}) => {
fieldDisplay="Emoji:"
placeholder="Ex: :thumbsup:"
/>
<EndpointInput
selectedEndpoint={selectedEndpoint}
handleModifyEndpoint={handleModifyEndpoint}
fieldName="username"
fieldDisplay="Username:"
placeholder="Ex: my_favorite_alert"
/>
</div>
</div>
)

View File

@ -1,9 +1,18 @@
import React, {PropTypes} from 'react'
const TalkConfig = () => {
return <div>this is TalkConfig</div>
return (
<div className="rule-section--row rule-section--border-bottom">
<p>Talk requires no additional alert parameters.</p>
</div>
)
}
TalkConfig.propTypes = {}
const {func, shape} = PropTypes
TalkConfig.propTypes = {
selectedEndpoint: shape({}).isRequired,
handleModifyEndpoint: func.isRequired,
}
export default TalkConfig

View File

@ -1,7 +1,7 @@
import React, {PropTypes} from 'react'
import EndpointInput from 'src/kapacitor/components/EndpointInput'
const HttpConfig = ({selectedEndpoint, handleModifyEndpoint}) => {
const TelegramConfig = ({selectedEndpoint, handleModifyEndpoint}) => {
return (
<div className="rule-section--row rule-section--border-bottom">
<p>Alert Parameters:</p>
@ -27,9 +27,9 @@ const HttpConfig = ({selectedEndpoint, handleModifyEndpoint}) => {
const {func, shape} = PropTypes
HttpConfig.propTypes = {
TelegramConfig.propTypes = {
selectedEndpoint: shape({}).isRequired,
handleModifyEndpoint: func.isRequired,
}
export default HttpConfig
export default TelegramConfig

View File

@ -10,8 +10,8 @@ const VictoropsConfig = ({selectedEndpoint, handleModifyEndpoint}) => {
selectedEndpoint={selectedEndpoint}
handleModifyEndpoint={handleModifyEndpoint}
fieldName="routingKey"
fieldDisplay="Channel:"
placeholder="Ex: team_rocket"
fieldDisplay="Routing Key:"
placeholder="Ex: routing_key"
/>
</div>
</div>

View File

@ -1,4 +1,4 @@
import HttpConfig from './HttpConfig'
import PostConfig from './PostConfig'
import TcpConfig from './TcpConfig'
import ExecConfig from './ExecConfig'
import LogConfig from './LogConfig'
@ -15,7 +15,7 @@ import TelegramConfig from './TelegramConfig'
import VictoropsConfig from './VictoropsConfig'
export {
HttpConfig,
PostConfig,
TcpConfig,
ExecConfig,
LogConfig,

View File

@ -87,14 +87,84 @@ export const RULE_MESSAGE_TEMPLATES = {
text: 'The time of the point that triggered the event',
},
}
// DEFAULT_ALERTS provides a template for alerts that don't exist in the kapacitor config
export const DEFAULT_ALERTS = [
{type: 'http', options: {url: ''}},
{type: 'tcp', options: {address: ''}},
{type: 'exec', options: {command: ''}},
{type: 'log', options: {file: ''}},
{type: 'post', url: '', headers: '', captureResponse: '', timeout: ''}, // is actually called 'post'??
{type: 'tcp', address: ''},
{type: 'exec', command: ''},
{type: 'log', filePath: ''},
]
// ALERT_FIELDS_FROM_CONFIG returns an array of fields to accept from the Kapacitor Config
// I WILL NEED TO ADD MORE TO DISPLAY FIELDS WHICH COME FROM THE CONFIG WHICH WILL JUST BE DISPLAYED NOT EDITABLE>
// I need to check what happens when one of these fields does not exist- the value in the input will fail at first. ?? add a default val?
export const ALERT_FIELDS_FROM_CONFIG = {
alerta: [
'token',
'resource',
'event',
'environment',
'group',
'value',
'origin',
'service',
'timeout',
],
hipchat: ['room', 'token'],
opsgenie: ['teams', 'recipients'],
pagerduty: ['serviceKey'],
pushover: ['userKey', 'device', 'title', 'url', 'urlTitle', 'sound'],
sensu: ['source', 'handlers'],
slack: ['channel', 'username', 'iconEmoji'],
smtp: ['to'],
snmpTrap: ['trapOid', 'data'], // [oid/type/value]
talk: [],
telegram: [
'chatId',
'parseMode',
'disableWebPagePreview',
'disableNotification',
],
victorOps: ['routingKey'],
influxdb: [],
}
// ALERTS_TO_RULE returns array of fields that may be updated for each alert on rule.
export const ALERT_FIELDS_TO_RULE = {
alerta: [
'token',
'resource',
'event',
'environment',
'group',
'value',
'origin',
'service',
'timeout',
],
hipchat: ['room', 'token'],
opsgenie: ['teams', 'recipients'],
pagerduty: ['serviceKey'],
pushover: ['userKey', 'device', 'title', 'url', 'urlTitle', 'sound'],
sensu: ['source', 'handlers'],
slack: ['channel', 'username', 'iconEmoji'],
email: ['to'],
snmpTrap: ['trapOid', 'data'], // [oid/type/value]
talk: [],
telegram: [
'chatId',
'parseMode',
'disableWebPagePreview',
'disableNotification',
],
victorOps: ['routingKey'],
influxdb: [], // ?????
post: ['url', 'headers', 'captureResponse', 'timeout'],
tcp: ['address'],
exec: ['command'],
log: ['filePath'],
}
export const RULE_ALERT_OPTIONS = {
http: {
args: {

View File

@ -7,18 +7,24 @@ import * as kapacitorQueryConfigActionCreators from 'src/kapacitor/actions/query
import {bindActionCreators} from 'redux'
import {getActiveKapacitor, getKapacitorConfig} from 'shared/apis/index'
import {DEFAULT_RULE_ID} from 'src/kapacitor/constants'
import {
DEFAULT_RULE_ID,
ALERT_FIELDS_FROM_CONFIG,
} from 'src/kapacitor/constants'
import KapacitorRule from 'src/kapacitor/components/KapacitorRule'
const getEnabled = config => {
const {data: {sections}} = config
const allAlerts = _.map(sections, (v, k) => {
return {type: k, options: _.get(v, ['elements', '0', 'options'], {})}
const fromConfig = _.get(v, ['elements', '0', 'options'], {})
const pickedFromConfig = _.pick(fromConfig, [
ALERT_FIELDS_FROM_CONFIG[k],
'enabled',
])
return {type: k, ...pickedFromConfig}
})
let enabledAlerts = _.filter(allAlerts, v =>
_.get(v, ['options', 'enabled'], false)
)
enabledAlerts = _.reject(enabledAlerts, v => v.type === 'influxdb') // TODO: should I be whitelisting here??
let enabledAlerts = _.filter(allAlerts, v => _.get(v, ['enabled'], false))
enabledAlerts = _.reject(enabledAlerts, v => v.type === 'influxdb') // TODO: remove this.
return enabledAlerts
}

View File

@ -1,6 +1,9 @@
import {defaultRuleConfigs, DEFAULT_RULE_ID} from 'src/kapacitor/constants'
import {
defaultRuleConfigs,
DEFAULT_RULE_ID,
ALERT_FIELDS_TO_RULE,
} from 'src/kapacitor/constants'
import _ from 'lodash'
import {parseAlerta} from 'shared/parsing/parseAlerta'
export default function rules(state = {}, action) {
switch (action.type) {
@ -86,46 +89,13 @@ export default function rules(state = {}, action) {
case 'UPDATE_RULE_ALERT_NODES': {
const {ruleID, alerts} = action.payload
const alertNodesByType = alerts.map(alert => {
const {type, alias} = alert
switch (type) {
case 'http':
case 'tcp':
case 'log':
return {
name: type,
args: [alias],
properties: [],
}
case 'exec':
case 'smtp':
return [
{
name: type,
args: alias.split(' '),
properties: [],
},
]
case 'alerta':
return {
name: type,
args: [],
properties: parseAlerta(alias),
}
case 'hipchat':
case 'opsgenie':
case 'pagerduty':
case 'slack':
case 'telegram':
case 'victorops':
case 'pushover':
default:
return {
name: type,
args: [],
properties: [],
}
}
const alertNodesByType = {}
_.forEach(alerts, ep => {
const existing = _.get(alertNodesByType, ep.type, [])
alertNodesByType[ep.type] = [
...existing,
_.pick(ep, ALERT_FIELDS_TO_RULE[ep.type]),
]
})
return Object.assign({}, state, {
[ruleID]: Object.assign({}, state[ruleID], {

View File

@ -451,7 +451,7 @@ $dash-editable-header-padding: 7px;
}
}
}
}
/* Add borders between items in .nav-tablist
-----------------------------------------------------------------------------
TODO: Add these styles into the theme