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] change UX of edit integration policy agent policies #190583

Merged
merged 12 commits into from
Aug 29, 2024
10 changes: 1 addition & 9 deletions x-pack/plugins/fleet/cypress/tasks/integrations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,8 @@ export const addIntegration = ({ useExistingPolicy } = { useExistingPolicy: fals
if (useExistingPolicy) {
cy.getBySel(EXISTING_HOSTS_TAB).click();
} else {
// speeding up creating with unchecking system and agent integration
// speeding up creating with unchecking system integration
cy.getBySel(AGENT_POLICY_SYSTEM_MONITORING_CHECKBOX).uncheck({ force: true });
cy.get('.euiAccordion__button').click();

cy.get('*[id^="logs_"]').uncheck({
force: true,
});
cy.get('*[id^="metrics_"]').uncheck({
force: true,
});
}
cy.getBySel(CREATE_PACKAGE_POLICY_SAVE_BTN).click();
// sometimes agent is assigned to default policy, sometimes not
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,29 +6,15 @@
*/

import React from 'react';
import {
EuiAccordion,
EuiDescribedFormGroup,
EuiForm,
EuiHorizontalRule,
EuiSpacer,
} from '@elastic/eui';
import { EuiDescribedFormGroup, EuiForm } from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n-react';
import styled from 'styled-components';

import type { NewAgentPolicy, AgentPolicy } from '../../../types';

import { AgentPolicyAdvancedOptionsContent } from './agent_policy_advanced_fields';
import { AgentPolicyGeneralFields } from './agent_policy_general_fields';
import { AgentPolicyFormSystemMonitoringCheckbox } from './agent_policy_system_monitoring_field';
import type { ValidationResults } from './agent_policy_validation';

const StyledEuiAccordion = styled(EuiAccordion)`
.ingest-active-button {
color: ${(props) => props.theme.eui.euiColorPrimary};
}
`;

interface Props {
agentPolicy: Partial<NewAgentPolicy | AgentPolicy>;
updateAgentPolicy: (u: Partial<NewAgentPolicy | AgentPolicy>) => void;
Expand Down Expand Up @@ -80,27 +66,6 @@ export const AgentPolicyIntegrationForm: React.FunctionComponent<Props> = ({
updateSysMonitoring={updateSysMonitoring}
/>
</EuiDescribedFormGroup>
<>
<EuiHorizontalRule />
<EuiSpacer size="xs" />
<StyledEuiAccordion
id="advancedOptions"
buttonContent={
<FormattedMessage
id="xpack.fleet.agentPolicyForm.advancedOptionsToggleLabel"
defaultMessage="Advanced options"
/>
}
buttonClassName="ingest-active-button"
>
<EuiSpacer size="l" />
<AgentPolicyAdvancedOptionsContent
agentPolicy={agentPolicy}
updateAgentPolicy={updateAgentPolicy}
validation={validation}
/>
</StyledEuiAccordion>
</>
</EuiForm>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
* 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 { useMemo } from 'react';

import type { AgentPolicy } from '../../../../../../../../../common';

import { SO_SEARCH_LIMIT } from '../../../../../../../../../common';
import { useGetAgentPolicies } from '../../../../../../../../hooks';

export const useAllNonManagedAgentPolicies = () => {
let existingAgentPolicies: AgentPolicy[] = [];
const { data: agentPoliciesData, error: err } = useGetAgentPolicies({
page: 1,
perPage: SO_SEARCH_LIMIT,
sortField: 'name',
sortOrder: 'asc',
full: false, // package_policies will always be empty
noAgentCount: true, // agentPolicy.agents will always be 0
});
if (err) {
// eslint-disable-next-line no-console
console.debug('Could not retrieve agent policies');
}
existingAgentPolicies = useMemo(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could we search directly for non managed policies in the API call with a kuery like not is_managed:* or is_managed:false (not tested)?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member

@nchaulet nchaulet Aug 28, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it should be indexed https://github.com/juliaElastic/kibana/blob/22c3f95868d6a5d804e9ed85b7575da6dd423b46/x-pack/plugins/fleet/server/saved_objects/index.ts#L282 but not a blocker it should not really change the number of policies returned as we do not expect to have many managed policies

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are right, I was looking at the wrong place.
The filter actually works, I tried before without the prefix ingest-agent-policies.is_managed:false

() => agentPoliciesData?.items.filter((policy) => !policy.is_managed) || [],
[agentPoliciesData?.items]
);
return existingAgentPolicies;
};
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,14 @@ import { useGetAgentPolicies } from '../../../../../hooks';
import type { AgentPolicy, PackageInfo } from '../../../../../types';

import { StepSelectHosts } from './step_select_hosts';
import { useAllNonManagedAgentPolicies } from './components/use_policies';

jest.mock('./components/use_policies', () => {
return {
...jest.requireActual('./components/use_policies'),
useAllNonManagedAgentPolicies: jest.fn(),
};
});

jest.mock('../../../../../hooks', () => {
return {
Expand Down Expand Up @@ -121,6 +129,9 @@ describe('StepSelectHosts', () => {
items: [{ id: '1', name: 'Agent policy 1', namespace: 'default' }],
},
});
(useAllNonManagedAgentPolicies as jest.MockedFunction<any>).mockReturnValue([
{ id: '1', name: 'Agent policy 1', namespace: 'default' },
]);

render();

Expand All @@ -140,6 +151,9 @@ describe('StepSelectHosts', () => {
items: [{ id: '1', name: 'Agent policy 1', namespace: 'default' }],
},
});
(useAllNonManagedAgentPolicies as jest.MockedFunction<any>).mockReturnValue([
{ id: '1', name: 'Agent policy 1', namespace: 'default' },
]);

render();

Expand All @@ -164,6 +178,10 @@ describe('StepSelectHosts', () => {
],
},
});
(useAllNonManagedAgentPolicies as jest.MockedFunction<any>).mockReturnValue([
{ id: '1', name: 'Agent policy 1', namespace: 'default' },
{ id: '2', name: 'Agent policy 2', namespace: 'default' },
]);

render();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,20 @@
* 2.0.
*/

import React, { useEffect, useMemo } from 'react';
import React, { useEffect } from 'react';
import type { EuiTabbedContentTab } from '@elastic/eui';
import { EuiTabbedContent } from '@elastic/eui';
import styled from 'styled-components';

import { useGetAgentPolicies } from '../../../../../hooks';
import type { AgentPolicy, NewAgentPolicy, PackageInfo } from '../../../../../types';
import { AgentPolicyIntegrationForm } from '../../../components';
import { SO_SEARCH_LIMIT } from '../../../../../constants';
import type { ValidationResults } from '../../../components/agent_policy_validation';

import { incrementPolicyName } from '../../../../../services';

import { AgentPolicyIntegrationForm } from '../../../components';

import { StepSelectAgentPolicy } from './step_select_agent_policy';
import { useAllNonManagedAgentPolicies } from './components/use_policies';

export enum SelectedPolicyTab {
NEW = 'new',
Expand Down Expand Up @@ -60,23 +60,7 @@ export const StepSelectHosts: React.FunctionComponent<Props> = ({
selectedAgentPolicyIds,
initialSelectedTabIndex,
}) => {
let existingAgentPolicies: AgentPolicy[] = [];
const { data: agentPoliciesData, error: err } = useGetAgentPolicies({
page: 1,
perPage: SO_SEARCH_LIMIT,
sortField: 'name',
sortOrder: 'asc',
full: false, // package_policies will always be empty
noAgentCount: true, // agentPolicy.agents will always be 0
});
if (err) {
// eslint-disable-next-line no-console
console.debug('Could not retrieve agent policies');
}
existingAgentPolicies = useMemo(
() => agentPoliciesData?.items.filter((policy) => !policy.is_managed) || [],
[agentPoliciesData?.items]
);
const existingAgentPolicies: AgentPolicy[] = useAllNonManagedAgentPolicies();

useEffect(() => {
if (existingAgentPolicies.length > 0) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,20 @@ import {
useConfig,
} from '../../../../hooks';

jest.mock('../components/steps/components/use_policies', () => {
return {
...jest.requireActual('../components/steps/components/use_policies'),
useAllNonManagedAgentPolicies: jest.fn().mockReturnValue([
{
id: 'agent-policy-1',
name: 'Agent policy 1',
namespace: 'default',
unprivileged_agents: 1,
},
]),
};
});

jest.mock('../../../../hooks', () => {
return {
...jest.requireActual('../../../../hooks'),
Expand Down Expand Up @@ -126,6 +140,8 @@ jest.mock('react-router-dom', () => ({

import { AGENTLESS_POLICY_ID } from '../../../../../../../common/constants';

import { useAllNonManagedAgentPolicies } from '../components/steps/components/use_policies';

import { CreatePackagePolicySinglePage } from '.';
import { SETUP_TECHNOLOGY_SELECTOR_TEST_SUBJ } from './components/setup_technology_selector';

Expand Down Expand Up @@ -702,6 +718,9 @@ describe('When on the package policy create page', () => {
isLoading: false,
resendRequest: jest.fn(),
});
(useAllNonManagedAgentPolicies as jest.MockedFunction<any>).mockReturnValue([
{ id: AGENTLESS_POLICY_ID, name: 'Agentless CSPM', namespace: 'default' },
]);

await act(async () => {
render();
Expand Down
Loading