-
Notifications
You must be signed in to change notification settings - Fork 8.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[Fleet] Added modal to manage agent policies of an integration policy (…
…#186987) ## Summary Closes #182112 Added modal to manage agent policies. To verify: - go to an integration where the integration policies are listed - click on the `+` button in the agent policies column - click on `Manage agent policies` in the popover - add/remove agent policies in the modal - click submit, the integration policy should be updated to be linked to the updated agent policies <img width="1614" alt="image" src="https://github.com/elastic/kibana/assets/90178898/33101f7e-8563-4990-9a52-74e5448c21da"> Made a change to the table column display to show a `+` button even if there is only one policy. Previously the popover could only be accessed if there are at least 2 agent policies. Also restored the agent policy link, lock icon and revision display (instead of a badge) if there are multiple agent policies. @simosilvestri Let me know if you have any UX recommendation as it differs slightly from the prototype. <img width="982" alt="image" src="https://github.com/elastic/kibana/assets/90178898/51aff39c-3f84-4861-8614-c0e16b64f4bf"> <img width="1533" alt="image" src="https://github.com/elastic/kibana/assets/90178898/f08de084-d4c2-47c6-b532-f875ceaf10ef"> EDIT: after discussing with Simona, removed the + button in case of a single agent policy assigned to the integration policy. <img width="1391" alt="image" src="https://github.com/elastic/kibana/assets/90178898/9ce5e98a-3ea2-4b79-a073-62047012db03"> Disabling `Manage agent policies` button if the current user doesn't have at least write integration policies and write agent policies privilege. This is how it looks with read privileges: <img width="2294" alt="image" src="https://github.com/elastic/kibana/assets/90178898/625843fb-8a50-4a06-b3a3-dc95a9fc2654"> ### Checklist - [x] Any text added follows [EUI's writing guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses sentence case text and includes [i18n support](https://github.com/elastic/kibana/blob/main/packages/kbn-i18n/README.md) - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios
- Loading branch information
1 parent
369fb60
commit 813fc21
Showing
11 changed files
with
823 additions
and
264 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
177 changes: 177 additions & 0 deletions
177
...nt_policy/create_package_policy_page/components/steps/components/agent_policy_options.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,177 @@ | ||
/* | ||
* 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, { useMemo } from 'react'; | ||
import type { EuiComboBoxOptionOption, EuiSuperSelectOption } from '@elastic/eui'; | ||
import { EuiIcon, EuiSpacer, EuiText, EuiToolTip } from '@elastic/eui'; | ||
|
||
import { FormattedMessage } from '@kbn/i18n-react'; | ||
|
||
import type { AgentPolicy, Output, PackageInfo } from '../../../../../../../../../common'; | ||
import { | ||
FLEET_APM_PACKAGE, | ||
PACKAGE_POLICY_SAVED_OBJECT_TYPE, | ||
SO_SEARCH_LIMIT, | ||
} from '../../../../../../../../../common'; | ||
import { outputType } from '../../../../../../../../../common/constants'; | ||
import { isPackageLimited } from '../../../../../../../../../common/services'; | ||
import { useGetAgentPolicies, useGetOutputs, useGetPackagePolicies } from '../../../../../../hooks'; | ||
|
||
export function useAgentPoliciesOptions(packageInfo?: PackageInfo) { | ||
// Fetch agent policies info | ||
const { | ||
data: agentPoliciesData, | ||
error: agentPoliciesError, | ||
isLoading: isAgentPoliciesLoading, | ||
} = useGetAgentPolicies({ | ||
page: 1, | ||
perPage: SO_SEARCH_LIMIT, | ||
sortField: 'name', | ||
sortOrder: 'asc', | ||
noAgentCount: true, // agentPolicy.agents will always be 0 | ||
full: false, // package_policies will always be empty | ||
}); | ||
const agentPolicies = useMemo( | ||
() => agentPoliciesData?.items.filter((policy) => !policy.is_managed) || [], | ||
[agentPoliciesData?.items] | ||
); | ||
|
||
const { data: outputsData, isLoading: isOutputLoading } = useGetOutputs(); | ||
|
||
// get all package policies with apm integration or the current integration | ||
const { data: packagePoliciesForThisPackage, isLoading: isLoadingPackagePolicies } = | ||
useGetPackagePolicies({ | ||
page: 1, | ||
perPage: SO_SEARCH_LIMIT, | ||
kuery: `${PACKAGE_POLICY_SAVED_OBJECT_TYPE}.package.name: ${packageInfo?.name}`, | ||
}); | ||
|
||
const packagePoliciesForThisPackageByAgentPolicyId = useMemo( | ||
() => | ||
packagePoliciesForThisPackage?.items.reduce( | ||
(acc: { [key: string]: boolean }, packagePolicy) => { | ||
packagePolicy.policy_ids.forEach((policyId) => { | ||
acc[policyId] = true; | ||
}); | ||
return acc; | ||
}, | ||
{} | ||
), | ||
[packagePoliciesForThisPackage?.items] | ||
); | ||
|
||
const { getDataOutputForPolicy } = useMemo(() => { | ||
const defaultOutput = (outputsData?.items ?? []).find((output) => output.is_default); | ||
const outputsById = (outputsData?.items ?? []).reduce( | ||
(acc: { [key: string]: Output }, output) => { | ||
acc[output.id] = output; | ||
return acc; | ||
}, | ||
{} | ||
); | ||
|
||
return { | ||
getDataOutputForPolicy: (policy: Pick<AgentPolicy, 'data_output_id'>) => { | ||
return policy.data_output_id ? outputsById[policy.data_output_id] : defaultOutput; | ||
}, | ||
}; | ||
}, [outputsData]); | ||
|
||
const agentPolicyOptions: Array<EuiSuperSelectOption<string>> = useMemo( | ||
() => | ||
packageInfo | ||
? agentPolicies.map((policy) => { | ||
const isLimitedPackageAlreadyInPolicy = | ||
isPackageLimited(packageInfo!) && | ||
packagePoliciesForThisPackageByAgentPolicyId?.[policy.id]; | ||
|
||
const isAPMPackageAndDataOutputIsLogstash = | ||
packageInfo?.name === FLEET_APM_PACKAGE && | ||
getDataOutputForPolicy(policy)?.type === outputType.Logstash; | ||
|
||
return { | ||
inputDisplay: ( | ||
<> | ||
<EuiText size="s">{policy.name}</EuiText> | ||
{isAPMPackageAndDataOutputIsLogstash && ( | ||
<> | ||
<EuiSpacer size="xs" /> | ||
<EuiText size="s"> | ||
<FormattedMessage | ||
id="xpack.fleet.createPackagePolicy.StepSelectPolicy.agentPolicyDisabledAPMLogstashOuputText" | ||
defaultMessage="Logstash output for integrations is not supported with APM" | ||
/> | ||
</EuiText> | ||
</> | ||
)} | ||
</> | ||
), | ||
value: policy.id, | ||
disabled: isLimitedPackageAlreadyInPolicy || isAPMPackageAndDataOutputIsLogstash, | ||
'data-test-subj': 'agentPolicyItem', | ||
}; | ||
}) | ||
: [], | ||
[ | ||
packageInfo, | ||
agentPolicies, | ||
packagePoliciesForThisPackageByAgentPolicyId, | ||
getDataOutputForPolicy, | ||
] | ||
); | ||
|
||
const agentPolicyMultiOptions: Array<EuiComboBoxOptionOption<string>> = useMemo( | ||
() => | ||
packageInfo && !isOutputLoading && !isAgentPoliciesLoading && !isLoadingPackagePolicies | ||
? agentPolicies.map((policy) => { | ||
const isLimitedPackageAlreadyInPolicy = | ||
isPackageLimited(packageInfo!) && | ||
packagePoliciesForThisPackageByAgentPolicyId?.[policy.id]; | ||
|
||
const isAPMPackageAndDataOutputIsLogstash = | ||
packageInfo?.name === FLEET_APM_PACKAGE && | ||
getDataOutputForPolicy(policy)?.type === outputType.Logstash; | ||
|
||
return { | ||
append: isAPMPackageAndDataOutputIsLogstash ? ( | ||
<EuiToolTip | ||
content={ | ||
<FormattedMessage | ||
id="xpack.fleet.createPackagePolicy.StepSelectPolicy.agentPolicyDisabledAPMLogstashOuputText" | ||
defaultMessage="Logstash output for integrations is not supported with APM" | ||
/> | ||
} | ||
> | ||
<EuiIcon size="s" type="warningFilled" /> | ||
</EuiToolTip> | ||
) : null, | ||
key: policy.id, | ||
label: policy.name, | ||
disabled: isLimitedPackageAlreadyInPolicy || isAPMPackageAndDataOutputIsLogstash, | ||
'data-test-subj': 'agentPolicyMultiItem', | ||
}; | ||
}) | ||
: [], | ||
[ | ||
packageInfo, | ||
agentPolicies, | ||
packagePoliciesForThisPackageByAgentPolicyId, | ||
getDataOutputForPolicy, | ||
isOutputLoading, | ||
isAgentPoliciesLoading, | ||
isLoadingPackagePolicies, | ||
] | ||
); | ||
|
||
return { | ||
agentPoliciesError, | ||
isLoading: isOutputLoading || isAgentPoliciesLoading || isLoadingPackagePolicies, | ||
agentPolicyOptions, | ||
agentPolicies, | ||
agentPolicyMultiOptions, | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.