Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Fleet] Add agent incoming data endpoint and presentational component #127177

Merged
merged 10 commits into from
Mar 15, 2022
1 change: 1 addition & 0 deletions x-pack/plugins/fleet/common/constants/routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ export const AGENT_API_ROUTES = {
REASSIGN_PATTERN: `${API_ROOT}/agents/{agentId}/reassign`,
BULK_REASSIGN_PATTERN: `${API_ROOT}/agents/bulk_reassign`,
STATUS_PATTERN: `${API_ROOT}/agent_status`,
DATA_PATTERN: `${API_ROOT}/agent_status/data`,
// deprecated since 8.0
STATUS_PATTERN_DEPRECATED: `${API_ROOT}/agent-status`,
UPGRADE_PATTERN: `${API_ROOT}/agents/{agentId}/upgrade`,
Expand Down
45 changes: 45 additions & 0 deletions x-pack/plugins/fleet/common/openapi/bundled.json
Original file line number Diff line number Diff line change
Expand Up @@ -1119,6 +1119,51 @@
]
}
},
"/agent_status/data": {
"get": {
"summary": "Agents - Get incoming data",
"tags": [],
"responses": {
"200": {
"description": "OK",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"items": {
"type": "array",
"items": {
"type": "object",
"additionalProperties": {
"type": "object",
"properties": {
"data": {
"type": "boolean"
}
}
}
}
}
}
}
}
}
}
},
"operationId": "get-agent-data",
"parameters": [
{
"schema": {
"type": "array"
},
"name": "agentsIds",
"in": "query",
"required": true
}
]
}
},
"/agents": {
"get": {
"summary": "Agents - List",
Expand Down
28 changes: 28 additions & 0 deletions x-pack/plugins/fleet/common/openapi/bundled.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -686,6 +686,34 @@ paths:
name: kuery
in: query
required: false
/agent_status/data:
get:
summary: Agents - Get incoming data
tags: []
responses:
'200':
description: OK
content:
application/json:
schema:
type: object
properties:
items:
type: array
items:
type: object
additionalProperties:
type: object
properties:
data:
type: boolean
operationId: get-agent-data
parameters:
- schema:
type: array
name: agentsId
in: query
required: true
/agents:
get:
summary: Agents - List
Expand Down
2 changes: 2 additions & 0 deletions x-pack/plugins/fleet/common/openapi/entrypoint.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ paths:
$ref: paths/agent_status_deprecated.yaml
/agent_status:
$ref: paths/agent_status.yaml
/agent_status/data:
$ref: paths/agent_status@data.yaml
/agents:
$ref: paths/agents.yaml
/agents/bulk_upgrade:
Expand Down
27 changes: 27 additions & 0 deletions x-pack/plugins/fleet/common/openapi/paths/agent_status@data.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
get:
summary: Agents - Get incoming data
tags: []
responses:
'200':
description: OK
content:
application/json:
schema:
type: object
properties:
items:
type: array
items:
type: object
additionalProperties:
type: object
properties:
data:
type: boolean
operationId: get-agent-data
parameters:
- schema:
type: array
name: agentsId
in: query
required: true
1 change: 1 addition & 0 deletions x-pack/plugins/fleet/common/services/routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,7 @@ export const agentRouteService = {
getBulkUpgradePath: () => AGENT_API_ROUTES.BULK_UPGRADE_PATTERN,
getListPath: () => AGENT_API_ROUTES.LIST_PATTERN,
getStatusPath: () => AGENT_API_ROUTES.STATUS_PATTERN,
getIncomingDataPath: () => AGENT_API_ROUTES.DATA_PATTERN,
getCreateActionPath: (agentId: string) =>
AGENT_API_ROUTES.ACTIONS_PATTERN.replace('{agentId}', agentId),
};
Expand Down
13 changes: 13 additions & 0 deletions x-pack/plugins/fleet/common/types/rest_spec/agent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -161,3 +161,16 @@ export interface GetAgentStatusResponse {
updating: number;
};
}

export interface GetAgentIncomingDataRequest {
query: {
agentsIds: string[];
};
}

export interface IncomingDataList {
[key: string]: { data: boolean };
}
export interface GetAgentIncomingDataResponse {
items: IncomingDataList[];
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/*
* 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 React, { useEffect, useState } from 'react';
import { EuiCallOut, EuiText, EuiSpacer } from '@elastic/eui';
import { i18n } from '@kbn/i18n';

import type { IncomingDataList } from '../../../public/applications/fleet/types';
import { sendGetAgentIncomingData } from '../../hooks';
interface Props {
agentsIds: string[];
}

export const ConfirmIncomingData: React.FunctionComponent<Props> = ({ agentsIds }) => {
const [isLoading, setIsLoading] = useState<boolean>(true);
const [incomingData, setIncomingData] = useState<IncomingDataList[]>([]);

useEffect(() => {
const getIncomingData = async () => {
const { data } = await sendGetAgentIncomingData({ agentsIds });
if (data?.items) {
setIncomingData(data?.items);
setIsLoading(false);
}
};
if (agentsIds) {
getIncomingData();
}
}, [agentsIds]);

const enrolledAgents = incomingData.length;
const agentsWithData = incomingData.reduce((acc, curr) => {
const agentData = Object.values(curr)[0];
return !!agentData.data ? acc + 1 : acc;
}, 0);

if (isLoading) {
return (
<EuiText size="s">
{i18n.translate('xpack.fleet.confirmIncomingData.loading', {
defaultMessage:
'It may take a few minutes for data to arrive in Elasticsearch. If the system is not generating data, it may help to generate some to ensure data is being collected correctly. If you’re having trouble, see our troubleshooting guide. You may close this dialog and check later by viewing our integration assets.',
})}
</EuiText>
);
}

return (
<>
<EuiCallOut
data-test-subj="IncomingDataConfirmedCallOut"
title={i18n.translate('xpack.fleet.confirmIncomingData.title', {
defaultMessage:
'Incoming data received from {agentsWithData} of {enrolledAgents} recently enrolled { enrolledAgents, plural, one {agent} other {agents}}.',
values: {
agentsWithData,
enrolledAgents,
},
})}
color="success"
iconType="check"
/>
<EuiSpacer size="m" />
<EuiText size="s">
{i18n.translate('xpack.fleet.confirmIncomingData.subtitle', {
defaultMessage: 'Your agent is enrolled successfully and your data is received.',
})}
</EuiText>
</>
);
};
9 changes: 9 additions & 0 deletions x-pack/plugins/fleet/public/hooks/use_request/agents.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ import type {
GetAgentsResponse,
GetAgentStatusRequest,
GetAgentStatusResponse,
GetAgentIncomingDataRequest,
GetAgentIncomingDataResponse,
PostAgentUpgradeRequest,
PostBulkAgentUpgradeRequest,
PostAgentUpgradeResponse,
Expand Down Expand Up @@ -68,6 +70,13 @@ export function useGetAgentStatus(query: GetAgentStatusRequest['query'], options
...options,
});
}
export function sendGetAgentIncomingData(query: GetAgentIncomingDataRequest['query']) {
return sendRequest<GetAgentIncomingDataResponse>({
method: 'get',
path: agentRouteService.getIncomingDataPath(),
query,
});
}

export function sendGetAgentStatus(
query: GetAgentStatusRequest['query'],
Expand Down
3 changes: 3 additions & 0 deletions x-pack/plugins/fleet/public/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,9 @@ export type {
PostBulkAgentUpgradeResponse,
GetAgentStatusRequest,
GetAgentStatusResponse,
GetAgentIncomingDataRequest,
IncomingDataList,
GetAgentIncomingDataResponse,
PutAgentReassignRequest,
PutAgentReassignResponse,
PostBulkAgentReassignRequest,
Expand Down
27 changes: 27 additions & 0 deletions x-pack/plugins/fleet/server/routes/agent/handlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import type {
UpdateAgentRequestSchema,
DeleteAgentRequestSchema,
GetAgentStatusRequestSchema,
GetAgentDataRequestSchema,
PutAgentReassignRequestSchema,
PostBulkAgentReassignRequestSchema,
} from '../../types';
Expand Down Expand Up @@ -218,3 +219,29 @@ export const getAgentStatusForAgentPolicyHandler: RequestHandler<
return defaultIngestErrorHandler({ error, response });
}
};

export const getAgentDataHandler: RequestHandler<
undefined,
TypeOf<typeof GetAgentDataRequestSchema.query>
> = async (context, request, response) => {
const esClient = context.core.elasticsearch.client.asCurrentUser;
try {
let items;

if (isStringArray(request.query.agentsIds)) {
items = await AgentService.getIncomingDataByAgentsId(esClient, request.query.agentsIds);
} else {
items = await AgentService.getIncomingDataByAgentsId(esClient, [request.query.agentsIds]);
}

const body = { items };

return response.ok({ body });
} catch (error) {
return defaultIngestErrorHandler({ error, response });
}
};

function isStringArray(arr: unknown | string[]): arr is string[] {
return Array.isArray(arr) && arr.every((p) => typeof p === 'string');
}
13 changes: 13 additions & 0 deletions x-pack/plugins/fleet/server/routes/agent/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
PostAgentUnenrollRequestSchema,
PostBulkAgentUnenrollRequestSchema,
GetAgentStatusRequestSchema,
GetAgentDataRequestSchema,
PostNewAgentActionRequestSchema,
PutAgentReassignRequestSchema,
PostBulkAgentReassignRequestSchema,
Expand All @@ -32,6 +33,7 @@ import {
getAgentStatusForAgentPolicyHandler,
putAgentsReassignHandler,
postBulkAgentsReassignHandler,
getAgentDataHandler,
} from './handlers';
import { postNewAgentActionHandlerBuilder } from './actions_handlers';
import { postAgentUnenrollHandler, postBulkAgentsUnenrollHandler } from './unenroll_handler';
Expand Down Expand Up @@ -141,6 +143,17 @@ export const registerAPIRoutes = (router: FleetAuthzRouter, config: FleetConfigT
},
getAgentStatusForAgentPolicyHandler
);
// Agent data
router.get(
{
path: AGENT_API_ROUTES.DATA_PATTERN,
validate: GetAgentDataRequestSchema,
fleetAuthz: {
fleet: { all: true },
},
},
getAgentDataHandler
);

// upgrade agent
router.post(
Expand Down
Loading