Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,6 @@ export const AGENT_CONFIG_DETAILS_PATH = `${AGENT_CONFIG_PATH}/`;
export const FLEET_PATH = '/fleet';
export const FLEET_AGENTS_PATH = `${FLEET_PATH}/agents`;
export const FLEET_AGENT_DETAIL_PATH = `${FLEET_AGENTS_PATH}/`;
export const FLEET_ENROLLMENT_TOKENS_PATH = `/fleet/enrollment-tokens`;

export const INDEX_NAME = '.kibana';
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,13 @@
* you may not use this file except in compliance with the Elastic License.
*/

import { useRequest, UseRequestConfig } from './use_request';
import { useRequest, UseRequestConfig, sendRequest } from './use_request';
import { enrollmentAPIKeyRouteService } from '../../services';
import { GetOneEnrollmentAPIKeyResponse, GetEnrollmentAPIKeysResponse } from '../../types';
import {
GetOneEnrollmentAPIKeyResponse,
GetEnrollmentAPIKeysResponse,
GetEnrollmentAPIKeysRequest,
} from '../../types';

type RequestOptions = Pick<Partial<UseRequestConfig>, 'pollIntervalMs'>;

Expand All @@ -18,10 +22,30 @@ export function useGetOneEnrollmentAPIKey(keyId: string, options?: RequestOption
});
}

export function useGetEnrollmentAPIKeys(options?: RequestOptions) {
export function sendGetOneEnrollmentAPIKey(keyId: string, options?: RequestOptions) {
return sendRequest<GetOneEnrollmentAPIKeyResponse>({
method: 'get',
path: enrollmentAPIKeyRouteService.getInfoPath(keyId),
...options,
});
}

export function sendDeleteOneEnrollmentAPIKey(keyId: string, options?: RequestOptions) {
return sendRequest({
method: 'delete',
path: enrollmentAPIKeyRouteService.getDeletePath(keyId),
...options,
});
}

export function useGetEnrollmentAPIKeys(
query: GetEnrollmentAPIKeysRequest['query'],
options?: RequestOptions
) {
return useRequest<GetEnrollmentAPIKeysResponse>({
method: 'get',
path: enrollmentAPIKeyRouteService.getListPath(),
query,
...options,
});
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,10 @@ export const ConfigYamlView = memo<{ config: AgentConfig }>(({ config }) => {
const core = useCore();

const fullConfigRequest = useGetOneAgentConfigFull(config.id);
const apiKeysRequest = useGetEnrollmentAPIKeys();
const apiKeysRequest = useGetEnrollmentAPIKeys({
page: 1,
perPage: 1000,
});
const apiKeyRequest = useGetOneEnrollmentAPIKey(apiKeysRequest.data?.list?.[0]?.id as string);

if (fullConfigRequest.isLoading && !fullConfigRequest.data) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,10 @@ import {
} from '../../../../../hooks';

export function useEnrollmentApiKeys(pagination: Pagination) {
const request = useGetEnrollmentAPIKeys();
const request = useGetEnrollmentAPIKeys({
page: pagination.currentPage,
perPage: pagination.pageSize,
});

return {
data: request.data,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
* you may not use this file except in compliance with the Elastic License.
*/
import React, { useState, useCallback } from 'react';
import styled, { CSSProperties } from 'styled-components';
import {
EuiBasicTable,
EuiButton,
Expand All @@ -17,21 +16,16 @@ import {
EuiLink,
EuiPopover,
EuiSpacer,
EuiSwitch,
EuiText,
EuiTitle,
EuiStat,
EuiI18nNumber,
EuiHealth,
EuiButtonIcon,
EuiContextMenuPanel,
EuiContextMenuItem,
EuiIcon,
} from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { FormattedMessage, FormattedRelative } from '@kbn/i18n/react';
import { CSSProperties } from 'styled-components';
import { AgentEnrollmentFlyout } from './components';
import { WithHeaderLayout } from '../../../layouts';
import { Agent } from '../../../types';
import {
usePagination,
Expand All @@ -45,17 +39,9 @@ import { ConnectedLink } from '../components';
import { SearchBar } from '../../../components/search_bar';
import { AgentHealth } from '../components/agent_health';
import { AgentUnenrollProvider } from '../components/agent_unenroll_provider';
import { DonutChart } from './components/donut_chart';
import { useGetAgentStatus } from '../../agent_config/details_page/hooks';
import { AgentStatusKueryHelper } from '../../../services';
import { FLEET_AGENT_DETAIL_PATH, AGENT_CONFIG_DETAILS_PATH } from '../../../constants';

const Divider = styled.div`
width: 0;
height: 100%;
border-left: ${props => props.theme.eui.euiBorderThin};
height: 45px;
`;
const NO_WRAP_TRUNCATE_STYLE: CSSProperties = Object.freeze({
overflow: 'hidden',
textOverflow: 'ellipsis',
Expand Down Expand Up @@ -204,11 +190,6 @@ export const AgentListPage: React.FunctionComponent<{}> = () => {
.join(' or ');
}

const agentStatusRequest = useGetAgentStatus(undefined, {
pollIntervalMs: REFRESH_INTERVAL_MS,
});
const agentStatus = agentStatusRequest.data?.results;

const agentsRequest = useGetAgents(
{
page: pagination.currentPage,
Expand Down Expand Up @@ -399,154 +380,15 @@ export const AgentListPage: React.FunctionComponent<{}> = () => {
}
/>
);
const headerRightColumn = (
<EuiFlexGroup justifyContent={'flexEnd'} direction="row">
<EuiFlexItem grow={false}>
<EuiStat
titleSize="xs"
textAlign="right"
title={<EuiI18nNumber value={agentStatus?.total ?? 0} />}
description={i18n.translate('xpack.ingestManager.agentListStatus.totalLabel', {
defaultMessage: 'Agents',
})}
/>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<DonutChart
width={40}
height={40}
data={{
online: agentStatus?.online || 0,
offline: agentStatus?.offline || 0,
error: agentStatus?.error || 0,
}}
/>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiStat
textAlign="right"
titleSize="xs"
title={
<EuiHealth color="success">
{' '}
<EuiI18nNumber value={agentStatus?.online ?? 0} />
</EuiHealth>
}
description={i18n.translate('xpack.ingestManager.agentListStatus.onlineLabel', {
defaultMessage: 'Online',
})}
/>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiStat
textAlign="right"
titleSize="xs"
title={<EuiI18nNumber value={agentStatus?.offline ?? 0} />}
description={i18n.translate('xpack.ingestManager.agentListStatus.offlineLabel', {
defaultMessage: 'Offline',
})}
/>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiStat
textAlign="right"
titleSize="xs"
title={<EuiI18nNumber value={agentStatus?.error ?? 0} />}
description={i18n.translate('xpack.ingestManager.agentListStatus.errorLabel', {
defaultMessage: 'Error',
})}
/>
</EuiFlexItem>
{hasWriteCapabilites && (
<>
<EuiFlexItem grow={false}>
<Divider />
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiButton fill iconType="plusInCircle" onClick={() => setIsEnrollmentFlyoutOpen(true)}>
<FormattedMessage
id="xpack.ingestManager.agentList.enrollButton"
defaultMessage="Enroll new agents"
/>
</EuiButton>
</EuiFlexItem>
</>
)}
</EuiFlexGroup>
);
const headerLeftColumn = (
<EuiFlexGroup direction="column" gutterSize="s">
<EuiFlexItem>
<EuiText>
<h1>
<FormattedMessage id="xpack.ingestManager.fleet.pageTitle" defaultMessage="Fleet" />
</h1>
</EuiText>
</EuiFlexItem>
<EuiFlexItem>
<EuiText color="subdued">
<p>
<FormattedMessage
id="xpack.ingestManager.fleet.pageSubtitle"
defaultMessage="Manage and deploy configuration updates to a group of agents of any size."
/>
</p>
</EuiText>
</EuiFlexItem>
</EuiFlexGroup>
);

return (
<WithHeaderLayout
leftColumn={headerLeftColumn}
rightColumn={headerRightColumn}
tabs={[
{
id: 'agents',
name: 'Agents',
isSelected: true,
},
{
id: 'enrollment_keys',
name: 'Enrollment keys',
},
]}
>
<>
{isEnrollmentFlyoutOpen ? (
<AgentEnrollmentFlyout
agentConfigs={agentConfigs}
onClose={() => setIsEnrollmentFlyoutOpen(false)}
/>
) : null}
<EuiTitle size="l">
<h1>
<FormattedMessage id="xpack.ingestManager.agentList.pageTitle" defaultMessage="Agents" />
</h1>
</EuiTitle>
<EuiSpacer size="s" />
<EuiFlexGroup alignItems={'center'} justifyContent={'spaceBetween'}>
<EuiFlexItem grow={false}>
<EuiTitle size="s">
<EuiText color="subdued">
<FormattedMessage
id="xpack.ingestManager.agentList.pageDescription"
defaultMessage="Use agents to faciliate data collection for your Elastic stack."
/>
</EuiText>
</EuiTitle>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiSwitch
label={i18n.translate('xpack.ingestManager.agentList.showInactiveSwitchLabel', {
defaultMessage: 'Show inactive agents',
})}
checked={showInactive}
onChange={() => setShowInactive(!showInactive)}
/>
</EuiFlexItem>
</EuiFlexGroup>
<EuiSpacer size="m" />

<EuiFlexGroup alignItems={'center'}>
{selectedAgents.length ? (
<EuiFlexItem>
Expand Down Expand Up @@ -591,7 +433,7 @@ export const AgentListPage: React.FunctionComponent<{}> = () => {
) : null}
<EuiFlexItem grow={4}>
<EuiFlexGroup gutterSize="s">
<EuiFlexItem grow={3}>
<EuiFlexItem grow={6}>
<SearchBar
value={search}
onChange={newSearch => {
Expand All @@ -604,7 +446,7 @@ export const AgentListPage: React.FunctionComponent<{}> = () => {
fieldPrefix="agents"
/>
</EuiFlexItem>
<EuiFlexItem grow={1}>
<EuiFlexItem grow={2}>
<EuiFilterGroup>
<EuiPopover
ownFocus
Expand Down Expand Up @@ -685,6 +527,15 @@ export const AgentListPage: React.FunctionComponent<{}> = () => {
))}
</div>
</EuiPopover>
<EuiFilterButton
hasActiveFilters={showInactive}
onClick={() => setShowInactive(!showInactive)}
>
<FormattedMessage
id="xpack.ingestManager.agentList.showInactiveSwitchLabel"
defaultMessage="Show inactive"
/>
</EuiFilterButton>
</EuiFilterGroup>
</EuiFlexItem>
</EuiFlexGroup>
Expand Down Expand Up @@ -747,6 +598,6 @@ export const AgentListPage: React.FunctionComponent<{}> = () => {
setPagination(newPagination);
}}
/>
</WithHeaderLayout>
</>
);
};
Loading