Skip to content

Commit

Permalink
[9.0] [Fleet] Include removed agent policies agent count in confirm m…
Browse files Browse the repository at this point in the history
…odal multiple integration policies (#209137) (#209166)

# Backport

This will backport the following commits from `main` to `9.0`:
- [[Fleet] Include removed agent policies agent count in confirm modal
multiple integration policies
(#209137)](#209137)

<!--- Backport version: 9.4.3 -->

### Questions ?
Please refer to the [Backport tool
documentation](https://github.com/sqren/backport)

<!--BACKPORT [{"author":{"name":"Nicolas
Chaulet","email":"[email protected]"},"sourceCommit":{"committedDate":"2025-01-31T19:37:48Z","message":"[Fleet]
Include removed agent policies agent count in confirm modal multiple
integration policies
(#209137)","sha":"ef77adf686495b0f1fd3517b28c29e786bee99f3","branchLabelMapping":{"^v9.1.0$":"main","^v8.19.0$":"8.x","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["release_note:skip","Team:Fleet","backport:prev-minor","v9.1.0"],"title":"[Fleet]
Include removed agent policies agent count in confirm modal multiple
integration
policies","number":209137,"url":"https://github.com/elastic/kibana/pull/209137","mergeCommit":{"message":"[Fleet]
Include removed agent policies agent count in confirm modal multiple
integration policies
(#209137)","sha":"ef77adf686495b0f1fd3517b28c29e786bee99f3"}},"sourceBranch":"main","suggestedTargetBranches":[],"targetPullRequestStates":[{"branch":"main","label":"v9.1.0","branchLabelMappingKey":"^v9.1.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/209137","number":209137,"mergeCommit":{"message":"[Fleet]
Include removed agent policies agent count in confirm modal multiple
integration policies
(#209137)","sha":"ef77adf686495b0f1fd3517b28c29e786bee99f3"}}]}]
BACKPORT-->

Co-authored-by: Nicolas Chaulet <[email protected]>
  • Loading branch information
kibanamachine and nchaulet authored Jan 31, 2025
1 parent 1a421d7 commit 24d8a92
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 39 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import { createFleetTestRendererMock } from '../../../../../mock';

import {
useUIExtension,
sendGetAgentStatus,
sendGetOneAgentPolicy,
sendGetOnePackagePolicy,
sendUpgradePackagePolicyDryRun,
Expand All @@ -24,6 +23,7 @@ import {
useGetAgentPolicies,
useMultipleAgentPolicies,
useGetPackagePolicies,
sendBulkGetAgentPoliciesForRq,
} from '../../../hooks';
import { useGetOnePackagePolicy } from '../../../../integrations/hooks';

Expand All @@ -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(),
Expand Down Expand Up @@ -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' }] },
});
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -529,8 +530,8 @@ describe('edit package policy page', () => {
beforeEach(() => {
useMultipleAgentPoliciesMock.mockReturnValue({ canUseMultipleAgentPolicies: true });

(sendGetAgentStatus as jest.MockedFunction<any>).mockResolvedValue({
data: { results: { total: 0 } },
(sendBulkGetAgentPoliciesForRq as jest.MockedFunction<any>).mockResolvedValue({
data: [],
});
jest.clearAllMocks();
});
Expand Down Expand Up @@ -569,7 +570,6 @@ describe('edit package policy page', () => {
policy_ids: ['agent-policy-1', 'agent-policy-2'],
})
);
expect(sendGetAgentStatus).toHaveBeenCalledTimes(1);
});
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ import {
useStartServices,
useConfig,
useUIExtension,
sendGetAgentStatus,
useAuthz,
sendBulkGetAgentPoliciesForRq,
} from '../../../hooks';
import {
useBreadcrumbs as useIntegrationsBreadcrumbs,
Expand Down Expand Up @@ -159,24 +159,74 @@ export const EditPackagePolicyForm = memo<{

const [hasAgentPolicyError, setHasAgentPolicyError] = useState<boolean>(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<number>(0);
const [impactedAgentCount, setImpactedAgentCount] = useState<number>(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']
Expand Down Expand Up @@ -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');
Expand Down Expand Up @@ -518,12 +546,12 @@ export const EditPackagePolicyForm = memo<{
/>
{formState === 'CONFIRM' && (
<ConfirmDeployAgentPolicyModal
agentCount={agentCount}
agentCount={impactedAgentCount}
agentPolicies={agentPolicies}
onConfirm={onSubmit}
onCancel={() => setFormState('VALID')}
agentPoliciesToAdd={agentPoliciesToAdd}
agentPoliciesToRemove={agentPoliciesToRemove}
agentPoliciesToRemove={agentPoliciesToRemoveName}
/>
)}
{packageInfo && isRootPrivilegesRequired(packageInfo) ? (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,18 @@ export const sendBulkGetAgentPolicies = (
});
};

export const sendBulkGetAgentPoliciesForRq = (
ids: string[],
options?: { full?: boolean; ignoreMissing?: boolean }
) => {
return sendRequestForRq<BulkGetAgentPoliciesResponse>({
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<GetAgentPoliciesResponse>({
path: agentPolicyRouteService.getListPath(),
Expand Down

0 comments on commit 24d8a92

Please sign in to comment.