From f242fb5d2773806cf5d9b2bcdef135851c89eaff Mon Sep 17 00:00:00 2001 From: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Date: Tue, 23 Mar 2021 13:31:55 -0400 Subject: [PATCH] [Fleet] Fix agent status count (#95099) (#95182) Co-authored-by: Nicolas Chaulet --- .../fleet/server/services/agents/crud.ts | 5 +- .../fleet/server/services/agents/helpers.ts | 2 + .../apis/agents/status.ts | 86 +++++++++++++++++++ .../test/fleet_api_integration/apis/index.js | 1 + 4 files changed, 92 insertions(+), 2 deletions(-) create mode 100644 x-pack/test/fleet_api_integration/apis/agents/status.ts diff --git a/x-pack/plugins/fleet/server/services/agents/crud.ts b/x-pack/plugins/fleet/server/services/agents/crud.ts index 52a6b98bd0c41..22e9f559c56b8 100644 --- a/x-pack/plugins/fleet/server/services/agents/crud.ts +++ b/x-pack/plugins/fleet/server/services/agents/crud.ts @@ -9,6 +9,7 @@ import Boom from '@hapi/boom'; import type { SearchResponse, MGetResponse, GetResponse } from 'elasticsearch'; import type { SavedObjectsClientContract, ElasticsearchClient } from 'src/core/server'; +import type { ESSearchResponse } from '../../../../../../typings/elasticsearch'; import type { AgentSOAttributes, Agent, ListWithKuery } from '../../types'; import { appContextService, agentPolicyService } from '../../services'; import type { FleetServerAgent } from '../../../common'; @@ -118,7 +119,7 @@ export async function getAgentsByKuery( const kueryNode = _joinFilters(filters); const body = kueryNode ? { query: esKuery.toElasticsearchQuery(kueryNode) } : {}; - const res = await esClient.search>({ + const res = await esClient.search>({ index: AGENTS_INDEX, from: (page - 1) * perPage, size: perPage, @@ -138,7 +139,7 @@ export async function getAgentsByKuery( return { agents, - total: agents.length, + total: res.body.hits.total.value, page, perPage, }; diff --git a/x-pack/plugins/fleet/server/services/agents/helpers.ts b/x-pack/plugins/fleet/server/services/agents/helpers.ts index bcc065badcd50..89f37a01a6b00 100644 --- a/x-pack/plugins/fleet/server/services/agents/helpers.ts +++ b/x-pack/plugins/fleet/server/services/agents/helpers.ts @@ -7,10 +7,12 @@ import type { GetResponse, SearchResponse } from 'elasticsearch'; +import type { ESSearchHit } from '../../../../../../typings/elasticsearch'; import type { Agent, AgentSOAttributes, FleetServerAgent } from '../../types'; type FleetServerAgentESResponse = | GetResponse + | ESSearchHit | SearchResponse['hits']['hits'][0]; export function searchHitToAgent(hit: FleetServerAgentESResponse): Agent { diff --git a/x-pack/test/fleet_api_integration/apis/agents/status.ts b/x-pack/test/fleet_api_integration/apis/agents/status.ts new file mode 100644 index 0000000000000..3245b9a459fb1 --- /dev/null +++ b/x-pack/test/fleet_api_integration/apis/agents/status.ts @@ -0,0 +1,86 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import expect from '@kbn/expect'; + +import { FtrProviderContext } from '../../../api_integration/ftr_provider_context'; +import { AGENTS_INDEX } from '../../../../plugins/fleet/common'; + +export default function ({ getService }: FtrProviderContext) { + const es = getService('es'); + const esArchiver = getService('esArchiver'); + const supertest = getService('supertest'); + + describe('fleet_agents_status', () => { + before(async () => { + await esArchiver.loadIfNeeded('fleet/agents'); + // 2 agents online + await es.update({ + id: 'agent1', + refresh: 'wait_for', + index: AGENTS_INDEX, + body: { + doc: { + last_checkin: new Date().toISOString(), + }, + }, + }); + await es.update({ + id: 'agent2', + refresh: 'wait_for', + index: AGENTS_INDEX, + body: { + doc: { + last_checkin: new Date().toISOString(), + }, + }, + }); + // 1 agents offline + await es.update({ + id: 'agent3', + refresh: 'wait_for', + index: AGENTS_INDEX, + body: { + doc: { + last_checkin: new Date(Date.now() - 1000 * 60 * 60 * 60 * 10).toISOString(), + }, + }, + }); + // 1 agent upgrading + await es.update({ + id: 'agent4', + refresh: 'wait_for', + index: AGENTS_INDEX, + body: { + doc: { + last_checkin: new Date().toISOString(), + upgrade_started_at: new Date().toISOString(), + }, + }, + }); + }); + after(async () => { + await esArchiver.unload('fleet/agents'); + }); + + it('should return the status of agents', async () => { + const { body: apiResponse } = await supertest.get(`/api/fleet/agent-status`).expect(200); + + expect(apiResponse).to.eql({ + results: { + events: 0, + total: 4, + online: 2, + error: 0, + offline: 1, + updating: 1, + other: 1, + }, + }); + }); + }); +} diff --git a/x-pack/test/fleet_api_integration/apis/index.js b/x-pack/test/fleet_api_integration/apis/index.js index 948985c52bd1b..3d7ee3686b575 100644 --- a/x-pack/test/fleet_api_integration/apis/index.js +++ b/x-pack/test/fleet_api_integration/apis/index.js @@ -25,6 +25,7 @@ export default function ({ loadTestFile }) { loadTestFile(require.resolve('./agents/actions')); loadTestFile(require.resolve('./agents/upgrade')); loadTestFile(require.resolve('./agents/reassign')); + loadTestFile(require.resolve('./agents/status')); // Enrollment API keys loadTestFile(require.resolve('./enrollment_api_keys/crud'));