Skip to content

Commit

Permalink
[EDR Workflows] Fix agent count for single agent policies (#194294)
Browse files Browse the repository at this point in the history
https://github.com/user-attachments/assets/2b64c1e0-0e6d-4ef5-952d-e4364b4403c4



The PR #193705 introduced an issue when counting active agents for
integration policies with only one agent policy assigned. In such cases,
`query.policyIds` was treated as a single string instead of an array of
strings (as expected with multiple agent policy ids like
`/?policyIds=x&policyIds=y`). This PR resolves the issue by ensuring
consistent handling of policyIds, regardless of the number of associated
agent policies.
  • Loading branch information
szwarckonrad authored Sep 27, 2024
1 parent 878ba13 commit 847285b
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 14 deletions.
64 changes: 55 additions & 9 deletions x-pack/plugins/fleet/server/routes/agent/handlers.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@

import { coreMock, httpServerMock } from '@kbn/core/server/mocks';

import { getAvailableVersionsHandler } from './handlers';
import { getAgentStatusForAgentPolicy } from '../../services/agents/status';

import { getAgentStatusForAgentPolicyHandler, getAvailableVersionsHandler } from './handlers';

jest.mock('../../services/agents/versions', () => {
return {
Expand All @@ -24,16 +26,60 @@ jest.mock('../../services/app_context', () => {
};
});

describe('getAvailableVersionsHandler', () => {
it('should return the value from getAvailableVersions', async () => {
const ctx = coreMock.createCustomRequestHandlerContext(coreMock.createRequestHandlerContext());
const response = httpServerMock.createResponseFactory();
jest.mock('../../services/agents/status', () => ({
getAgentStatusForAgentPolicy: jest.fn(),
}));

describe('Handlers', () => {
describe('getAgentStatusForAgentPolicyHandler', () => {
it.each([
{ requested: 'policy-id-1', called: ['policy-id-1'] },
{ requested: ['policy-id-2'], called: ['policy-id-2'] },
{ requested: ['policy-id-3', 'policy-id-4'], called: ['policy-id-3', 'policy-id-4'] },
...[undefined, '', []].map((requested) => ({ requested, called: undefined })),
])('calls getAgentStatusForAgentPolicy with correct parameters', async (item) => {
const request = {
query: {
policyId: 'policy-id',
kuery: 'kuery',
policyIds: item.requested,
},
};
const response = httpServerMock.createResponseFactory();

await getAgentStatusForAgentPolicyHandler(
{
core: coreMock.createRequestHandlerContext(),
fleet: { internalSoClient: {} },
} as any,
request as any,
response
);

expect(getAgentStatusForAgentPolicy).toHaveBeenCalledWith(
expect.anything(),
expect.anything(),
'policy-id',
'kuery',
undefined,
item.called
);
});
});

describe('getAvailableVersionsHandler', () => {
it('should return the value from getAvailableVersions', async () => {
const ctx = coreMock.createCustomRequestHandlerContext(
coreMock.createRequestHandlerContext()
);
const response = httpServerMock.createResponseFactory();

await getAvailableVersionsHandler(ctx, httpServerMock.createKibanaRequest(), response);
await getAvailableVersionsHandler(ctx, httpServerMock.createKibanaRequest(), response);

expect(response.ok).toBeCalled();
expect(response.ok.mock.calls[0][0]?.body).toEqual({
items: ['8.1.0', '8.0.0', '7.17.0'],
expect(response.ok).toBeCalled();
expect(response.ok.mock.calls[0][0]?.body).toEqual({
items: ['8.1.0', '8.0.0', '7.17.0'],
});
});
});
});
11 changes: 10 additions & 1 deletion x-pack/plugins/fleet/server/routes/agent/handlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -323,13 +323,22 @@ export const getAgentStatusForAgentPolicyHandler: FleetRequestHandler<
const [coreContext, fleetContext] = await Promise.all([context.core, context.fleet]);
const esClient = coreContext.elasticsearch.client.asInternalUser;
const soClient = fleetContext.internalSoClient;

const parsePolicyIds = (policyIds: string | string[] | undefined): string[] | undefined => {
if (!policyIds || !policyIds.length) {
return undefined;
}

return Array.isArray(policyIds) ? policyIds : [policyIds];
};

const results = await getAgentStatusForAgentPolicy(
esClient,
soClient,
request.query.policyId,
request.query.kuery,
coreContext.savedObjects.client.getCurrentNamespace(),
request.query.policyIds
parsePolicyIds(request.query.policyIds)
);

const body: GetAgentStatusResponse = { results };
Expand Down
2 changes: 1 addition & 1 deletion x-pack/plugins/fleet/server/types/rest_spec/agent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,7 @@ export const PostBulkUpdateAgentTagsRequestSchema = {
export const GetAgentStatusRequestSchema = {
query: schema.object({
policyId: schema.maybe(schema.string()),
policyIds: schema.maybe(schema.arrayOf(schema.string())),
policyIds: schema.maybe(schema.oneOf([schema.arrayOf(schema.string()), schema.string()])),
kuery: schema.maybe(
schema.string({
validate: (value: string) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ export const policySettingsMiddlewareRunner: MiddlewareRunner = async (

// Agent summary is secondary data, so its ok for it to come after the details
// page is populated with the main content
if (policyItem.policy_id) {
if (policyItem.policy_ids?.length) {
const { results } = await sendGetFleetAgentStatusForPolicy(http, policyItem.policy_ids);
dispatch({
type: 'serverReturnedPolicyDetailsAgentSummaryData',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,15 +83,15 @@ export const sendPutPackagePolicy = (
};

/**
* Get a status summary for all Agents that are currently assigned to a given agent policy
* Get a status summary for all Agents that are currently assigned to a given agent policies
*
* @param http
* @param policyIds
* @param options
*/
export const sendGetFleetAgentStatusForPolicy = (
http: HttpStart,
/** the Agent (fleet) policy id */
/** the Agent (fleet) policy ids */
policyIds: string[],
options: Exclude<HttpFetchOptions, 'query'> = {}
): Promise<GetAgentStatusResponse> => {
Expand Down

0 comments on commit 847285b

Please sign in to comment.