Skip to content

Commit 80efcd2

Browse files
Merge branch 'ServerCentral-json-results' into develop
2 parents d16e5d5 + d9803d8 commit 80efcd2

File tree

12 files changed

+134
-8
lines changed

12 files changed

+134
-8
lines changed

README.md

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,10 @@ You can use the following config options:
111111
"dataPath": { // The path to a folder that the server can use to store data and temporary files.
112112
"relative": true, // Whether to use a path relative to the `elastalertPath` folder.
113113
"path": "/server_data" // The path to the data folder.
114-
}
114+
},
115+
"es_host": "elastalert", // For getting metadata and field mappings, connect to this ES server
116+
"es_port": 9200, // Port for above
117+
"writeback_index": "elastalert_status" // Writeback index to examine for /metadata endpoint
115118
}
116119
```
117120

@@ -200,11 +203,25 @@ This server exposes the following REST API's:
200203
"days": "1"
201204
202205
// Whether to send real alerts
203-
"alert": false
206+
"alert": false,
207+
208+
// Return results in structured JSON
209+
"format": "json",
210+
211+
// Limit returned results to this amount
212+
"maxResults": 1000
204213
}
205214
}
206215
```
207216

217+
- **GET `/metadata/:type`**
218+
219+
Returns metadata from elasticsearch related to elasalert's state. `:type` should be one of: elastalert_status, elastalert, elastalert_error, or silence. See [docs about the elastalert metadata index](https://elastalert.readthedocs.io/en/latest/elastalert_status.html).
220+
221+
- **GET `/mapping/:index`**
222+
223+
Returns field mapping from elasticsearch for a given index.
224+
208225
- **[WIP] GET `/config`**
209226

210227
Gets the ElastAlert configuration from `config.yaml` in `elastalertPath` (from the config).

config/config.json

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,8 @@
1212
"templatesPath": {
1313
"relative": true,
1414
"path": "/rule_templates"
15-
}
16-
}
15+
},
16+
"es_host": "elastalert",
17+
"es_port": 9200,
18+
"writeback_index": "elastalert_status"
19+
}

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323
"babel-register": "^6.14.0",
2424
"body-parser": "^1.15.2",
2525
"bunyan": "^1.8.1",
26+
"cors": "^2.8.4",
27+
"elasticsearch": "^15.1.1",
2628
"express": "^4.14.0",
2729
"fs-extra": "^5.0.0",
2830
"joi": "^13.1.2",

src/common/config/schema.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@ import Joi from 'joi';
33

44
const schema = Joi.object().keys({
55
'appName': Joi.string().default('elastalert-server'),
6+
'es_host': Joi.string().default('elastalert'),
7+
'es_port': Joi.number().default(9200),
8+
'writeback_index': Joi.string().default('elastalert_status'),
69
'port': Joi.number().default(3030),
710
'elastalertPath': Joi.string().default('/opt/elastalert'),
811
'rulesPath': Joi.object().keys({

src/common/elasticsearch_client.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import elasticsearch from 'elasticsearch';
2+
import config from './config';
3+
4+
export function getClient() {
5+
var client = new elasticsearch.Client({
6+
hosts: [ `http://${config.get('es_host')}:${config.get('es_port')}`]
7+
});
8+
return client;
9+
}

src/controllers/test/index.js

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,15 @@ export default class TestController {
3333

3434
processOptions.push('-m', 'elastalert.test_rule', '--config', 'config.yaml', tempFilePath, '--days', options.days);
3535

36+
if (options.format === 'json') {
37+
processOptions.push('--formatted-output');
38+
}
39+
40+
if (options.maxResults > 0) {
41+
processOptions.push('--max-query-size');
42+
processOptions.push(options.maxResults);
43+
}
44+
3645
if (options.alert) {
3746
processOptions.push('--alert');
3847
}
@@ -61,7 +70,12 @@ export default class TestController {
6170

6271
testProcess.on('exit', function (statusCode) {
6372
if (statusCode === 0) {
64-
resolve(stdoutLines.join('\n'));
73+
if (options.format === 'json') {
74+
resolve(stdoutLines.join(''));
75+
}
76+
else {
77+
resolve(stdoutLines.join('\n'));
78+
}
6579
} else {
6680
reject(stderrLines.join('\n'));
6781
logger.error(stderrLines.join('\n'));

src/elastalert_server.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import ProcessController from './controllers/process';
99
import RulesController from './controllers/rules';
1010
import TemplatesController from './controllers/templates';
1111
import TestController from './controllers/test';
12+
import cors from 'cors';
1213

1314
let logger = new Logger('Server');
1415

@@ -58,6 +59,7 @@ export default class ElastalertServer {
5859
// Start the server when the config is loaded
5960
config.ready(function () {
6061
try {
62+
self._express.use(cors());
6163
self._express.use(bodyParser.json());
6264
self._express.use(bodyParser.urlencoded({ extended: true }));
6365
self._setupRouter();

src/handlers/mapping/get.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import { getClient } from '../../common/elasticsearch_client';
2+
3+
export default function metadataHandler(request, response) {
4+
/**
5+
* @type {ElastalertServer}
6+
*/
7+
8+
var client = getClient();
9+
10+
client.indices.getMapping({
11+
index: request.params.index
12+
}).then(function(resp) {
13+
response.send(resp);
14+
}, function(err) {
15+
response.send({
16+
error: err
17+
});
18+
});
19+
20+
}

src/handlers/metadata/get.js

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import config from '../../common/config';
2+
import { getClient } from '../../common/elasticsearch_client';
3+
4+
5+
function getQueryString(request) {
6+
if (request.params.type === 'elastalert_error') {
7+
return '*:*';
8+
}
9+
else {
10+
return `rule_name:${request.query.rule_name || '*'}`;
11+
}
12+
}
13+
14+
export default function metadataHandler(request, response) {
15+
/**
16+
* @type {ElastalertServer}
17+
*/
18+
var client = getClient();
19+
20+
client.search({
21+
index: config.get('writeback_index'),
22+
type: request.params.type,
23+
body: {
24+
from : request.query.from || 0,
25+
size : request.query.size || 100,
26+
query: {
27+
query_string: {
28+
query: getQueryString(request)
29+
}
30+
},
31+
sort: [{ '@timestamp': { order: 'desc' } }]
32+
}
33+
}).then(function(resp) {
34+
resp.hits.hits = resp.hits.hits.map(h => h._source);
35+
response.send(resp.hits);
36+
}, function(err) {
37+
response.send({
38+
error: err
39+
});
40+
});
41+
42+
}

src/handlers/templates/id/post.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@ export default function templatePostHandler(request, response) {
2626
});
2727
})
2828
.catch(function (error) {
29-
if (error.error === 'ruleNotFound') {
30-
server.templatesController.createRule(request.params.id, body)
29+
if (error.error === 'templateNotFound') {
30+
server.templatesController.createTemplate(request.params.id, body)
3131
.then(function () {
3232
logger.sendSuccessful();
3333
response.send({

0 commit comments

Comments
 (0)