Skip to content

Commit

Permalink
[Beats Management] APIs: List beats (elastic#19086)
Browse files Browse the repository at this point in the history
* WIP checkin

* Add API integration test

* Converting to Jest test

* WIP checkin

* Fixing API for default case + adding test for it

* Fixing copy pasta typos

* Fixing variable name

* Using a single index

* Implementing GET /api/beats/agents API

* Updating mapping
  • Loading branch information
ycombinator authored and justinkambic committed Jul 23, 2018
1 parent 7aad032 commit 6e5e0bd
Show file tree
Hide file tree
Showing 6 changed files with 178 additions and 0 deletions.
2 changes: 2 additions & 0 deletions x-pack/plugins/beats/server/routes/api/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@

import { registerCreateEnrollmentTokensRoute } from './register_create_enrollment_tokens_route';
import { registerEnrollBeatRoute } from './register_enroll_beat_route';
import { registerListBeatsRoute } from './register_list_beats_route';

export function registerApiRoutes(server) {
registerCreateEnrollmentTokensRoute(server);
registerEnrollBeatRoute(server);
registerListBeatsRoute(server);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

import {
get,
omit
} from "lodash";
import { INDEX_NAMES } from "../../../common/constants";
import { callWithRequestFactory } from '../../lib/client';
import { wrapEsError } from "../../lib/error_wrappers";

async function getBeats(callWithRequest) {
const params = {
index: INDEX_NAMES.BEATS,
type: '_doc',
q: 'type:beat'
};

const response = await callWithRequest('search', params);
return get(response, 'hits.hits', []);
}

// TODO: add license check pre-hook
export function registerListBeatsRoute(server) {
server.route({
method: 'GET',
path: '/api/beats/agents',
handler: async (request, reply) => {
const callWithRequest = callWithRequestFactory(server, request);
let beats;

try {
beats = await getBeats(callWithRequest);
} catch (err) {
return reply(wrapEsError(err));
}

const response = {
beats: beats.map(beat => omit(beat._source.beat, ['access_token']))
};
reply(response);
}
});
}
1 change: 1 addition & 0 deletions x-pack/test/api_integration/apis/beats/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,6 @@ export default function ({ getService, loadTestFile }) {

loadTestFile(require.resolve('./create_enrollment_tokens'));
loadTestFile(require.resolve('./enroll_beat'));
loadTestFile(require.resolve('./list_beats'));
});
}
46 changes: 46 additions & 0 deletions x-pack/test/api_integration/apis/beats/list_beats.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

import expect from 'expect.js';

export default function ({ getService }) {
const supertest = getService('supertest');
const esArchiver = getService('esArchiver');

describe('list_beats', () => {
const archive = 'beats/list';

beforeEach('load beats archive', () => esArchiver.load(archive));
afterEach('unload beats archive', () => esArchiver.unload(archive));

it('should return all beats', async () => {
const { body: apiResponse } = await supertest
.get(
'/api/beats/agents'
)
.expect(200);

const beatsFromApi = apiResponse.beats;

expect(beatsFromApi.length).to.be(3);
expect(beatsFromApi.filter(beat => beat.hasOwnProperty('verified_on')).length).to.be(1);
expect(beatsFromApi.find(beat => beat.hasOwnProperty('verified_on')).id).to.be('foo');
});

it('should not return access tokens', async () => {
const { body: apiResponse } = await supertest
.get(
'/api/beats/agents'
)
.expect(200);

const beatsFromApi = apiResponse.beats;

expect(beatsFromApi.length).to.be(3);
expect(beatsFromApi.filter(beat => beat.hasOwnProperty('access_token')).length).to.be(0);
});
});
}
Binary file not shown.
82 changes: 82 additions & 0 deletions x-pack/test/functional/es_archives/beats/list/mappings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
{
"type": "index",
"value": {
"index": ".management-beats",
"settings": {
"index": {
"codec": "best_compression",
"number_of_shards": "1",
"auto_expand_replicas": "0-1",
"number_of_replicas": "0"
}
},
"mappings": {
"_doc": {
"dynamic": "strict",
"properties": {
"type": {
"type": "keyword"
},
"enrollment_token": {
"properties": {
"token": {
"type": "keyword"
},
"expires_on": {
"type": "date"
}
}
},
"configuration_block": {
"properties": {
"tag": {
"type": "keyword"
},
"type": {
"type": "keyword"
},
"block_yml": {
"type": "text"
}
}
},
"beat": {
"properties": {
"id": {
"type": "keyword"
},
"access_token": {
"type": "keyword"
},
"verified_on": {
"type": "date"
},
"type": {
"type": "keyword"
},
"host_ip": {
"type": "ip"
},
"host_name": {
"type": "keyword"
},
"ephemeral_id": {
"type": "keyword"
},
"local_configuration_yml": {
"type": "text"
},
"central_configuration_yml": {
"type": "text"
},
"metadata": {
"dynamic": "true",
"type": "object"
}
}
}
}
}
}
}
}

0 comments on commit 6e5e0bd

Please sign in to comment.