Refactor parseAlerta spec to test reducer, accessors, and parser separately. Refactor parseAlerta out of rules reducer into its own file in shared/prasing. Update appearance of AlertaConfig. Update appearance of RuleMessage input field. Remove smtp and alerta from default alerts.
parent
e9d8b77a96
commit
d428aaf8c7
|
@ -110,58 +110,15 @@ describe('Kapacitor.Reducers.rules', () => {
|
|||
`;
|
||||
|
||||
let newState = reducer(initialState, updateAlertNodes(ruleID, 'alerta', tickScript));
|
||||
|
||||
const expectedObj = [
|
||||
{
|
||||
"name": "alerta",
|
||||
"args": [],
|
||||
"properties": [
|
||||
{
|
||||
"name": "resource",
|
||||
"args": [
|
||||
"Hostname or service"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "event",
|
||||
"args": [
|
||||
"Something went wrong"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "environment",
|
||||
"args": [
|
||||
"Development"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "group",
|
||||
"args": [
|
||||
"Dev. Servers"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "services",
|
||||
"args": [
|
||||
"a",
|
||||
"b",
|
||||
"c"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
];
|
||||
const expectedStr = `alerta().resource('Hostname or service').event('Something went wrong').environment('Development').group('Dev. Servers').services('a b c')`;
|
||||
let actualStr = ALERT_NODES_ACCESSORS.alerta(newState[ruleID]);
|
||||
|
||||
// Test both data structure and accessor string
|
||||
expect(newState[ruleID].alertNodes).to.deep.equal(expectedObj);
|
||||
expect(actualStr).to.equal(expectedStr);
|
||||
|
||||
// Test that accessor string is the same if fed back in
|
||||
newState = reducer(newState, updateAlertNodes(ruleID, 'alerta', actualStr));
|
||||
actualStr = ALERT_NODES_ACCESSORS.alerta(newState[ruleID]);
|
||||
expect(newState[ruleID].alertNodes).to.deep.equal(expectedObj);
|
||||
expect(actualStr).to.equal(expectedStr);
|
||||
});
|
||||
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
import {parseAlerta} from 'src/shared/parsing/parseAlerta';
|
||||
|
||||
it('can parse an alerta tick script', () => {
|
||||
const tickScript = `stream
|
||||
|alert()
|
||||
.alerta()
|
||||
.resource('Hostname or service')
|
||||
.event('Something went wrong')
|
||||
.environment('Development')
|
||||
.group('Dev. Servers')
|
||||
.services('a b c')
|
||||
`;
|
||||
|
||||
let actualObj = parseAlerta(tickScript);
|
||||
|
||||
const expectedObj = [
|
||||
{
|
||||
"name": "resource",
|
||||
"args": [
|
||||
"Hostname or service"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "event",
|
||||
"args": [
|
||||
"Something went wrong"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "environment",
|
||||
"args": [
|
||||
"Development"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "group",
|
||||
"args": [
|
||||
"Dev. Servers"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "services",
|
||||
"args": [
|
||||
"a",
|
||||
"b",
|
||||
"c"
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
// Test data structure
|
||||
expect(actualObj).to.deep.equal(expectedObj);
|
||||
|
||||
// Test that data structure is the same if fed back in
|
||||
const expectedStr = `alerta().resource('Hostname or service').event('Something went wrong').environment('Development').group('Dev. Servers').services('a b c')`;
|
||||
actualObj = parseAlerta(expectedStr);
|
||||
expect(actualObj).to.deep.equal(expectedObj);
|
||||
});
|
|
@ -30,44 +30,37 @@ const AlertaConfig = React.createClass({
|
|||
const {environment, origin, token, url} = this.props.config.options;
|
||||
|
||||
return (
|
||||
<div className="col-xs-12 col-sm-8 col-sm-offset-2">
|
||||
<div className="col-xs-12">
|
||||
<h4 className="text-center">Alerta Alert</h4>
|
||||
<br/>
|
||||
<form onSubmit={this.handleSaveAlert}>
|
||||
<div className="row">
|
||||
<div className="col-xs-7 col-sm-8 col-sm-offset-2">
|
||||
<p>
|
||||
Have alerts sent to Alerta
|
||||
</p>
|
||||
<p>
|
||||
Have alerts sent to Alerta
|
||||
</p>
|
||||
|
||||
<div className="form-group">
|
||||
<label htmlFor="environment">Environment</label>
|
||||
<input className="form-control" id="environment" type="text" ref={(r) => this.environment = r} defaultValue={environment || ''}></input>
|
||||
</div>
|
||||
|
||||
<div className="form-group">
|
||||
<label htmlFor="origin">Origin</label>
|
||||
<input className="form-control" id="origin" type="text" ref={(r) => this.origin = r} defaultValue={origin || ''}></input>
|
||||
</div>
|
||||
|
||||
<div className="form-group">
|
||||
<label htmlFor="token">Token</label>
|
||||
<input className="form-control" id="token" type="text" ref={(r) => this.token = r} defaultValue={token || ''}></input>
|
||||
<span>Note: a value of <code>true</code> indicates the Alerta Token has been set</span>
|
||||
</div>
|
||||
|
||||
<div className="form-group">
|
||||
<label htmlFor="url">User</label>
|
||||
<input className="form-control" id="url" type="text" ref={(r) => this.url = r} defaultValue={url || ''}></input>
|
||||
</div>
|
||||
</div>
|
||||
<div className="form-group col-xs-12">
|
||||
<label htmlFor="environment">Environment</label>
|
||||
<input className="form-control" id="environment" type="text" ref={(r) => this.environment = r} defaultValue={environment || ''}></input>
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
<div className="row">
|
||||
<div className="form-group col-xs-5 col-sm-3 col-sm-offset-2">
|
||||
<button className="btn btn-block btn-primary" type="submit">Save</button>
|
||||
</div>
|
||||
<div className="form-group col-xs-12">
|
||||
<label htmlFor="origin">Origin</label>
|
||||
<input className="form-control" id="origin" type="text" ref={(r) => this.origin = r} defaultValue={origin || ''}></input>
|
||||
</div>
|
||||
|
||||
<div className="form-group col-xs-12">
|
||||
<label htmlFor="token">Token</label>
|
||||
<input className="form-control" id="token" type="text" ref={(r) => this.token = r} defaultValue={token || ''}></input>
|
||||
<span>Note: a value of <code>true</code> indicates the Alerta Token has been set</span>
|
||||
</div>
|
||||
|
||||
<div className="form-group col-xs-12">
|
||||
<label htmlFor="url">User</label>
|
||||
<input className="form-control" id="url" type="text" ref={(r) => this.url = r} defaultValue={url || ''}></input>
|
||||
</div>
|
||||
|
||||
<div className="form-group-submit col-xs-12 col-sm-6 col-sm-offset-3">
|
||||
<button className="btn btn-block btn-primary" type="submit">Save</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
|
|
@ -94,8 +94,10 @@ export const RuleMessage = React.createClass({
|
|||
/> : null
|
||||
}
|
||||
<div className="rule-section--item bottom alert-message--endpoint">
|
||||
<p>Send this Alert to:</p>
|
||||
<Dropdown className="size-256 dropdown-kapacitor" selected={selectedAlert || 'Choose an output'} items={alerts} onChoose={this.handleChooseAlert} />
|
||||
<div>
|
||||
<p>Send this Alert to:</p>
|
||||
<Dropdown className="dropdown-kapacitor size-136" selected={selectedAlert || 'Choose an output'} items={alerts} onChoose={this.handleChooseAlert} />
|
||||
</div>
|
||||
{this.renderInput(actions.updateAlertNodes, selectedAlert, rule)}
|
||||
</div>
|
||||
</div>
|
||||
|
@ -104,17 +106,27 @@ export const RuleMessage = React.createClass({
|
|||
},
|
||||
|
||||
renderInput(updateAlertNodes, alert, rule) {
|
||||
if (!DEFAULT_ALERTS.find((a) => a === alert)) {
|
||||
if (!Object.keys(DEFAULT_ALERT_PLACEHOLDERS).find((a) => a === alert)) {
|
||||
return null;
|
||||
}
|
||||
return (<input
|
||||
className="form-control col-xs-6"
|
||||
type="text"
|
||||
placeholder={DEFAULT_ALERT_PLACEHOLDERS[alert]}
|
||||
ref={(r) => this.selectedAlertProperty = r}
|
||||
onChange={() => updateAlertNodes(rule.id, alert, this.selectedAlertProperty.value)}
|
||||
value={ALERT_NODES_ACCESSORS[alert](rule)}
|
||||
/>);
|
||||
return (
|
||||
<form className="form-group col-xs-12" style={{marginTop: '8px'}}>
|
||||
<div>
|
||||
<label htmlFor="alert-input">{DEFAULT_ALERT_PLACEHOLDERS[alert]}</label>
|
||||
</div>
|
||||
<div>
|
||||
<input
|
||||
id="alert-input"
|
||||
className="form-control"
|
||||
type="text"
|
||||
placeholder={DEFAULT_ALERT_PLACEHOLDERS[alert]}
|
||||
ref={(r) => this.selectedAlertProperty = r}
|
||||
onChange={() => updateAlertNodes(rule.id, alert, this.selectedAlertProperty.value)}
|
||||
value={ALERT_NODES_ACCESSORS[alert](rule)}
|
||||
/>
|
||||
</div>
|
||||
</form>
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
|
|
|
@ -39,7 +39,7 @@ export const RULE_MESSAGE_TEMPLATES = {
|
|||
time: {label: "{{.Time}}", text: "The time of the point that triggered the event"},
|
||||
};
|
||||
|
||||
export const DEFAULT_ALERTS = ['http', 'tcp', 'exec', 'smtp', 'alerta'];
|
||||
export const DEFAULT_ALERTS = ['http', 'tcp', 'exec'];
|
||||
|
||||
export const DEFAULT_ALERT_PLACEHOLDERS = {
|
||||
http: 'URL',
|
||||
|
|
|
@ -1,25 +1,6 @@
|
|||
import {defaultRuleConfigs, DEFAULT_RULE_ID} from 'src/kapacitor/constants';
|
||||
import _ from 'lodash';
|
||||
|
||||
const alertaRegex = /(services)\('(.+?)'\)|(resource)\('(.+?)'\)|(event)\('(.+?)'\)|(environment)\('(.+?)'\)|(group)\('(.+?)'\)|(origin)\('(.+?)'\)|(token)\('(.+?)'\)/gi;
|
||||
|
||||
function parseAlerta(string, regex) {
|
||||
const properties = [];
|
||||
let match;
|
||||
|
||||
while (match = regex.exec(string)) { // eslint-disable-line no-cond-assign
|
||||
for (let m = 1; m < match.length; m += 2) {
|
||||
if (match[m]) {
|
||||
properties.push({
|
||||
name: match[m],
|
||||
args: match[m] === 'services' ? match[m + 1].split(' ') : [match[m + 1]],
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return properties;
|
||||
}
|
||||
import {parseAlerta} from 'src/shared/parsing/parseAlerta';
|
||||
|
||||
export default function rules(state = {}, action) {
|
||||
switch (action.type) {
|
||||
|
@ -125,7 +106,7 @@ export default function rules(state = {}, action) {
|
|||
{
|
||||
name: alertType,
|
||||
args: [],
|
||||
properties: parseAlerta(alertNodesText, alertaRegex),
|
||||
properties: parseAlerta(alertNodesText),
|
||||
},
|
||||
];
|
||||
break;
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
const alertaRegex = /(services)\('(.+?)'\)|(resource)\('(.+?)'\)|(event)\('(.+?)'\)|(environment)\('(.+?)'\)|(group)\('(.+?)'\)|(origin)\('(.+?)'\)|(token)\('(.+?)'\)/gi;
|
||||
|
||||
export function parseAlerta(string) {
|
||||
const properties = [];
|
||||
let match;
|
||||
|
||||
while (match = alertaRegex.exec(string)) { // eslint-disable-line no-cond-assign
|
||||
for (let m = 1; m < match.length; m += 2) {
|
||||
if (match[m]) {
|
||||
properties.push({
|
||||
name: match[m],
|
||||
args: match[m] === 'services' ? match[m + 1].split(' ') : [match[m + 1]],
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return properties;
|
||||
}
|
Loading…
Reference in New Issue