Skip to content

Commit

Permalink
[Fleet] Redesign agent flyout (#128381)
Browse files Browse the repository at this point in the history
* [Fleet] Redesign and refactor agent flyout

* Further refactoring

* More refactoring and some bug fixing

* bug fixing

* Fix step tests + skip standalone tab tests

* Use test-subj for agent policy code block to fix cypress tests

* Fixing small issues on rendering

* Fix broken import; Fix button in incoming data comp

* Fix loading; add button in incoming data step

* Fix some failures

* Fix tests

* Fix checks

* Address code review comments; add retry logic to incoming data component

* Fix download link

* Check enrolled agents in last 10 minutes

* Filter out agents with data=false from incoming data

Co-authored-by: Kibana Machine <[email protected]>
Co-authored-by: Kyle Pollich <[email protected]>
(cherry picked from commit 6e8d979)
  • Loading branch information
criamico committed Apr 11, 2022
1 parent 3171c94 commit 55603b0
Show file tree
Hide file tree
Showing 44 changed files with 1,704 additions and 1,113 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
ADD_AGENT_BUTTON_TOP,
AGENT_FLYOUT_CLOSE_BUTTON,
STANDALONE_TAB,
AGENT_POLICY_CODE_BLOCK,
} from '../screens/fleet';
import { cleanupAgentPolicies, unenrollAgent } from '../tasks/cleanup';
import { verifyPolicy, verifyAgentPackage, navigateToTab } from '../tasks/fleet';
Expand Down Expand Up @@ -60,12 +61,11 @@ describe('Fleet startup', () => {
cy.log('Create agent policy took: ' + (Date.now() - startTime) / 1000 + ' s');
agentPolicyId = xhr.response.body.item.id;

cy.getBySel('agentPolicyCreateStatusCallOut').contains('Agent policy created');

// verify create button changed to dropdown
cy.getBySel('agentPolicyDropdown');

// verify agent.yml code block has new policy id
cy.get('.euiCodeBlock__code').contains(`id: ${agentPolicyId}`);
cy.getBySel(AGENT_POLICY_CODE_BLOCK).contains(`id: ${agentPolicyId}`);

cy.getBySel(AGENT_FLYOUT_CLOSE_BUTTON).click();

Expand All @@ -78,7 +78,6 @@ describe('Fleet startup', () => {

it('should create Fleet Server policy', () => {
cy.getBySel('createFleetServerPolicyBtn').click();
cy.getBySel('agentPolicyCreateStatusCallOut').contains('Agent policy created');

// verify policy is created and has fleet server and system package
verifyPolicy('Fleet Server policy 1', ['Fleet Server', 'System']);
Expand Down
1 change: 1 addition & 0 deletions x-pack/plugins/fleet/cypress/screens/fleet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export const ADD_AGENT_BUTTON = 'addAgentButton';
export const ADD_AGENT_BUTTON_TOP = 'addAgentBtnTop';
export const CREATE_POLICY_BUTTON = 'createPolicyBtn';
export const AGENT_FLYOUT_CLOSE_BUTTON = 'euiFlyoutCloseButton';
export const AGENT_POLICY_CODE_BLOCK = 'agentPolicyCodeBlock';

export const AGENTS_TAB = 'fleet-agents-tab';
export const AGENT_POLICIES_TAB = 'fleet-agent-policies-tab';
Expand Down
1 change: 0 additions & 1 deletion x-pack/plugins/fleet/cypress/tasks/fleet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ export function createAgentPolicy() {
cy.getBySel(ADD_AGENT_BUTTON_TOP).click();
cy.getBySel(STANDALONE_TAB).click();
cy.getBySel(CREATE_POLICY_BUTTON).click();
cy.getBySel('agentPolicyCreateStatusCallOut').contains('Agent policy created');
cy.getBySel(AGENT_FLYOUT_CLOSE_BUTTON).click();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,6 @@ export const FleetServerCommandStep = ({
windowsCommand={installCommand.windows}
linuxDebCommand={installCommand.deb}
linuxRpmCommand={installCommand.rpm}
troubleshootLink={docLinks.links.fleet.troubleshooting}
isK8s={false}
/>
</>
Expand Down Expand Up @@ -290,36 +289,16 @@ export const useFleetServerInstructions = (policyId?: string) => {
};

const AgentPolicySelectionStep = ({
policyId,
selectedPolicy,
setPolicyId,
agentPolicies,
refreshAgentPolicies,
}: {
policyId?: string;
setPolicyId: (v: string) => void;
selectedPolicy?: AgentPolicy;
setPolicyId: (v?: string) => void;
agentPolicies: AgentPolicy[];
refreshAgentPolicies: () => void;
}): EuiStepProps => {
const { data, resendRequest: refreshAgentPolicies } = useGetAgentPolicies({ full: true });

const agentPolicies = useMemo(
() => (data ? data.items.filter((item) => policyHasFleetServer(item)) : []),
[data]
);

useEffect(() => {
// Select default value
if (agentPolicies.length && !policyId) {
setPolicyId(agentPolicies[0].id);
}
}, [agentPolicies, policyId, setPolicyId]);

const onChangeCallback = useCallback(
(key: string | undefined, policy?: AgentPolicy) => {
if (policy) {
refreshAgentPolicies();
}
setPolicyId(key!);
},
[setPolicyId, refreshAgentPolicies]
);

return {
title:
agentPolicies.length === 0
Expand All @@ -335,9 +314,11 @@ const AgentPolicySelectionStep = ({
<SelectCreateAgentPolicy
agentPolicies={agentPolicies}
withKeySelection={false}
onAgentPolicyChange={onChangeCallback}
excludeFleetServer={false}
isFleetServerPolicy={true}
selectedPolicy={selectedPolicy}
setSelectedPolicyId={setPolicyId}
refreshAgentPolicies={refreshAgentPolicies}
/>
</>
),
Expand Down Expand Up @@ -642,9 +623,28 @@ const CompleteStep = (): EuiStepProps => {
};
};

const findPolicyById = (policies: AgentPolicy[], id: string | undefined) => {
if (!id) return undefined;
return policies.find((p) => p.id === id);
};

export const OnPremInstructions: React.FC = () => {
const { notifications } = useStartServices();
const [policyId, setPolicyId] = useState<string | undefined>();

const { data, resendRequest: refreshAgentPolicies } = useGetAgentPolicies({ full: true });

const agentPolicies = useMemo(
() => (data ? data.items.filter((item) => policyHasFleetServer(item)) : []),
[data]
);

// Select default value
let defaultValue = '';
if (agentPolicies.length) {
defaultValue = agentPolicies[0].id;
}
const [policyId, setPolicyId] = useState<string | undefined>(defaultValue);
const selectedPolicy = findPolicyById(agentPolicies, policyId);

const {
serviceToken,
Expand Down Expand Up @@ -720,7 +720,12 @@ export const OnPremInstructions: React.FC = () => {
<EuiSteps
className="eui-textLeft"
steps={[
AgentPolicySelectionStep({ policyId, setPolicyId }),
AgentPolicySelectionStep({
selectedPolicy,
setPolicyId,
agentPolicies,
refreshAgentPolicies,
}),
DownloadStep(true),
deploymentModeStep({ deploymentMode, setDeploymentMode }),
addFleetServerHostStep({ addFleetServerHost }),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ export const AgentsApp: React.FunctionComponent = () => {
<EuiPortal>
<AgentEnrollmentFlyout
defaultMode="standalone"
isIntegrationFlow={true}
onClose={() => setIsEnrollmentFlyoutOpen(false)}
/>
</EuiPortal>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,14 @@
import { stringify, parse } from 'query-string';
import React, { memo, useCallback, useEffect, useMemo, useState } from 'react';
import { Redirect, useLocation, useHistory } from 'react-router-dom';
import type {
CriteriaWithPagination,
EuiStepProps,
EuiTableFieldDataColumnType,
} from '@elastic/eui';
import type { CriteriaWithPagination, EuiTableFieldDataColumnType } from '@elastic/eui';
import {
EuiBasicTable,
EuiLink,
EuiFlexGroup,
EuiFlexItem,
EuiText,
EuiButton,
EuiSpacer,
} from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { FormattedRelative, FormattedMessage } from '@kbn/i18n-react';
Expand All @@ -31,7 +26,6 @@ import {
useUrlPagination,
useGetPackageInstallStatus,
AgentPolicyRefreshContext,
useUIExtension,
usePackageInstallations,
useAuthz,
} from '../../../../../hooks';
Expand Down Expand Up @@ -103,7 +97,6 @@ export const PackagePoliciesPage = ({ name, version }: PackagePoliciesPanelProps
kuery: `${PACKAGE_POLICY_SAVED_OBJECT_TYPE}.package.name: ${name}`,
});
const { updatableIntegrations } = usePackageInstallations();
const agentEnrollmentFlyoutExtension = useUIExtension(name, 'agent-enrollment-flyout');

const canWriteIntegrationPolicies = useAuthz().integrations.writeIntegrationPolicies;

Expand Down Expand Up @@ -165,50 +158,6 @@ export const PackagePoliciesPage = ({ name, version }: PackagePoliciesPanelProps
[setPagination]
);

const viewDataStep = useMemo<EuiStepProps>(() => {
if (agentEnrollmentFlyoutExtension) {
return {
title: agentEnrollmentFlyoutExtension.title,
children: <agentEnrollmentFlyoutExtension.Component />,
};
}

return {
title: i18n.translate('xpack.fleet.agentEnrollment.stepViewDataTitle', {
defaultMessage: 'View your data',
}),
children: (
<>
<EuiText>
<FormattedMessage
id="xpack.fleet.agentEnrollment.viewDataDescription"
defaultMessage="After your agent starts, you can view your data in Kibana by using the integration's installed assets. {pleaseNote}: it may take a few minutes for the initial data to arrive."
values={{
pleaseNote: (
<strong>
{i18n.translate(
'xpack.fleet.epm.agentEnrollment.viewDataDescription.pleaseNoteLabel',
{ defaultMessage: 'Please note' }
)}
</strong>
),
}}
/>
</EuiText>
<EuiSpacer size="l" />
<EuiButton
fill
href={getHref('integration_details_assets', { pkgkey: `${name}-${version}` })}
>
{i18n.translate('xpack.fleet.epm.agentEnrollment.viewDataAssetsLabel', {
defaultMessage: 'View assets',
})}
</EuiButton>
</>
),
};
}, [name, version, getHref, agentEnrollmentFlyoutExtension]);

const columns: Array<EuiTableFieldDataColumnType<InMemoryPackagePolicyAndAgentPolicy>> = useMemo(
() => [
{
Expand Down Expand Up @@ -323,7 +272,6 @@ export const PackagePoliciesPage = ({ name, version }: PackagePoliciesPanelProps
<PackagePolicyActionsMenu
agentPolicy={agentPolicy}
packagePolicy={packagePolicy}
viewDataStep={viewDataStep}
showAddAgent={true}
upgradePackagePolicyHref={`${getHref('upgrade_package_policy', {
policyId: agentPolicy.id,
Expand All @@ -334,7 +282,7 @@ export const PackagePoliciesPage = ({ name, version }: PackagePoliciesPanelProps
},
},
],
[getHref, showAddAgentHelpForPackagePolicyId, viewDataStep, canWriteIntegrationPolicies]
[getHref, showAddAgentHelpForPackagePolicyId, canWriteIntegrationPolicies]
);

const noItemsMessage = useMemo(() => {
Expand Down Expand Up @@ -362,6 +310,11 @@ export const PackagePoliciesPage = ({ name, version }: PackagePoliciesPanelProps
<Redirect to={getPath('integration_details_overview', { pkgkey: `${name}-${version}` })} />
);
}
const selectedPolicies = packageAndAgentPolicies.find(
({ agentPolicy: policy }) => policy.id === flyoutOpenForPolicyId
);
const agentPolicy = selectedPolicies?.agentPolicy;
const packagePolicy = selectedPolicies?.packagePolicy;

return (
<AgentPolicyRefreshContext.Provider value={{ refresh: refreshPolicies }}>
Expand All @@ -379,19 +332,19 @@ export const PackagePoliciesPage = ({ name, version }: PackagePoliciesPanelProps
/>
</EuiFlexItem>
</EuiFlexGroup>
{flyoutOpenForPolicyId && !isLoading && (
{flyoutOpenForPolicyId && agentPolicy && !isLoading && (
<AgentEnrollmentFlyout
onClose={() => {
setFlyoutOpenForPolicyId(null);
const { addAgentToPolicyId, ...rest } = parse(search);
history.replace({ search: stringify(rest) });
}}
agentPolicy={
packageAndAgentPolicies.find(
({ agentPolicy }) => agentPolicy.id === flyoutOpenForPolicyId
)?.agentPolicy
}
viewDataStep={viewDataStep}
agentPolicy={agentPolicy}
isIntegrationFlow={true}
installedPackagePolicy={{
name: packagePolicy?.package?.name || '',
version: packagePolicy?.package?.version || '',
}}
/>
)}
</AgentPolicyRefreshContext.Provider>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
jest.mock('../../hooks', () => {
return {
...jest.requireActual('../../hooks'),
useFleetStatus: jest.fn(),
useAgentEnrollmentFlyoutData: jest.fn(),
};
});
Expand All @@ -24,6 +25,16 @@ jest.mock('../../hooks/use_request', () => {
};
});

jest.mock('../../applications/fleet/sections/agents/hooks/use_fleet_server_unhealthy', () => {
const module = jest.requireActual(
'../../applications/fleet/sections/agents/hooks/use_fleet_server_unhealthy'
);
return {
...module,
useFleetServerUnhealthy: jest.fn(),
};
});

jest.mock(
'../../applications/fleet/sections/agents/agent_requirements_page/components/fleet_server_on_prem_instructions',
() => {
Expand Down Expand Up @@ -57,18 +68,17 @@ jest.mock('./steps', () => {
const module = jest.requireActual('./steps');
return {
...module,
AgentPolicySelectionStep: jest.fn(),
AgentEnrollmentKeySelectionStep: jest.fn(),
ViewDataStep: jest.fn(),
DownloadStep: jest.fn(),
};
});

jest.mock('@elastic/eui', () => {
const module = jest.requireActual('@elastic/eui');
return {
...module,
EuiSteps: 'eui-steps',
AgentPolicySelectionStep: jest.fn().mockReturnValue({
'data-test-subj': 'agent-policy-selection-step',
title: 'agent-policy-selection-step',
}),
AgentEnrollmentKeySelectionStep: jest.fn().mockReturnValue({
'data-test-subj': 'agent-enrollment-key-selection-step',
title: 'agent-enrollment-key-selection-step',
}),
DownloadStep: jest
.fn()
.mockReturnValue({ 'data-test-subj': 'download-step', title: 'download-step' }),
};
});

Expand Down
Loading

0 comments on commit 55603b0

Please sign in to comment.