diff --git a/x-pack/platform/plugins/shared/fleet/public/applications/fleet/sections/agent_policy/edit_package_policy_page/index.test.tsx b/x-pack/platform/plugins/shared/fleet/public/applications/fleet/sections/agent_policy/edit_package_policy_page/index.test.tsx index 8ddc2e80b0aa8..d4cac73ae049d 100644 --- a/x-pack/platform/plugins/shared/fleet/public/applications/fleet/sections/agent_policy/edit_package_policy_page/index.test.tsx +++ b/x-pack/platform/plugins/shared/fleet/public/applications/fleet/sections/agent_policy/edit_package_policy_page/index.test.tsx @@ -13,7 +13,6 @@ import { createFleetTestRendererMock } from '../../../../../mock'; import { useUIExtension, - sendGetAgentStatus, sendGetOneAgentPolicy, sendGetOnePackagePolicy, sendUpgradePackagePolicyDryRun, @@ -24,6 +23,7 @@ import { useGetAgentPolicies, useMultipleAgentPolicies, useGetPackagePolicies, + sendBulkGetAgentPoliciesForRq, } from '../../../hooks'; import { useGetOnePackagePolicy } from '../../../../integrations/hooks'; @@ -44,6 +44,7 @@ jest.mock('../../../hooks', () => { return { ...jest.requireActual('../../../hooks'), sendGetAgentStatus: jest.fn(), + sendBulkGetAgentPoliciesForRq: jest.fn(), sendUpdatePackagePolicy: jest.fn(), sendGetOnePackagePolicy: jest.fn(), sendGetOneAgentPolicy: jest.fn(), @@ -261,7 +262,7 @@ describe('edit package policy page', () => { (sendUpdatePackagePolicy as MockFn).mockResolvedValue({}); (useStartServices().application.navigateToUrl as MockFn).mockReset(); (useStartServices().notifications.toasts.addError as MockFn).mockReset(); - (sendGetAgentStatus as MockFn).mockResolvedValue({ data: { results: { total: 0 } } }); + (sendBulkGetAgentPoliciesForRq as MockFn).mockResolvedValue({ data: [] }); (sendBulkGetAgentPolicies as MockFn).mockResolvedValue({ data: { items: [{ id: 'agent-policy-1', name: 'Agent policy 1' }] }, }); @@ -477,7 +478,7 @@ describe('edit package policy page', () => { }); it('should not show confirmation modal if package is on agentless policy', async () => { - (sendGetAgentStatus as MockFn).mockResolvedValue({ data: { results: { total: 1 } } }); + (sendBulkGetAgentPoliciesForRq as MockFn).mockResolvedValue({ data: [{ agents: 1 }] }); (useGetOnePackagePolicy as MockFn).mockReturnValue({ data: { item: mockPackagePolicyAgentless, @@ -529,8 +530,8 @@ describe('edit package policy page', () => { beforeEach(() => { useMultipleAgentPoliciesMock.mockReturnValue({ canUseMultipleAgentPolicies: true }); - (sendGetAgentStatus as jest.MockedFunction).mockResolvedValue({ - data: { results: { total: 0 } }, + (sendBulkGetAgentPoliciesForRq as jest.MockedFunction).mockResolvedValue({ + data: [], }); jest.clearAllMocks(); }); @@ -569,7 +570,6 @@ describe('edit package policy page', () => { policy_ids: ['agent-policy-1', 'agent-policy-2'], }) ); - expect(sendGetAgentStatus).toHaveBeenCalledTimes(1); }); }); diff --git a/x-pack/platform/plugins/shared/fleet/public/applications/fleet/sections/agent_policy/edit_package_policy_page/index.tsx b/x-pack/platform/plugins/shared/fleet/public/applications/fleet/sections/agent_policy/edit_package_policy_page/index.tsx index 9522d02756887..946006cec9fa5 100644 --- a/x-pack/platform/plugins/shared/fleet/public/applications/fleet/sections/agent_policy/edit_package_policy_page/index.tsx +++ b/x-pack/platform/plugins/shared/fleet/public/applications/fleet/sections/agent_policy/edit_package_policy_page/index.tsx @@ -25,8 +25,8 @@ import { useStartServices, useConfig, useUIExtension, - sendGetAgentStatus, useAuthz, + sendBulkGetAgentPoliciesForRq, } from '../../../hooks'; import { useBreadcrumbs as useIntegrationsBreadcrumbs, @@ -159,24 +159,74 @@ export const EditPackagePolicyForm = memo<{ const [hasAgentPolicyError, setHasAgentPolicyError] = useState(false); + const agentPoliciesToAdd = useMemo( + () => [ + ...agentPolicies + .filter( + (policy) => + !existingAgentPolicies.find((existingPolicy) => existingPolicy.id === policy.id) + ) + .map((policy) => policy.name), + ...(newAgentPolicyName ? [newAgentPolicyName] : []), + ], + [agentPolicies, existingAgentPolicies, newAgentPolicyName] + ); + const agentPoliciesToRemove = useMemo( + () => + existingAgentPolicies.filter( + (existingPolicy) => !agentPolicies.find((policy) => policy.id === existingPolicy.id) + ), + [agentPolicies, existingAgentPolicies] + ); + + const agentPoliciesToRemoveIds = useMemo( + () => agentPoliciesToRemove.map((policy) => policy.id), + [agentPoliciesToRemove] + ); + + const agentPoliciesToRemoveName = useMemo( + () => agentPoliciesToRemove.map((policy) => policy.name), + [agentPoliciesToRemove] + ); + // Retrieve agent count const [agentCount, setAgentCount] = useState(0); + const [impactedAgentCount, setImpactedAgentCount] = useState(0); useEffect(() => { const getAgentCount = async () => { - let count = 0; - for (const id of packagePolicy.policy_ids) { - const { data } = await sendGetAgentStatus({ policyId: id }); - if (data?.results.active) { - count += data.results.active; + const policiesToFetchIds = [...packagePolicy.policy_ids, ...agentPoliciesToRemoveIds]; + try { + const bulkGetAgentPoliciesResponse = await sendBulkGetAgentPoliciesForRq( + policiesToFetchIds, + { + ignoreMissing: true, + } + ); + + let count = 0; + let impactedCount = 0; + for (const item of bulkGetAgentPoliciesResponse.items) { + if (packagePolicy.policy_ids.includes(item.id)) { + count += item.agents ?? 0; + } + + impactedCount += item.agents ?? 0; } + setAgentCount(count); + setImpactedAgentCount(impactedCount); + } catch (err) { + setAgentCount(0); + setImpactedAgentCount(0); } - setAgentCount(count); }; - if (isFleetEnabled && packagePolicy.policy_ids.length > 0) { + if ( + isFleetEnabled && + (packagePolicy.policy_ids.length > 0 || agentPoliciesToRemoveIds.length > 0) + ) { getAgentCount(); } - }, [packagePolicy.policy_ids, isFleetEnabled]); + }, [packagePolicy.policy_ids, agentPoliciesToRemoveIds, isFleetEnabled]); const handleExtensionViewOnChange = useCallback< PackagePolicyEditExtensionComponentProps['onChange'] @@ -225,28 +275,6 @@ export const EditPackagePolicyForm = memo<{ } }, [existingAgentPolicies, isFirstLoad]); - const agentPoliciesToAdd = useMemo( - () => [ - ...agentPolicies - .filter( - (policy) => - !existingAgentPolicies.find((existingPolicy) => existingPolicy.id === policy.id) - ) - .map((policy) => policy.name), - ...(newAgentPolicyName ? [newAgentPolicyName] : []), - ], - [agentPolicies, existingAgentPolicies, newAgentPolicyName] - ); - const agentPoliciesToRemove = useMemo( - () => - existingAgentPolicies - .filter( - (existingPolicy) => !agentPolicies.find((policy) => policy.id === existingPolicy.id) - ) - .map((policy) => policy.name), - [agentPolicies, existingAgentPolicies] - ); - const onSubmit = async () => { if (formState === 'VALID' && hasErrors) { setFormState('INVALID'); @@ -518,12 +546,12 @@ export const EditPackagePolicyForm = memo<{ /> {formState === 'CONFIRM' && ( setFormState('VALID')} agentPoliciesToAdd={agentPoliciesToAdd} - agentPoliciesToRemove={agentPoliciesToRemove} + agentPoliciesToRemove={agentPoliciesToRemoveName} /> )} {packageInfo && isRootPrivilegesRequired(packageInfo) ? ( diff --git a/x-pack/platform/plugins/shared/fleet/public/hooks/use_request/agent_policy.ts b/x-pack/platform/plugins/shared/fleet/public/hooks/use_request/agent_policy.ts index 3bf3468370685..5d699a841326e 100644 --- a/x-pack/platform/plugins/shared/fleet/public/hooks/use_request/agent_policy.ts +++ b/x-pack/platform/plugins/shared/fleet/public/hooks/use_request/agent_policy.ts @@ -85,6 +85,18 @@ export const sendBulkGetAgentPolicies = ( }); }; +export const sendBulkGetAgentPoliciesForRq = ( + ids: string[], + options?: { full?: boolean; ignoreMissing?: boolean } +) => { + return sendRequestForRq({ + path: agentPolicyRouteService.getBulkGetPath(), + method: 'post', + body: JSON.stringify({ ids, full: options?.full, ignoreMissing: options?.ignoreMissing }), + version: API_VERSIONS.public.v1, + }); +}; + export const sendGetAgentPolicies = (query?: GetAgentPoliciesRequest['query']) => { return sendRequest({ path: agentPolicyRouteService.getListPath(),