mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 01:38:56 -04:00
[Asset management] Osquery app bug squashing (#102406)
* only display healthy agents to query * updated toasts to clear on update * null checking aggBuckets * properly display expired actions * clear the error toasts on success * review comments Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
parent
dd20b8adb6
commit
5e898734d5
20 changed files with 186 additions and 112 deletions
|
@ -36,6 +36,7 @@ const StyledEuiCard = styled(EuiCard)`
|
|||
|
||||
interface ActionResultsSummaryProps {
|
||||
actionId: string;
|
||||
expirationDate: Date;
|
||||
agentIds?: string[];
|
||||
isLive?: boolean;
|
||||
}
|
||||
|
@ -48,6 +49,7 @@ const renderErrorMessage = (error: string) => (
|
|||
|
||||
const ActionResultsSummaryComponent: React.FC<ActionResultsSummaryProps> = ({
|
||||
actionId,
|
||||
expirationDate,
|
||||
agentIds,
|
||||
isLive,
|
||||
}) => {
|
||||
|
@ -56,6 +58,7 @@ const ActionResultsSummaryComponent: React.FC<ActionResultsSummaryProps> = ({
|
|||
const [pageIndex, setPageIndex] = useState(0);
|
||||
// @ts-expect-error update types
|
||||
const [pageSize, setPageSize] = useState(50);
|
||||
const expired = useMemo(() => expirationDate < new Date(), [expirationDate]);
|
||||
const {
|
||||
// @ts-expect-error update types
|
||||
data: { aggregations, edges },
|
||||
|
@ -66,7 +69,7 @@ const ActionResultsSummaryComponent: React.FC<ActionResultsSummaryProps> = ({
|
|||
limit: pageSize,
|
||||
direction: Direction.asc,
|
||||
sortField: '@timestamp',
|
||||
isLive,
|
||||
isLive: !expired && isLive,
|
||||
});
|
||||
|
||||
const { data: logsResults } = useAllResults({
|
||||
|
@ -79,7 +82,7 @@ const ActionResultsSummaryComponent: React.FC<ActionResultsSummaryProps> = ({
|
|||
direction: Direction.asc,
|
||||
},
|
||||
],
|
||||
isLive,
|
||||
isLive: !expired && isLive,
|
||||
});
|
||||
|
||||
const notRespondedCount = useMemo(() => {
|
||||
|
@ -108,9 +111,13 @@ const ActionResultsSummaryComponent: React.FC<ActionResultsSummaryProps> = ({
|
|||
description: aggregations.successful,
|
||||
},
|
||||
{
|
||||
title: i18n.translate('xpack.osquery.liveQueryActionResults.summary.pendingLabelText', {
|
||||
defaultMessage: 'Not yet responded',
|
||||
}),
|
||||
title: expired
|
||||
? i18n.translate('xpack.osquery.liveQueryActionResults.summary.expiredLabelText', {
|
||||
defaultMessage: 'Expired',
|
||||
})
|
||||
: i18n.translate('xpack.osquery.liveQueryActionResults.summary.pendingLabelText', {
|
||||
defaultMessage: 'Not yet responded',
|
||||
}),
|
||||
description: notRespondedCount,
|
||||
},
|
||||
{
|
||||
|
@ -124,7 +131,7 @@ const ActionResultsSummaryComponent: React.FC<ActionResultsSummaryProps> = ({
|
|||
),
|
||||
},
|
||||
],
|
||||
[agentIds, aggregations.failed, aggregations.successful, notRespondedCount]
|
||||
[agentIds, aggregations.failed, aggregations.successful, notRespondedCount, expired]
|
||||
);
|
||||
|
||||
const renderAgentIdColumn = useCallback(
|
||||
|
@ -158,23 +165,30 @@ const ActionResultsSummaryComponent: React.FC<ActionResultsSummaryProps> = ({
|
|||
[logsResults]
|
||||
);
|
||||
|
||||
const renderStatusColumn = useCallback((_, item) => {
|
||||
if (!item.fields.completed_at) {
|
||||
return i18n.translate('xpack.osquery.liveQueryActionResults.table.pendingStatusText', {
|
||||
defaultMessage: 'pending',
|
||||
});
|
||||
}
|
||||
const renderStatusColumn = useCallback(
|
||||
(_, item) => {
|
||||
if (!item.fields.completed_at) {
|
||||
return expired
|
||||
? i18n.translate('xpack.osquery.liveQueryActionResults.table.expiredStatusText', {
|
||||
defaultMessage: 'expired',
|
||||
})
|
||||
: i18n.translate('xpack.osquery.liveQueryActionResults.table.pendingStatusText', {
|
||||
defaultMessage: 'pending',
|
||||
});
|
||||
}
|
||||
|
||||
if (item.fields['error.keyword']) {
|
||||
return i18n.translate('xpack.osquery.liveQueryActionResults.table.errorStatusText', {
|
||||
defaultMessage: 'error',
|
||||
});
|
||||
}
|
||||
if (item.fields['error.keyword']) {
|
||||
return i18n.translate('xpack.osquery.liveQueryActionResults.table.errorStatusText', {
|
||||
defaultMessage: 'error',
|
||||
});
|
||||
}
|
||||
|
||||
return i18n.translate('xpack.osquery.liveQueryActionResults.table.successStatusText', {
|
||||
defaultMessage: 'success',
|
||||
});
|
||||
}, []);
|
||||
return i18n.translate('xpack.osquery.liveQueryActionResults.table.successStatusText', {
|
||||
defaultMessage: 'success',
|
||||
});
|
||||
},
|
||||
[expired]
|
||||
);
|
||||
|
||||
const columns = useMemo(
|
||||
() => [
|
||||
|
@ -227,7 +241,7 @@ const ActionResultsSummaryComponent: React.FC<ActionResultsSummaryProps> = ({
|
|||
<EuiFlexGroup>
|
||||
<EuiFlexItem grow={false}>
|
||||
<StyledEuiCard title="" description="" textAlign="left">
|
||||
{notRespondedCount ? <EuiProgress size="xs" position="absolute" /> : null}
|
||||
{!expired && notRespondedCount ? <EuiProgress size="xs" position="absolute" /> : null}
|
||||
<EuiDescriptionList
|
||||
compressed
|
||||
textStyle="reverse"
|
||||
|
|
|
@ -23,6 +23,7 @@ import { ESTermQuery } from '../../common/typed_json';
|
|||
import { queryClient } from '../query_client';
|
||||
|
||||
import { generateTablePaginationOptions, getInspectResponse, InspectResponse } from './helpers';
|
||||
import { useErrorToast } from '../common/hooks/use_error_toast';
|
||||
|
||||
export interface ResultsArgs {
|
||||
results: ResultEdges;
|
||||
|
@ -56,10 +57,8 @@ export const useActionResults = ({
|
|||
skip = false,
|
||||
isLive = false,
|
||||
}: UseActionResults) => {
|
||||
const {
|
||||
data,
|
||||
notifications: { toasts },
|
||||
} = useKibana().services;
|
||||
const { data } = useKibana().services;
|
||||
const setErrorToast = useErrorToast();
|
||||
|
||||
return useQuery(
|
||||
['actionResults', { actionId }],
|
||||
|
@ -103,9 +102,9 @@ export const useActionResults = ({
|
|||
aggregations: {
|
||||
totalResponded,
|
||||
// @ts-expect-error update types
|
||||
successful: aggsBuckets.find((bucket) => bucket.key === 'success')?.doc_count ?? 0,
|
||||
successful: aggsBuckets?.find((bucket) => bucket.key === 'success')?.doc_count ?? 0,
|
||||
// @ts-expect-error update types
|
||||
failed: aggsBuckets.find((bucket) => bucket.key === 'error')?.doc_count ?? 0,
|
||||
failed: aggsBuckets?.find((bucket) => bucket.key === 'error')?.doc_count ?? 0,
|
||||
},
|
||||
inspect: getInspectResponse(responseData, {} as InspectResponse),
|
||||
};
|
||||
|
@ -124,8 +123,9 @@ export const useActionResults = ({
|
|||
refetchInterval: isLive ? 1000 : false,
|
||||
keepPreviousData: true,
|
||||
enabled: !skip && !!agentIds?.length,
|
||||
onSuccess: () => setErrorToast(),
|
||||
onError: (error: Error) =>
|
||||
toasts.addError(error, {
|
||||
setErrorToast(error, {
|
||||
title: i18n.translate('xpack.osquery.action_results.fetchError', {
|
||||
defaultMessage: 'Error while fetching action results',
|
||||
}),
|
||||
|
|
|
@ -18,6 +18,7 @@ import {
|
|||
import { ESTermQuery } from '../../common/typed_json';
|
||||
|
||||
import { getInspectResponse, InspectResponse } from './helpers';
|
||||
import { useErrorToast } from '../common/hooks/use_error_toast';
|
||||
|
||||
export interface ActionDetailsArgs {
|
||||
actionDetails: Record<string, string>;
|
||||
|
@ -33,10 +34,8 @@ interface UseActionDetails {
|
|||
}
|
||||
|
||||
export const useActionDetails = ({ actionId, filterQuery, skip = false }: UseActionDetails) => {
|
||||
const {
|
||||
data,
|
||||
notifications: { toasts },
|
||||
} = useKibana().services;
|
||||
const { data } = useKibana().services;
|
||||
const setErrorToast = useErrorToast();
|
||||
|
||||
return useQuery(
|
||||
['actionDetails', { actionId, filterQuery }],
|
||||
|
@ -61,8 +60,9 @@ export const useActionDetails = ({ actionId, filterQuery, skip = false }: UseAct
|
|||
},
|
||||
{
|
||||
enabled: !skip,
|
||||
onSuccess: () => setErrorToast(),
|
||||
onError: (error: Error) =>
|
||||
toasts.addError(error, {
|
||||
setErrorToast(error, {
|
||||
title: i18n.translate('xpack.osquery.action_details.fetchError', {
|
||||
defaultMessage: 'Error while fetching action details',
|
||||
}),
|
||||
|
|
|
@ -21,6 +21,7 @@ import {
|
|||
import { ESTermQuery } from '../../common/typed_json';
|
||||
|
||||
import { generateTablePaginationOptions, getInspectResponse, InspectResponse } from './helpers';
|
||||
import { useErrorToast } from '../common/hooks/use_error_toast';
|
||||
|
||||
export interface ActionsArgs {
|
||||
actions: ActionEdges;
|
||||
|
@ -48,10 +49,8 @@ export const useAllActions = ({
|
|||
filterQuery,
|
||||
skip = false,
|
||||
}: UseAllActions) => {
|
||||
const {
|
||||
data,
|
||||
notifications: { toasts },
|
||||
} = useKibana().services;
|
||||
const { data } = useKibana().services;
|
||||
const setErrorToast = useErrorToast();
|
||||
|
||||
return useQuery(
|
||||
['actions', { activePage, direction, limit, sortField }],
|
||||
|
@ -82,8 +81,9 @@ export const useAllActions = ({
|
|||
{
|
||||
keepPreviousData: true,
|
||||
enabled: !skip,
|
||||
onSuccess: () => setErrorToast(),
|
||||
onError: (error: Error) =>
|
||||
toasts.addError(error, {
|
||||
setErrorToast(error, {
|
||||
title: i18n.translate('xpack.osquery.all_actions.fetchError', {
|
||||
defaultMessage: 'Error while fetching actions',
|
||||
}),
|
||||
|
|
|
@ -14,12 +14,11 @@ import {
|
|||
GetAgentPoliciesResponse,
|
||||
GetAgentPoliciesResponseItem,
|
||||
} from '../../../fleet/common';
|
||||
import { useErrorToast } from '../common/hooks/use_error_toast';
|
||||
|
||||
export const useAgentPolicies = () => {
|
||||
const {
|
||||
http,
|
||||
notifications: { toasts },
|
||||
} = useKibana().services;
|
||||
const { http } = useKibana().services;
|
||||
const setErrorToast = useErrorToast();
|
||||
|
||||
return useQuery<GetAgentPoliciesResponse, unknown, GetAgentPoliciesResponseItem[]>(
|
||||
['agentPolicies'],
|
||||
|
@ -34,8 +33,9 @@ export const useAgentPolicies = () => {
|
|||
placeholderData: [],
|
||||
keepPreviousData: true,
|
||||
select: (response) => response.items,
|
||||
onSuccess: () => setErrorToast(),
|
||||
onError: (error) =>
|
||||
toasts.addError(error as Error, {
|
||||
setErrorToast(error as Error, {
|
||||
title: i18n.translate('xpack.osquery.agent_policies.fetchError', {
|
||||
defaultMessage: 'Error while fetching agent policies',
|
||||
}),
|
||||
|
|
|
@ -10,6 +10,7 @@ import { useQuery } from 'react-query';
|
|||
import { i18n } from '@kbn/i18n';
|
||||
import { useKibana } from '../common/lib/kibana';
|
||||
import { agentPolicyRouteService } from '../../../fleet/common';
|
||||
import { useErrorToast } from '../common/hooks/use_error_toast';
|
||||
|
||||
interface UseAgentPolicy {
|
||||
policyId: string;
|
||||
|
@ -17,10 +18,8 @@ interface UseAgentPolicy {
|
|||
}
|
||||
|
||||
export const useAgentPolicy = ({ policyId, skip }: UseAgentPolicy) => {
|
||||
const {
|
||||
http,
|
||||
notifications: { toasts },
|
||||
} = useKibana().services;
|
||||
const { http } = useKibana().services;
|
||||
const setErrorToast = useErrorToast();
|
||||
|
||||
return useQuery(
|
||||
['agentPolicy', { policyId }],
|
||||
|
@ -29,8 +28,9 @@ export const useAgentPolicy = ({ policyId, skip }: UseAgentPolicy) => {
|
|||
enabled: !skip,
|
||||
keepPreviousData: true,
|
||||
select: (response) => response.item,
|
||||
onSuccess: () => setErrorToast(),
|
||||
onError: (error: Error) =>
|
||||
toasts.addError(error, {
|
||||
setErrorToast(error, {
|
||||
title: i18n.translate('xpack.osquery.agent_policy_details.fetchError', {
|
||||
defaultMessage: 'Error while fetching agent policy details',
|
||||
}),
|
||||
|
|
|
@ -18,6 +18,7 @@ import {
|
|||
|
||||
import { generateTablePaginationOptions, processAggregations } from './helpers';
|
||||
import { Overlap, Group } from './types';
|
||||
import { useErrorToast } from '../common/hooks/use_error_toast';
|
||||
|
||||
interface UseAgentGroups {
|
||||
osqueryPolicies: string[];
|
||||
|
@ -25,10 +26,8 @@ interface UseAgentGroups {
|
|||
}
|
||||
|
||||
export const useAgentGroups = ({ osqueryPolicies, osqueryPoliciesLoading }: UseAgentGroups) => {
|
||||
const {
|
||||
data,
|
||||
notifications: { toasts },
|
||||
} = useKibana().services;
|
||||
const { data } = useKibana().services;
|
||||
const setErrorToast = useErrorToast();
|
||||
|
||||
const { agentPoliciesLoading, agentPolicyById } = useAgentPolicies(osqueryPolicies);
|
||||
const [platforms, setPlatforms] = useState<Group[]>([]);
|
||||
|
@ -100,8 +99,9 @@ export const useAgentGroups = ({ osqueryPolicies, osqueryPoliciesLoading }: UseA
|
|||
},
|
||||
{
|
||||
enabled: !osqueryPoliciesLoading && !agentPoliciesLoading,
|
||||
onSuccess: () => setErrorToast(),
|
||||
onError: (error) =>
|
||||
toasts.addError(error as Error, {
|
||||
setErrorToast(error as Error, {
|
||||
title: i18n.translate('xpack.osquery.agent_groups.fetchError', {
|
||||
defaultMessage: 'Error while fetching agent groups',
|
||||
}),
|
||||
|
|
|
@ -10,20 +10,20 @@ import { useQueries, UseQueryResult } from 'react-query';
|
|||
import { i18n } from '@kbn/i18n';
|
||||
import { useKibana } from '../common/lib/kibana';
|
||||
import { agentPolicyRouteService, GetOneAgentPolicyResponse } from '../../../fleet/common';
|
||||
import { useErrorToast } from '../common/hooks/use_error_toast';
|
||||
|
||||
export const useAgentPolicies = (policyIds: string[] = []) => {
|
||||
const {
|
||||
http,
|
||||
notifications: { toasts },
|
||||
} = useKibana().services;
|
||||
const { http } = useKibana().services;
|
||||
const setErrorToast = useErrorToast();
|
||||
|
||||
const agentResponse = useQueries(
|
||||
policyIds.map((policyId) => ({
|
||||
queryKey: ['agentPolicy', policyId],
|
||||
queryFn: () => http.get(agentPolicyRouteService.getInfoPath(policyId)),
|
||||
enabled: policyIds.length > 0,
|
||||
onSuccess: () => setErrorToast(),
|
||||
onError: (error) =>
|
||||
toasts.addError(error as Error, {
|
||||
setErrorToast(error as Error, {
|
||||
title: i18n.translate('xpack.osquery.action_policy_details.fetchError', {
|
||||
defaultMessage: 'Error while fetching policy details',
|
||||
}),
|
||||
|
|
|
@ -9,6 +9,7 @@ import { i18n } from '@kbn/i18n';
|
|||
import { useQuery } from 'react-query';
|
||||
|
||||
import { GetAgentStatusResponse, agentRouteService } from '../../../fleet/common';
|
||||
import { useErrorToast } from '../common/hooks/use_error_toast';
|
||||
import { useKibana } from '../common/lib/kibana';
|
||||
|
||||
interface UseAgentStatus {
|
||||
|
@ -17,10 +18,8 @@ interface UseAgentStatus {
|
|||
}
|
||||
|
||||
export const useAgentStatus = ({ policyId, skip }: UseAgentStatus) => {
|
||||
const {
|
||||
http,
|
||||
notifications: { toasts },
|
||||
} = useKibana().services;
|
||||
const { http } = useKibana().services;
|
||||
const setErrorToast = useErrorToast();
|
||||
|
||||
return useQuery<GetAgentStatusResponse, unknown, GetAgentStatusResponse['results']>(
|
||||
['agentStatus', policyId],
|
||||
|
@ -38,8 +37,9 @@ export const useAgentStatus = ({ policyId, skip }: UseAgentStatus) => {
|
|||
{
|
||||
enabled: !skip,
|
||||
select: (response) => response.results,
|
||||
onSuccess: () => setErrorToast(),
|
||||
onError: (error) =>
|
||||
toasts.addError(error as Error, {
|
||||
setErrorToast(error as Error, {
|
||||
title: i18n.translate('xpack.osquery.agent_status.fetchError', {
|
||||
defaultMessage: 'Error while fetching agent status',
|
||||
}),
|
||||
|
|
|
@ -9,6 +9,7 @@ import { i18n } from '@kbn/i18n';
|
|||
import { useQuery } from 'react-query';
|
||||
|
||||
import { GetAgentsResponse, agentRouteService } from '../../../fleet/common';
|
||||
import { useErrorToast } from '../common/hooks/use_error_toast';
|
||||
import { useKibana } from '../common/lib/kibana';
|
||||
|
||||
interface UseAllAgents {
|
||||
|
@ -28,36 +29,30 @@ export const useAllAgents = (
|
|||
opts: RequestOptions = { perPage: 9000 }
|
||||
) => {
|
||||
const { perPage } = opts;
|
||||
const {
|
||||
http,
|
||||
notifications: { toasts },
|
||||
} = useKibana().services;
|
||||
const { http } = useKibana().services;
|
||||
const setErrorToast = useErrorToast();
|
||||
const { isLoading: agentsLoading, data: agentData } = useQuery<GetAgentsResponse>(
|
||||
['agents', osqueryPolicies, searchValue, perPage],
|
||||
() => {
|
||||
const kueryFragments: string[] = [];
|
||||
if (osqueryPolicies.length) {
|
||||
kueryFragments.push(`${osqueryPolicies.map((p) => `policy_id:${p}`).join(' or ')}`);
|
||||
}
|
||||
const policyFragment = osqueryPolicies.map((p) => `policy_id:${p}`).join(' or ');
|
||||
let kuery = `last_checkin_status: online and (${policyFragment})`;
|
||||
|
||||
if (searchValue) {
|
||||
kueryFragments.push(
|
||||
`local_metadata.host.hostname:*${searchValue}* or local_metadata.elastic.agent.id:*${searchValue}*`
|
||||
);
|
||||
kuery += `and (local_metadata.host.hostname:*${searchValue}* or local_metadata.elastic.agent.id:*${searchValue}*)`;
|
||||
}
|
||||
|
||||
return http.get(agentRouteService.getListPath(), {
|
||||
query: {
|
||||
kuery: kueryFragments.map((frag) => `(${frag})`).join(' and '),
|
||||
kuery,
|
||||
perPage,
|
||||
showInactive: true,
|
||||
},
|
||||
});
|
||||
},
|
||||
{
|
||||
enabled: !osqueryPoliciesLoading,
|
||||
enabled: !osqueryPoliciesLoading && osqueryPolicies.length > 0,
|
||||
onSuccess: () => setErrorToast(),
|
||||
onError: (error) =>
|
||||
toasts.addError(error as Error, {
|
||||
setErrorToast(error as Error, {
|
||||
title: i18n.translate('xpack.osquery.agents.fetchError', {
|
||||
defaultMessage: 'Error while fetching agents',
|
||||
}),
|
||||
|
|
|
@ -12,12 +12,11 @@ import { i18n } from '@kbn/i18n';
|
|||
import { useKibana } from '../common/lib/kibana';
|
||||
import { packagePolicyRouteService, PACKAGE_POLICY_SAVED_OBJECT_TYPE } from '../../../fleet/common';
|
||||
import { OSQUERY_INTEGRATION_NAME } from '../../common';
|
||||
import { useErrorToast } from '../common/hooks/use_error_toast';
|
||||
|
||||
export const useOsqueryPolicies = () => {
|
||||
const {
|
||||
http,
|
||||
notifications: { toasts },
|
||||
} = useKibana().services;
|
||||
const { http } = useKibana().services;
|
||||
const setErrorToast = useErrorToast();
|
||||
|
||||
const { isLoading: osqueryPoliciesLoading, data: osqueryPolicies = [] } = useQuery(
|
||||
['osqueryPolicies'],
|
||||
|
@ -30,8 +29,9 @@ export const useOsqueryPolicies = () => {
|
|||
{
|
||||
select: (response) =>
|
||||
uniq<string>(response.items.map((p: { policy_id: string }) => p.policy_id)),
|
||||
onSuccess: () => setErrorToast(),
|
||||
onError: (error: Error) =>
|
||||
toasts.addError(error, {
|
||||
setErrorToast(error, {
|
||||
title: i18n.translate('xpack.osquery.osquery_policies.fetchError', {
|
||||
defaultMessage: 'Error while fetching osquery policies',
|
||||
}),
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* 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 { ErrorToastOptions, Toast } from 'kibana/public';
|
||||
import { useState } from 'react';
|
||||
import { useKibana } from '../../common/lib/kibana';
|
||||
|
||||
export const useErrorToast = () => {
|
||||
const [errorToast, setErrorToast] = useState<Toast>();
|
||||
const {
|
||||
notifications: { toasts },
|
||||
} = useKibana().services;
|
||||
return (error?: unknown, opts?: ErrorToastOptions) => {
|
||||
if (errorToast) {
|
||||
toasts.remove(errorToast);
|
||||
}
|
||||
if (error) {
|
||||
// @ts-expect-error update types
|
||||
setErrorToast(toasts.addError(error, opts));
|
||||
}
|
||||
};
|
||||
};
|
|
@ -12,12 +12,11 @@ import { useQuery } from 'react-query';
|
|||
import { GetPackagesResponse, epmRouteService } from '../../../../fleet/common';
|
||||
import { OSQUERY_INTEGRATION_NAME } from '../../../common';
|
||||
import { useKibana } from '../lib/kibana';
|
||||
import { useErrorToast } from './use_error_toast';
|
||||
|
||||
export const useOsqueryIntegration = () => {
|
||||
const {
|
||||
http,
|
||||
notifications: { toasts },
|
||||
} = useKibana().services;
|
||||
const { http } = useKibana().services;
|
||||
const setErrorToast = useErrorToast();
|
||||
|
||||
return useQuery(
|
||||
'integrations',
|
||||
|
@ -31,7 +30,7 @@ export const useOsqueryIntegration = () => {
|
|||
select: ({ response }: GetPackagesResponse) =>
|
||||
find(['name', OSQUERY_INTEGRATION_NAME], response),
|
||||
onError: (error: Error) =>
|
||||
toasts.addError(error, {
|
||||
setErrorToast(error, {
|
||||
title: i18n.translate('xpack.osquery.osquery_integration.fetchError', {
|
||||
defaultMessage: 'Error while fetching osquery integration',
|
||||
}),
|
||||
|
|
|
@ -19,6 +19,7 @@ import { useKibana } from '../../common/lib/kibana';
|
|||
import { ResultTabs } from '../../queries/edit/tabs';
|
||||
import { queryFieldValidation } from '../../common/validations';
|
||||
import { fieldValidators } from '../../shared_imports';
|
||||
import { useErrorToast } from '../../common/hooks/use_error_toast';
|
||||
|
||||
const FORM_ID = 'liveQueryForm';
|
||||
|
||||
|
@ -35,10 +36,9 @@ const LiveQueryFormComponent: React.FC<LiveQueryFormProps> = ({
|
|||
// onSubmit,
|
||||
onSuccess,
|
||||
}) => {
|
||||
const {
|
||||
http,
|
||||
notifications: { toasts },
|
||||
} = useKibana().services;
|
||||
const { http } = useKibana().services;
|
||||
|
||||
const setErrorToast = useErrorToast();
|
||||
|
||||
const {
|
||||
data,
|
||||
|
@ -53,14 +53,20 @@ const LiveQueryFormComponent: React.FC<LiveQueryFormProps> = ({
|
|||
body: JSON.stringify(payload),
|
||||
}),
|
||||
{
|
||||
onSuccess,
|
||||
onSuccess: () => {
|
||||
setErrorToast();
|
||||
if (onSuccess) {
|
||||
onSuccess();
|
||||
}
|
||||
},
|
||||
onError: (error) => {
|
||||
// @ts-expect-error update types
|
||||
toasts.addError(error, { title: error.body.error, toastMessage: error.body.message });
|
||||
setErrorToast(error);
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
const expirationDate = useMemo(() => new Date(data?.actions[0].expiration), [data?.actions]);
|
||||
|
||||
const formSchema = {
|
||||
query: {
|
||||
type: FIELD_TYPES.TEXT,
|
||||
|
@ -173,7 +179,12 @@ const LiveQueryFormComponent: React.FC<LiveQueryFormProps> = ({
|
|||
defaultMessage: 'Check results',
|
||||
}),
|
||||
children: actionId ? (
|
||||
<ResultTabs actionId={actionId} agentIds={agentIds} isLive={true} />
|
||||
<ResultTabs
|
||||
actionId={actionId}
|
||||
expirationDate={expirationDate}
|
||||
agentIds={agentIds}
|
||||
isLive={true}
|
||||
/>
|
||||
) : null,
|
||||
status: resultsStatus,
|
||||
},
|
||||
|
@ -185,6 +196,7 @@ const LiveQueryFormComponent: React.FC<LiveQueryFormProps> = ({
|
|||
queryComponentProps,
|
||||
queryStatus,
|
||||
queryValueProvided,
|
||||
expirationDate,
|
||||
resultsStatus,
|
||||
submit,
|
||||
]
|
||||
|
|
|
@ -14,6 +14,7 @@ import { ActionResultsSummary } from '../../action_results/action_results_summar
|
|||
interface ResultTabsProps {
|
||||
actionId: string;
|
||||
agentIds?: string[];
|
||||
expirationDate: Date;
|
||||
isLive?: boolean;
|
||||
startDate?: string;
|
||||
endDate?: string;
|
||||
|
@ -22,6 +23,7 @@ interface ResultTabsProps {
|
|||
const ResultTabsComponent: React.FC<ResultTabsProps> = ({
|
||||
actionId,
|
||||
agentIds,
|
||||
expirationDate,
|
||||
endDate,
|
||||
isLive,
|
||||
startDate,
|
||||
|
@ -34,7 +36,12 @@ const ResultTabsComponent: React.FC<ResultTabsProps> = ({
|
|||
content: (
|
||||
<>
|
||||
<EuiSpacer />
|
||||
<ActionResultsSummary actionId={actionId} agentIds={agentIds} isLive={isLive} />
|
||||
<ActionResultsSummary
|
||||
expirationDate={expirationDate}
|
||||
actionId={actionId}
|
||||
agentIds={agentIds}
|
||||
isLive={isLive}
|
||||
/>
|
||||
</>
|
||||
),
|
||||
},
|
||||
|
@ -55,7 +62,7 @@ const ResultTabsComponent: React.FC<ResultTabsProps> = ({
|
|||
),
|
||||
},
|
||||
],
|
||||
[actionId, agentIds, endDate, isLive, startDate]
|
||||
[actionId, agentIds, endDate, isLive, startDate, expirationDate]
|
||||
);
|
||||
|
||||
return (
|
||||
|
|
|
@ -21,6 +21,7 @@ import {
|
|||
import { ESTermQuery } from '../../common/typed_json';
|
||||
|
||||
import { generateTablePaginationOptions, getInspectResponse, InspectResponse } from './helpers';
|
||||
import { useErrorToast } from '../common/hooks/use_error_toast';
|
||||
|
||||
export interface ResultsArgs {
|
||||
results: ResultEdges;
|
||||
|
@ -50,10 +51,8 @@ export const useAllResults = ({
|
|||
skip = false,
|
||||
isLive = false,
|
||||
}: UseAllResults) => {
|
||||
const {
|
||||
data,
|
||||
notifications: { toasts },
|
||||
} = useKibana().services;
|
||||
const { data } = useKibana().services;
|
||||
const setErrorToast = useErrorToast();
|
||||
|
||||
return useQuery(
|
||||
['allActionResults', { actionId, activePage, limit, sort }],
|
||||
|
@ -81,8 +80,9 @@ export const useAllResults = ({
|
|||
{
|
||||
refetchInterval: isLive ? 1000 : false,
|
||||
enabled: !skip,
|
||||
onSuccess: () => setErrorToast(),
|
||||
onError: (error: Error) =>
|
||||
toasts.addError(error, {
|
||||
setErrorToast(error, {
|
||||
title: i18n.translate('xpack.osquery.results.fetchError', {
|
||||
defaultMessage: 'Error while fetching results',
|
||||
}),
|
||||
|
|
|
@ -43,6 +43,10 @@ const LiveQueryDetailsPageComponent = () => {
|
|||
const liveQueryListProps = useRouterNavigate('live_queries');
|
||||
|
||||
const { data } = useActionDetails({ actionId });
|
||||
const expirationDate = useMemo(() => new Date(data?.actionDetails._source.expiration), [
|
||||
data?.actionDetails,
|
||||
]);
|
||||
const expired = useMemo(() => expirationDate < new Date(), [expirationDate]);
|
||||
const { data: actionResultsData } = useActionResults({
|
||||
actionId,
|
||||
activePage: 0,
|
||||
|
@ -78,6 +82,18 @@ const LiveQueryDetailsPageComponent = () => {
|
|||
[liveQueryListProps]
|
||||
);
|
||||
|
||||
const failed = useMemo(() => {
|
||||
let result = actionResultsData?.aggregations.failed;
|
||||
if (expired) {
|
||||
result = '-';
|
||||
if (data?.actionDetails?.fields?.agents && actionResultsData?.aggregations) {
|
||||
result =
|
||||
data.actionDetails.fields.agents.length - actionResultsData.aggregations.successful;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}, [expired, actionResultsData?.aggregations, data?.actionDetails?.fields?.agents]);
|
||||
|
||||
const RightColumn = useMemo(
|
||||
() => (
|
||||
<EuiFlexGroup justifyContent="flexEnd" direction="row">
|
||||
|
@ -114,15 +130,13 @@ const LiveQueryDetailsPageComponent = () => {
|
|||
/>
|
||||
</EuiDescriptionListTitle>
|
||||
<EuiDescriptionListDescription className="eui-textNoWrap">
|
||||
<EuiTextColor color={actionResultsData?.aggregations.failed ? 'danger' : 'default'}>
|
||||
{actionResultsData?.aggregations.failed}
|
||||
</EuiTextColor>
|
||||
<EuiTextColor color={failed ? 'danger' : 'default'}>{failed}</EuiTextColor>
|
||||
</EuiDescriptionListDescription>
|
||||
</EuiDescriptionList>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
),
|
||||
[actionResultsData?.aggregations.failed, data?.actionDetails?.fields?.agents?.length]
|
||||
[data?.actionDetails?.fields?.agents?.length, failed]
|
||||
);
|
||||
|
||||
return (
|
||||
|
@ -133,6 +147,7 @@ const LiveQueryDetailsPageComponent = () => {
|
|||
<EuiSpacer />
|
||||
<ResultTabs
|
||||
actionId={actionId}
|
||||
expirationDate={expirationDate}
|
||||
agentIds={data?.actionDetails?.fields?.agents}
|
||||
startDate={get(data, ['actionDetails', 'fields', '@timestamp', '0'])}
|
||||
endDate={get(data, 'actionDetails.fields.expiration[0]')}
|
||||
|
|
|
@ -21,6 +21,7 @@ import { useKibana } from '../common/lib/kibana';
|
|||
import { useAgentStatus } from '../agents/use_agent_status';
|
||||
import { useAgentPolicy } from '../agent_policies/use_agent_policy';
|
||||
import { ConfirmDeployAgentPolicyModal } from './form/confirmation_modal';
|
||||
import { useErrorToast } from '../common/hooks/use_error_toast';
|
||||
|
||||
const StyledEuiLoadingSpinner = styled(EuiLoadingSpinner)`
|
||||
margin-right: ${({ theme }) => theme.eui.paddingSizes.s};
|
||||
|
@ -36,6 +37,7 @@ const ActiveStateSwitchComponent: React.FC<ActiveStateSwitchProps> = ({ item })
|
|||
http,
|
||||
notifications: { toasts },
|
||||
} = useKibana().services;
|
||||
const setErrorToast = useErrorToast();
|
||||
const [confirmationModal, setConfirmationModal] = useState(false);
|
||||
|
||||
const hideConfirmationModal = useCallback(() => setConfirmationModal(false), []);
|
||||
|
@ -51,6 +53,7 @@ const ActiveStateSwitchComponent: React.FC<ActiveStateSwitchProps> = ({ item })
|
|||
{
|
||||
onSuccess: (response) => {
|
||||
queryClient.invalidateQueries('scheduledQueries');
|
||||
setErrorToast();
|
||||
toasts.addSuccess(
|
||||
response.item.enabled
|
||||
? i18n.translate(
|
||||
|
@ -75,7 +78,7 @@ const ActiveStateSwitchComponent: React.FC<ActiveStateSwitchProps> = ({ item })
|
|||
},
|
||||
onError: (error) => {
|
||||
// @ts-expect-error update types
|
||||
toasts.addError(error, { title: error.body.error, toastMessage: error.body.message });
|
||||
setErrorToast(error, { title: error.body.error, toastMessage: error.body.message });
|
||||
},
|
||||
}
|
||||
);
|
||||
|
|
|
@ -45,6 +45,7 @@ import { PolicyIdComboBoxField } from './policy_id_combobox_field';
|
|||
import { QueriesField } from './queries_field';
|
||||
import { ConfirmDeployAgentPolicyModal } from './confirmation_modal';
|
||||
import { useAgentPolicies } from '../../agent_policies';
|
||||
import { useErrorToast } from '../../common/hooks/use_error_toast';
|
||||
|
||||
const GhostFormField = () => <></>;
|
||||
|
||||
|
@ -68,6 +69,7 @@ const ScheduledQueryGroupFormComponent: React.FC<ScheduledQueryGroupFormProps> =
|
|||
http,
|
||||
notifications: { toasts },
|
||||
} = useKibana().services;
|
||||
const setErrorToast = useErrorToast();
|
||||
const [showConfirmationModal, setShowConfirmationModal] = useState(false);
|
||||
const handleHideConfirmationModal = useCallback(() => setShowConfirmationModal(false), []);
|
||||
|
||||
|
@ -110,6 +112,7 @@ const ScheduledQueryGroupFormComponent: React.FC<ScheduledQueryGroupFormProps> =
|
|||
return;
|
||||
}
|
||||
|
||||
setErrorToast();
|
||||
navigateToApp(PLUGIN_ID, { path: `scheduled_query_groups/${data.item.id}` });
|
||||
toasts.addSuccess(
|
||||
i18n.translate('xpack.osquery.scheduledQueryGroup.form.updateSuccessToastMessageText', {
|
||||
|
@ -122,7 +125,7 @@ const ScheduledQueryGroupFormComponent: React.FC<ScheduledQueryGroupFormProps> =
|
|||
},
|
||||
onError: (error) => {
|
||||
// @ts-expect-error update types
|
||||
toasts.addError(error, { title: error.body.error, toastMessage: error.body.message });
|
||||
setErrorToast(error, { title: error.body.error, toastMessage: error.body.message });
|
||||
},
|
||||
}
|
||||
);
|
||||
|
|
|
@ -63,7 +63,7 @@ export const parseAgentSelection = async (
|
|||
perPage,
|
||||
page,
|
||||
kuery,
|
||||
showInactive: true,
|
||||
showInactive: false,
|
||||
});
|
||||
return { results: res.agents.map((agent) => agent.id), total: res.total };
|
||||
});
|
||||
|
@ -84,7 +84,7 @@ export const parseAgentSelection = async (
|
|||
perPage,
|
||||
page,
|
||||
kuery,
|
||||
showInactive: true,
|
||||
showInactive: false,
|
||||
});
|
||||
return { results: res.agents.map((agent) => agent.id), total: res.total };
|
||||
});
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue