Save or Exit alert rule before redirecting to config page

pull/10616/head
deniz kusefoglu 2017-12-07 15:53:10 -08:00
parent b7c4756ad6
commit 928be9877c
16 changed files with 245 additions and 72 deletions

View File

@ -1,26 +1,30 @@
import React, {PropTypes} from 'react'
import {Link} from 'react-router'
const HandlerEmpty = ({configLink}) =>
const HandlerEmpty = ({onGoToConfig, validationError}) =>
<div className="endpoint-tab-contents">
<div className="endpoint-tab--parameters">
<div className="endpoint-tab--parameters--empty">
<p>This handler does not seem to be configured.</p>
<Link to={configLink} title="Configuration Page">
<div className="form-group-submit col-xs-12 text-center">
<button className="btn btn-primary" type="submit">
Configure Alert Handlers
</button>
</div>
</Link>
<div className="form-group-submit col-xs-12 text-center">
<button
className="btn btn-primary"
type="submit"
onClick={onGoToConfig}
>
{validationError
? 'Exit Rule and Configure Alert Handlers'
: 'Save Rule and Configure Alert Handlers'}
</button>
</div>
</div>
</div>
</div>
const {string} = PropTypes
const {string, func} = PropTypes
HandlerEmpty.propTypes = {
configLink: string,
onGoToConfig: func.isRequired,
validationError: string.isRequired,
}
export default HandlerEmpty

View File

@ -26,9 +26,10 @@ class HandlerOptions extends Component {
const {
selectedHandler,
handleModifyHandler,
configLink,
rule,
updateDetails,
onGoToConfig,
validationError,
} = this.props
switch (selectedHandler && selectedHandler.type) {
case 'post':
@ -36,7 +37,6 @@ class HandlerOptions extends Component {
<PostHandler
selectedHandler={selectedHandler}
handleModifyHandler={handleModifyHandler}
configLink={configLink}
/>
)
case 'tcp':
@ -44,7 +44,6 @@ class HandlerOptions extends Component {
<TcpHandler
selectedHandler={selectedHandler}
handleModifyHandler={handleModifyHandler}
configLink={configLink}
/>
)
case 'exec':
@ -52,7 +51,6 @@ class HandlerOptions extends Component {
<ExecHandler
selectedHandler={selectedHandler}
handleModifyHandler={handleModifyHandler}
configLink={configLink}
/>
)
case 'log':
@ -60,7 +58,6 @@ class HandlerOptions extends Component {
<LogHandler
selectedHandler={selectedHandler}
handleModifyHandler={handleModifyHandler}
configLink={configLink}
/>
)
case 'email':
@ -68,7 +65,8 @@ class HandlerOptions extends Component {
<EmailHandler
selectedHandler={selectedHandler}
handleModifyHandler={handleModifyHandler}
configLink={configLink}
onGoToConfig={onGoToConfig}
validationError={validationError}
updateDetails={updateDetails}
rule={rule}
/>
@ -78,7 +76,8 @@ class HandlerOptions extends Component {
<AlertaHandler
selectedHandler={selectedHandler}
handleModifyHandler={handleModifyHandler}
configLink={configLink}
onGoToConfig={onGoToConfig}
validationError={validationError}
/>
)
case 'hipChat':
@ -86,7 +85,8 @@ class HandlerOptions extends Component {
<HipchatHandler
selectedHandler={selectedHandler}
handleModifyHandler={handleModifyHandler}
configLink={configLink}
onGoToConfig={onGoToConfig}
validationError={validationError}
/>
)
case 'opsGenie':
@ -94,7 +94,8 @@ class HandlerOptions extends Component {
<OpsgenieHandler
selectedHandler={selectedHandler}
handleModifyHandler={handleModifyHandler}
configLink={configLink}
onGoToConfig={onGoToConfig}
validationError={validationError}
/>
)
case 'pagerDuty':
@ -102,7 +103,8 @@ class HandlerOptions extends Component {
<PagerdutyHandler
selectedHandler={selectedHandler}
handleModifyHandler={handleModifyHandler}
configLink={configLink}
onGoToConfig={onGoToConfig}
validationError={validationError}
/>
)
case 'pushover':
@ -110,7 +112,8 @@ class HandlerOptions extends Component {
<PushoverHandler
selectedHandler={selectedHandler}
handleModifyHandler={handleModifyHandler}
configLink={configLink}
onGoToConfig={onGoToConfig}
validationError={validationError}
/>
)
case 'sensu':
@ -118,7 +121,8 @@ class HandlerOptions extends Component {
<SensuHandler
selectedHandler={selectedHandler}
handleModifyHandler={handleModifyHandler}
configLink={configLink}
onGoToConfig={onGoToConfig}
validationError={validationError}
/>
)
case 'slack':
@ -126,7 +130,8 @@ class HandlerOptions extends Component {
<SlackHandler
selectedHandler={selectedHandler}
handleModifyHandler={handleModifyHandler}
configLink={configLink}
onGoToConfig={onGoToConfig}
validationError={validationError}
/>
)
case 'talk':
@ -134,7 +139,8 @@ class HandlerOptions extends Component {
<TalkHandler
selectedHandler={selectedHandler}
handleModifyHandler={handleModifyHandler}
configLink={configLink}
onGoToConfig={onGoToConfig}
validationError={validationError}
/>
)
case 'telegram':
@ -142,7 +148,8 @@ class HandlerOptions extends Component {
<TelegramHandler
selectedHandler={selectedHandler}
handleModifyHandler={handleModifyHandler}
configLink={configLink}
onGoToConfig={onGoToConfig}
validationError={validationError}
/>
)
case 'victorOps':
@ -150,7 +157,8 @@ class HandlerOptions extends Component {
<VictoropsHandler
selectedHandler={selectedHandler}
handleModifyHandler={handleModifyHandler}
configLink={configLink}
onGoToConfig={onGoToConfig}
validationError={validationError}
/>
)
default:
@ -164,9 +172,10 @@ const {func, shape, string} = PropTypes
HandlerOptions.propTypes = {
selectedHandler: shape({}).isRequired,
handleModifyHandler: func.isRequired,
configLink: string,
updateDetails: func,
rule: shape({}),
onGoToConfig: func.isRequired,
validationError: string.isRequired,
}
export default HandlerOptions

View File

@ -74,6 +74,58 @@ class KapacitorRule extends Component {
})
}
handleSaveToConfig = () => {
const {
addFlashMessage,
queryConfigs,
rule,
router,
configLink,
kapacitor,
} = this.props
const updatedRule = Object.assign({}, rule, {
query: queryConfigs[rule.queryID],
})
if (this.validationError()) {
router.push(configLink)
} else if (rule.id === 'new') {
const newRule = Object.assign({}, rule, {
query: queryConfigs[rule.queryID],
})
delete newRule.queryID
createRule(kapacitor, newRule)
.then(() => {
router.push(configLink)
addFlashMessage({
type: 'success',
text: 'Rule successfully created',
})
})
.catch(() => {
addFlashMessage({
type: 'error',
text: 'There was a problem creating the rule',
})
})
} else {
editRule(updatedRule)
.then(() => {
router.push(configLink)
addFlashMessage({
type: 'success',
text: `${rule.name} successfully saved!`,
})
})
.catch(() => {
addFlashMessage({
type: 'error',
text: `There was a problem saving ${rule.name}`,
})
})
}
}
handleAddEvery = frequency => {
const {rule: {id: ruleID}, ruleActions: {addEvery}} = this.props
addEvery(ruleID, frequency)
@ -143,7 +195,6 @@ class KapacitorRule extends Component {
queryConfigs,
handlersFromConfig,
queryConfigActions,
configLink,
} = this.props
const {chooseTrigger, updateRuleValues} = ruleActions
const {timeRange} = this.state
@ -181,10 +232,11 @@ class KapacitorRule extends Component {
onChooseTimeRange={this.handleChooseTimeRange}
/>
<RuleHandlers
configLink={configLink}
rule={rule}
ruleActions={ruleActions}
handlersFromConfig={handlersFromConfig}
onGoToConfig={this.handleSaveToConfig}
validationError={this.validationError()}
/>
<RuleMessage rule={rule} ruleActions={ruleActions} />
</div>
@ -215,7 +267,7 @@ KapacitorRule.propTypes = {
push: func.isRequired,
}).isRequired,
kapacitor: shape({}).isRequired,
configLink: string,
configLink: string.isRequired,
}
export default KapacitorRule

View File

@ -142,7 +142,13 @@ class RuleHandlers extends Component {
}
render() {
const {handlersFromConfig, configLink, rule, ruleActions} = this.props
const {
handlersFromConfig,
rule,
ruleActions,
onGoToConfig,
validationError,
} = this.props
const {handlersOnThisAlert, selectedHandler} = this.state
const alerts = _.map([...DEFAULT_HANDLERS, ...handlersFromConfig], a => {
return {...a, text: a.type}
@ -178,11 +184,12 @@ class RuleHandlers extends Component {
handleRemoveHandler={this.handleRemoveHandler}
/>
<HandlerOptions
configLink={configLink}
selectedHandler={selectedHandler}
handleModifyHandler={this.handleModifyHandler}
updateDetails={ruleActions.updateDetails}
rule={rule}
onGoToConfig={onGoToConfig}
validationError={validationError}
/>
</div>
: null}
@ -203,7 +210,8 @@ RuleHandlers.propTypes = {
updateAlertProperty: func.isRequired,
}).isRequired,
handlersFromConfig: arrayOf(shape({})),
configLink: string,
onGoToConfig: func.isRequired,
validationError: string.isRequired,
}
export default RuleHandlers

View File

@ -2,7 +2,12 @@ import React, {PropTypes} from 'react'
import HandlerInput from 'src/kapacitor/components/HandlerInput'
import HandlerEmpty from 'src/kapacitor/components/HandlerEmpty'
const AlertaHandler = ({selectedHandler, handleModifyHandler, configLink}) =>
const AlertaHandler = ({
selectedHandler,
handleModifyHandler,
onGoToConfig,
validationError,
}) =>
selectedHandler.enabled
? <div className="endpoint-tab-contents">
<div className="endpoint-tab--parameters">
@ -76,14 +81,19 @@ const AlertaHandler = ({selectedHandler, handleModifyHandler, configLink}) =>
</div>
</div>
</div>
: <HandlerEmpty configLink={configLink} />
: <HandlerEmpty
onGoToConfig={onGoToConfig}
validationError={validationError}
/>
const {func, shape, string} = PropTypes
AlertaHandler.propTypes = {
selectedHandler: shape({}).isRequired,
handleModifyHandler: func.isRequired,
configLink: string,
onGoToConfig: func.isRequired,
validationError: string.isRequired,
}
export default AlertaHandler

View File

@ -8,7 +8,8 @@ const EmailHandler = ({
updateDetails,
selectedHandler,
handleModifyHandler,
configLink,
onGoToConfig,
validationError,
}) =>
selectedHandler.enabled
? <div className="endpoint-tab-contents">
@ -60,16 +61,21 @@ const EmailHandler = ({
</div>
</div>
</div>
: <HandlerEmpty configLink={configLink} />
: <HandlerEmpty
onGoToConfig={onGoToConfig}
validationError={validationError}
/>
const {func, shape, string} = PropTypes
EmailHandler.propTypes = {
selectedHandler: shape({}).isRequired,
handleModifyHandler: func.isRequired,
configLink: string,
updateDetails: func,
rule: shape({}),
onGoToConfig: func.isRequired,
validationError: string.isRequired,
}
export default EmailHandler

View File

@ -2,7 +2,12 @@ import React, {PropTypes} from 'react'
import HandlerInput from 'src/kapacitor/components/HandlerInput'
import HandlerEmpty from 'src/kapacitor/components/HandlerEmpty'
const HipchatHandler = ({selectedHandler, handleModifyHandler, configLink}) =>
const HipchatHandler = ({
selectedHandler,
handleModifyHandler,
onGoToConfig,
validationError,
}) =>
selectedHandler.enabled
? <div className="endpoint-tab-contents">
<div className="endpoint-tab--parameters">
@ -35,14 +40,19 @@ const HipchatHandler = ({selectedHandler, handleModifyHandler, configLink}) =>
</div>
</div>
</div>
: <HandlerEmpty configLink={configLink} />
: <HandlerEmpty
onGoToConfig={onGoToConfig}
validationError={validationError}
/>
const {func, shape, string} = PropTypes
HipchatHandler.propTypes = {
selectedHandler: shape({}).isRequired,
handleModifyHandler: func.isRequired,
configLink: string,
onGoToConfig: func.isRequired,
validationError: string.isRequired,
}
export default HipchatHandler

View File

@ -2,7 +2,12 @@ import React, {PropTypes} from 'react'
import HandlerInput from 'src/kapacitor/components/HandlerInput'
import HandlerEmpty from 'src/kapacitor/components/HandlerEmpty'
const OpsgenieHandler = ({selectedHandler, handleModifyHandler, configLink}) =>
const OpsgenieHandler = ({
selectedHandler,
handleModifyHandler,
onGoToConfig,
validationError,
}) =>
selectedHandler.enabled
? <div className="endpoint-tab-contents">
<div className="endpoint-tab--parameters">
@ -42,14 +47,18 @@ const OpsgenieHandler = ({selectedHandler, handleModifyHandler, configLink}) =>
</div>
</div>
</div>
: <HandlerEmpty configLink={configLink} />
: <HandlerEmpty
onGoToConfig={onGoToConfig}
validationError={validationError}
/>
const {func, shape, string} = PropTypes
OpsgenieHandler.propTypes = {
selectedHandler: shape({}).isRequired,
handleModifyHandler: func.isRequired,
configLink: string,
onGoToConfig: func.isRequired,
validationError: string.isRequired,
}
export default OpsgenieHandler

View File

@ -2,7 +2,12 @@ import React, {PropTypes} from 'react'
import HandlerInput from 'src/kapacitor/components/HandlerInput'
import HandlerEmpty from 'src/kapacitor/components/HandlerEmpty'
const PagerdutyHandler = ({selectedHandler, handleModifyHandler, configLink}) =>
const PagerdutyHandler = ({
selectedHandler,
handleModifyHandler,
onGoToConfig,
validationError,
}) =>
selectedHandler.enabled
? <div className="endpoint-tab-contents">
<div className="endpoint-tab--parameters">
@ -18,14 +23,18 @@ const PagerdutyHandler = ({selectedHandler, handleModifyHandler, configLink}) =>
/>
</div>
</div>
: <HandlerEmpty configLink={configLink} />
: <HandlerEmpty
onGoToConfig={onGoToConfig}
validationError={validationError}
/>
const {func, shape, string} = PropTypes
PagerdutyHandler.propTypes = {
selectedHandler: shape({}).isRequired,
handleModifyHandler: func.isRequired,
configLink: string,
onGoToConfig: func.isRequired,
validationError: string.isRequired,
}
export default PagerdutyHandler

View File

@ -2,7 +2,12 @@ import React, {PropTypes} from 'react'
import HandlerInput from 'src/kapacitor/components/HandlerInput'
import HandlerEmpty from 'src/kapacitor/components/HandlerEmpty'
const PushoverHandler = ({selectedHandler, handleModifyHandler, configLink}) =>
const PushoverHandler = ({
selectedHandler,
handleModifyHandler,
onGoToConfig,
validationError,
}) =>
selectedHandler.enabled
? <div className="endpoint-tab-contents">
<div className="endpoint-tab--parameters">
@ -69,14 +74,18 @@ const PushoverHandler = ({selectedHandler, handleModifyHandler, configLink}) =>
</div>
</div>
</div>
: <HandlerEmpty configLink={configLink} />
: <HandlerEmpty
onGoToConfig={onGoToConfig}
validationError={validationError}
/>
const {func, shape, string} = PropTypes
PushoverHandler.propTypes = {
selectedHandler: shape({}).isRequired,
handleModifyHandler: func.isRequired,
configLink: string,
onGoToConfig: func.isRequired,
validationError: string.isRequired,
}
export default PushoverHandler

View File

@ -2,7 +2,12 @@ import React, {PropTypes} from 'react'
import HandlerInput from 'src/kapacitor/components/HandlerInput'
import HandlerEmpty from 'src/kapacitor/components/HandlerEmpty'
const SensuHandler = ({selectedHandler, handleModifyHandler, configLink}) =>
const SensuHandler = ({
selectedHandler,
handleModifyHandler,
onGoToConfig,
validationError,
}) =>
selectedHandler.enabled
? <div className="endpoint-tab-contents">
<div className="endpoint-tab--parameters">
@ -40,14 +45,18 @@ const SensuHandler = ({selectedHandler, handleModifyHandler, configLink}) =>
</div>
</div>
</div>
: <HandlerEmpty configLink={configLink} />
: <HandlerEmpty
onGoToConfig={onGoToConfig}
validationError={validationError}
/>
const {func, shape, string} = PropTypes
SensuHandler.propTypes = {
selectedHandler: shape({}).isRequired,
handleModifyHandler: func.isRequired,
configLink: string,
onGoToConfig: func.isRequired,
validationError: string.isRequired,
}
export default SensuHandler

View File

@ -2,7 +2,12 @@ import React, {PropTypes} from 'react'
import HandlerInput from 'src/kapacitor/components/HandlerInput'
import HandlerEmpty from 'src/kapacitor/components/HandlerEmpty'
const SlackHandler = ({selectedHandler, handleModifyHandler, configLink}) =>
const SlackHandler = ({
selectedHandler,
handleModifyHandler,
onGoToConfig,
validationError,
}) =>
selectedHandler.enabled
? <div className="endpoint-tab-contents">
<div className="endpoint-tab--parameters">
@ -50,14 +55,18 @@ const SlackHandler = ({selectedHandler, handleModifyHandler, configLink}) =>
</div>
</div>
</div>
: <HandlerEmpty configLink={configLink} />
: <HandlerEmpty
onGoToConfig={onGoToConfig}
validationError={validationError}
/>
const {func, shape, string} = PropTypes
SlackHandler.propTypes = {
selectedHandler: shape({}).isRequired,
handleModifyHandler: func.isRequired,
configLink: string,
onGoToConfig: func.isRequired,
validationError: string.isRequired,
}
export default SlackHandler

View File

@ -2,7 +2,12 @@ import React, {PropTypes} from 'react'
import HandlerInput from 'src/kapacitor/components/HandlerInput'
import HandlerEmpty from 'src/kapacitor/components/HandlerEmpty'
const TalkHandler = ({selectedHandler, handleModifyHandler, configLink}) =>
const TalkHandler = ({
selectedHandler,
handleModifyHandler,
onGoToConfig,
validationError,
}) =>
selectedHandler.enabled
? <div className="endpoint-tab-contents">
<div className="endpoint-tab--parameters">
@ -28,14 +33,18 @@ const TalkHandler = ({selectedHandler, handleModifyHandler, configLink}) =>
</div>
</div>
</div>
: <HandlerEmpty configLink={configLink} />
: <HandlerEmpty
onGoToConfig={onGoToConfig}
validationError={validationError}
/>
const {func, shape, string} = PropTypes
TalkHandler.propTypes = {
selectedHandler: shape({}).isRequired,
handleModifyHandler: func.isRequired,
configLink: string,
onGoToConfig: func.isRequired,
validationError: string.isRequired,
}
export default TalkHandler

View File

@ -3,7 +3,12 @@ import HandlerInput from 'src/kapacitor/components/HandlerInput'
import HandlerCheckbox from 'src/kapacitor/components/HandlerCheckbox'
import HandlerEmpty from 'src/kapacitor/components/HandlerEmpty'
const TelegramHandler = ({selectedHandler, handleModifyHandler, configLink}) =>
const TelegramHandler = ({
selectedHandler,
handleModifyHandler,
onGoToConfig,
validationError,
}) =>
selectedHandler.enabled
? <div className="endpoint-tab-contents">
<div className="endpoint-tab--parameters">
@ -53,14 +58,18 @@ const TelegramHandler = ({selectedHandler, handleModifyHandler, configLink}) =>
</div>
</div>
</div>
: <HandlerEmpty configLink={configLink} />
: <HandlerEmpty
onGoToConfig={onGoToConfig}
validationError={validationError}
/>
const {func, shape, string} = PropTypes
TelegramHandler.propTypes = {
selectedHandler: shape({}).isRequired,
handleModifyHandler: func.isRequired,
configLink: string,
onGoToConfig: func.isRequired,
validationError: string.isRequired,
}
export default TelegramHandler

View File

@ -2,7 +2,12 @@ import React, {PropTypes} from 'react'
import HandlerInput from 'src/kapacitor/components/HandlerInput'
import HandlerEmpty from 'src/kapacitor/components/HandlerEmpty'
const VictoropsHandler = ({selectedHandler, handleModifyHandler, configLink}) =>
const VictoropsHandler = ({
selectedHandler,
handleModifyHandler,
onGoToConfig,
validationError,
}) =>
selectedHandler.enabled
? <div className="endpoint-tab-contents">
<div className="endpoint-tab--parameters">
@ -34,14 +39,18 @@ const VictoropsHandler = ({selectedHandler, handleModifyHandler, configLink}) =>
</div>
</div>
</div>
: <HandlerEmpty configLink={configLink} />
: <HandlerEmpty
onGoToConfig={onGoToConfig}
validationError={validationError}
/>
const {func, shape, string} = PropTypes
VictoropsHandler.propTypes = {
selectedHandler: shape({}).isRequired,
handleModifyHandler: func.isRequired,
configLink: string,
onGoToConfig: func.isRequired,
validationError: string.isRequired,
}
export default VictoropsHandler

View File

@ -80,11 +80,13 @@ export default function rules(state = {}, action) {
const {ruleID, alerts} = action.payload
const alertNodesByType = {}
_.forEach(alerts, ep => {
const existing = _.get(alertNodesByType, ep.type, [])
alertNodesByType[ep.type] = [
...existing,
_.pick(ep, ALERTS_TO_RULE[ep.type]),
]
if (ep.enabled) {
const existing = _.get(alertNodesByType, ep.type, [])
alertNodesByType[ep.type] = [
...existing,
_.pick(ep, ALERTS_TO_RULE[ep.type]),
]
}
})
return Object.assign({}, state, {
[ruleID]: Object.assign({}, state[ruleID], {