[Fleet] Fix enrollment flyout with fleet server from policy page (#104542)

* [Fleet] Fix enrollment flyout with fleet server from policy page

* Fix tests

* Show enrollment instructions for add agent from fleet server policy

* Fix conditions to show fleet server setup in flyout

Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
Nicolas Chaulet 2021-07-12 11:56:43 -04:00 committed by GitHub
parent 3e5ed77470
commit eae975e91b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 87 additions and 44 deletions

View file

@ -11,6 +11,7 @@ jest.mock('../../hooks/use_request', () => {
...module,
useGetSettings: jest.fn(),
sendGetFleetStatus: jest.fn(),
sendGetOneAgentPolicy: jest.fn(),
};
});

View file

@ -16,7 +16,7 @@ import { coreMock } from 'src/core/public/mocks';
import { KibanaContextProvider } from '../../../../../../src/plugins/kibana_react/public';
import type { AgentPolicy } from '../../../common';
import { useGetSettings, sendGetFleetStatus } from '../../hooks/use_request';
import { useGetSettings, sendGetFleetStatus, sendGetOneAgentPolicy } from '../../hooks/use_request';
import { FleetStatusProvider, ConfigContext } from '../../hooks';
import { useFleetServerInstructions } from '../../applications/fleet/sections/agents/agent_requirements_page/components';
@ -79,6 +79,10 @@ describe('<AgentEnrollmentFlyout />', () => {
data: { isReady: true },
});
(sendGetOneAgentPolicy as jest.Mock).mockResolvedValue({
data: { item: { package_policies: [] } },
});
(useFleetServerInstructions as jest.Mock).mockReturnValue({
serviceToken: 'test',
getServiceToken: jest.fn(),

View file

@ -22,7 +22,9 @@ import {
} from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n/react';
import { useGetSettings, useUrlModal } from '../../hooks';
import { useGetSettings, useUrlModal, sendGetOneAgentPolicy, useFleetStatus } from '../../hooks';
import { FLEET_SERVER_PACKAGE } from '../../constants';
import type { PackagePolicy } from '../../types';
import { ManagedInstructions } from './managed_instructions';
import { StandaloneInstructions } from './standalone_instructions';
@ -63,6 +65,30 @@ export const AgentEnrollmentFlyout: React.FunctionComponent<Props> = ({
}
}, [modal, lastModal, settings]);
const fleetStatus = useFleetStatus();
const [policyId, setSelectedPolicyId] = useState(agentPolicy?.id);
const [isFleetServerPolicySelected, setIsFleetServerPolicySelected] = useState<boolean>(false);
useEffect(() => {
async function checkPolicyIsFleetServer() {
if (policyId && setIsFleetServerPolicySelected) {
const agentPolicyRequest = await sendGetOneAgentPolicy(policyId);
if (
agentPolicyRequest.data?.item &&
(agentPolicyRequest.data.item.package_policies as PackagePolicy[]).some(
(packagePolicy) => packagePolicy.package?.name === FLEET_SERVER_PACKAGE
)
) {
setIsFleetServerPolicySelected(true);
} else {
setIsFleetServerPolicySelected(false);
}
}
}
checkPolicyIsFleetServer();
}, [policyId]);
const isLoadingInitialRequest = settings.isLoading && settings.isInitialRequest;
return (
@ -110,16 +136,23 @@ export const AgentEnrollmentFlyout: React.FunctionComponent<Props> = ({
<EuiFlyoutBody
banner={
!isLoadingInitialRequest && fleetServerHosts.length === 0 && mode === 'managed' ? (
fleetStatus.isReady &&
!isFleetServerPolicySelected &&
!isLoadingInitialRequest &&
fleetServerHosts.length === 0 &&
mode === 'managed' ? (
<MissingFleetServerHostCallout />
) : undefined
}
>
{fleetServerHosts.length === 0 && mode === 'managed' ? null : mode === 'managed' ? (
{mode === 'managed' ? (
<ManagedInstructions
settings={settings.data?.item}
setSelectedPolicyId={setSelectedPolicyId}
agentPolicy={agentPolicy}
agentPolicies={agentPolicies}
viewDataStep={viewDataStep}
isFleetServerPolicySelected={isFleetServerPolicySelected}
/>
) : (
<StandaloneInstructions agentPolicy={agentPolicy} agentPolicies={agentPolicies} />

View file

@ -11,7 +11,7 @@ import type { EuiContainedStepProps } from '@elastic/eui/src/components/steps/st
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n/react';
import { useGetOneEnrollmentAPIKey, useGetSettings, useLink, useFleetStatus } from '../../hooks';
import { useGetOneEnrollmentAPIKey, useLink, useFleetStatus } from '../../hooks';
import { ManualInstructions } from '../../components/enrollment_instructions';
import {
@ -56,14 +56,19 @@ const FleetServerMissingRequirements = () => {
};
export const ManagedInstructions = React.memo<Props>(
({ agentPolicy, agentPolicies, viewDataStep }) => {
({
agentPolicy,
agentPolicies,
viewDataStep,
setSelectedPolicyId,
isFleetServerPolicySelected,
settings,
}) => {
const fleetStatus = useFleetStatus();
const [selectedApiKeyId, setSelectedAPIKeyId] = useState<string | undefined>();
const [isFleetServerPolicySelected, setIsFleetServerPolicySelected] = useState<boolean>(false);
const apiKey = useGetOneEnrollmentAPIKey(selectedApiKeyId);
const settings = useGetSettings();
const fleetServerInstructions = useFleetServerInstructions(apiKey?.data?.item?.policy_id);
const fleetServerSteps = useMemo(() => {
@ -88,7 +93,7 @@ export const ManagedInstructions = React.memo<Props>(
}, [fleetServerInstructions]);
const steps = useMemo(() => {
const fleetServerHosts = settings.data?.item?.fleet_server_hosts || [];
const fleetServerHosts = settings?.fleet_server_hosts || [];
const baseSteps: EuiContainedStepProps[] = [
DownloadStep(),
!agentPolicy
@ -96,7 +101,7 @@ export const ManagedInstructions = React.memo<Props>(
agentPolicies,
selectedApiKeyId,
setSelectedAPIKeyId,
setIsFleetServerPolicySelected,
setSelectedPolicyId,
})
: AgentEnrollmentKeySelectionStep({ agentPolicy, selectedApiKeyId, setSelectedAPIKeyId }),
];
@ -121,30 +126,39 @@ export const ManagedInstructions = React.memo<Props>(
}, [
agentPolicy,
selectedApiKeyId,
setSelectedPolicyId,
setSelectedAPIKeyId,
agentPolicies,
apiKey.data,
fleetServerSteps,
isFleetServerPolicySelected,
settings.data?.item?.fleet_server_hosts,
settings?.fleet_server_hosts,
viewDataStep,
]);
if (fleetStatus.isReady && settings?.fleet_server_hosts.length === 0) {
return null;
}
if (fleetStatus.isReady) {
return (
<>
<EuiText>
<FormattedMessage
id="xpack.fleet.agentEnrollment.managedDescription"
defaultMessage="Enroll an Elastic Agent in Fleet to automatically deploy updates and centrally manage the agent."
/>
</EuiText>
<EuiSpacer size="l" />
<EuiSteps steps={steps} />
</>
);
}
return (
<>
{fleetStatus.isReady ? (
<>
<EuiText>
<FormattedMessage
id="xpack.fleet.agentEnrollment.managedDescription"
defaultMessage="Enroll an Elastic Agent in Fleet to automatically deploy updates and centrally manage the agent."
/>
</EuiText>
<EuiSpacer size="l" />
<EuiSteps steps={steps} />
</>
) : fleetStatus.missingRequirements?.length === 1 &&
fleetStatus.missingRequirements[0] === 'fleet_server' ? (
{fleetStatus.missingRequirements?.length === 1 &&
fleetStatus.missingRequirements[0] === 'fleet_server' ? (
<FleetServerMissingRequirements />
) : (
<DefaultMissingRequirements />

View file

@ -11,9 +11,8 @@ import { FormattedMessage } from '@kbn/i18n/react';
import { i18n } from '@kbn/i18n';
import semver from 'semver';
import type { AgentPolicy, PackagePolicy } from '../../types';
import { sendGetOneAgentPolicy, useKibanaVersion } from '../../hooks';
import { FLEET_SERVER_PACKAGE } from '../../constants';
import type { AgentPolicy } from '../../types';
import { useKibanaVersion } from '../../hooks';
import { EnrollmentStepAgentPolicy } from './agent_policy_selection';
import { AdvancedAgentAuthenticationSettings } from './advanced_agent_authentication_settings';
@ -69,13 +68,11 @@ export const AgentPolicySelectionStep = ({
selectedApiKeyId,
setSelectedAPIKeyId,
excludeFleetServer,
setIsFleetServerPolicySelected,
}: {
agentPolicies?: AgentPolicy[];
setSelectedPolicyId?: (policyId?: string) => void;
selectedApiKeyId?: string;
setSelectedAPIKeyId?: (key?: string) => void;
setIsFleetServerPolicySelected?: (selected: boolean) => void;
excludeFleetServer?: boolean;
}) => {
const regularAgentPolicies = useMemo(() => {
@ -92,21 +89,8 @@ export const AgentPolicySelectionStep = ({
if (setSelectedPolicyId) {
setSelectedPolicyId(policyId);
}
if (policyId && setIsFleetServerPolicySelected) {
const agentPolicyRequest = await sendGetOneAgentPolicy(policyId);
if (
agentPolicyRequest.data?.item &&
(agentPolicyRequest.data.item.package_policies as PackagePolicy[]).some(
(packagePolicy) => packagePolicy.package?.name === FLEET_SERVER_PACKAGE
)
) {
setIsFleetServerPolicySelected(true);
} else {
setIsFleetServerPolicySelected(false);
}
}
},
[setIsFleetServerPolicySelected, setSelectedPolicyId]
[setSelectedPolicyId]
);
return {

View file

@ -7,7 +7,7 @@
import type { EuiStepProps } from '@elastic/eui';
import type { AgentPolicy } from '../../types';
import type { AgentPolicy, Settings } from '../../types';
export interface BaseProps {
/**
@ -27,4 +27,10 @@ export interface BaseProps {
* in some way. This is an area for consumers to render a button and text explaining how data can be viewed.
*/
viewDataStep?: EuiStepProps;
settings?: Settings;
setSelectedPolicyId?: (policyId?: string) => void;
isFleetServerPolicySelected?: boolean;
}

View file

@ -27,6 +27,7 @@ export {
PackagePolicyPackage,
Output,
DataStream,
Settings,
// API schema - misc setup, status
GetFleetStatusResponse,
// API schemas - Agent policy