Skip to content

Commit

Permalink
Merge branch 'main' into elastic#200545
Browse files Browse the repository at this point in the history
  • Loading branch information
alexwizp authored Nov 26, 2024
2 parents 284b155 + 430cc27 commit 1b51bc3
Show file tree
Hide file tree
Showing 56 changed files with 936 additions and 561 deletions.
2 changes: 1 addition & 1 deletion src/dev/build/tasks/os_packages/docker_generator/run.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ export async function runDockerGenerator(
*/
if (flags.baseImage === 'wolfi')
baseImageName =
'docker.elastic.co/wolfi/chainguard-base:latest@sha256:55b297da5151d2a2997e8ab9729fe1304e4869389d7090ab7031cc29530f69f8';
'docker.elastic.co/wolfi/chainguard-base:latest@sha256:32f06b169bb4b0f257fbb10e8c8379f06d3ee1355c89b3327cb623781a29590e';

let imageFlavor = '';
if (flags.baseImage === 'ubi') imageFlavor += `-ubi`;
Expand Down
1 change: 0 additions & 1 deletion x-pack/plugins/cases/common/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ export type {
CaseViewRefreshPropInterface,
CasesPermissions,
CasesCapabilities,
CasesStatus,
} from './ui/types';

export { CaseSeverity } from './types/domain';
Expand Down
6 changes: 6 additions & 0 deletions x-pack/plugins/cases/common/types/api/metrics/v1.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export enum CaseMetricsFeature {
CONNECTORS = 'connectors',
LIFESPAN = 'lifespan',
MTTR = 'mttr',
STATUS = 'status',
}

export const SingleCaseMetricsFeatureFieldRt = rt.union([
Expand All @@ -37,6 +38,7 @@ export const SingleCaseMetricsFeatureFieldRt = rt.union([
export const CasesMetricsFeatureFieldRt = rt.union([
SingleCaseMetricsFeatureFieldRt,
rt.literal(CaseMetricsFeature.MTTR),
rt.literal(CaseMetricsFeature.STATUS),
]);

const StatusInfoRt = rt.strict({
Expand Down Expand Up @@ -210,6 +212,10 @@ export const CasesMetricsResponseRt = rt.exact(
* The average resolve time of all cases in seconds
*/
mttr: rt.union([rt.number, rt.null]),
/**
* The number of total cases per status
*/
status: rt.strict({ open: rt.number, inProgress: rt.number, closed: rt.number }),
})
);

Expand Down
2 changes: 0 additions & 2 deletions x-pack/plugins/cases/common/ui/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ import type {
import type {
CasePatchRequest,
CasesFindResponse,
CasesStatusResponse,
CaseUserActionStatsResponse,
GetCaseConnectorsResponse,
GetCaseUsersResponse,
Expand Down Expand Up @@ -105,7 +104,6 @@ export type CasesUI = CaseUI[];
export type CasesFindResponseUI = Omit<SnakeToCamelCase<CasesFindResponse>, 'cases'> & {
cases: CasesUI;
};
export type CasesStatus = SnakeToCamelCase<CasesStatusResponse>;
export type CasesMetrics = SnakeToCamelCase<CasesMetricsResponse>;
export type CaseUpdateRequest = SnakeToCamelCase<CasePatchRequest>;
export type CaseConnectors = SnakeToCamelCase<GetCaseConnectorsResponse>;
Expand Down
12 changes: 3 additions & 9 deletions x-pack/plugins/cases/public/api/__mocks__/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,9 @@
*/

import type { HTTPService } from '..';
import { casesMetrics, casesStatus } from '../../containers/mock';
import type { CasesMetrics, CasesStatus } from '../../containers/types';
import type { CasesFindRequest, CasesMetricsRequest } from '../../../common/types/api';

export const getCasesStatus = async ({
http,
signal,
query,
}: HTTPService & { query: CasesFindRequest }): Promise<CasesStatus> => Promise.resolve(casesStatus);
import { casesMetrics } from '../../containers/mock';
import type { CasesMetrics } from '../../containers/types';
import type { CasesMetricsRequest } from '../../../common/types/api';

export const getCasesMetrics = async ({
http,
Expand Down
9 changes: 0 additions & 9 deletions x-pack/plugins/cases/public/api/decoders.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,11 @@ import { pipe } from 'fp-ts/lib/pipeable';

import type {
CasesFindResponse,
CasesStatusResponse,
CasesBulkGetResponse,
CasesMetricsResponse,
} from '../../common/types/api';
import {
CasesFindResponseRt,
CasesStatusResponseRt,
CasesBulkGetResponseRt,
CasesMetricsResponseRt,
} from '../../common/types/api';
Expand All @@ -26,13 +24,6 @@ import { throwErrors } from '../../common';

export const decodeCasesFindResponse = (respCases?: CasesFindResponse) =>
pipe(CasesFindResponseRt.decode(respCases), fold(throwErrors(createToasterPlainError), identity));

export const decodeCasesStatusResponse = (respCase?: CasesStatusResponse) =>
pipe(
CasesStatusResponseRt.decode(respCase),
fold(throwErrors(createToasterPlainError), identity)
);

export const decodeCasesMetricsResponse = (metrics?: CasesMetricsResponse) =>
pipe(
CasesMetricsResponseRt.decode(metrics),
Expand Down
19 changes: 1 addition & 18 deletions x-pack/plugins/cases/public/api/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,26 +9,22 @@ import type { HttpStart } from '@kbn/core/public';
import type {
CasesFindRequest,
CasesFindResponse,
CasesStatusRequest,
CasesStatusResponse,
CasesBulkGetRequest,
CasesBulkGetResponse,
CasesMetricsRequest,
CasesMetricsResponse,
} from '../../common/types/api';
import type { CasesStatus, CasesMetrics, CasesFindResponseUI } from '../../common/ui';
import type { CasesMetrics, CasesFindResponseUI } from '../../common/ui';
import {
CASE_FIND_URL,
INTERNAL_CASE_METRICS_URL,
CASE_STATUS_URL,
INTERNAL_BULK_GET_CASES_URL,
} from '../../common/constants';
import { convertAllCasesToCamel, convertToCamelCase } from './utils';
import {
decodeCasesBulkGetResponse,
decodeCasesFindResponse,
decodeCasesMetricsResponse,
decodeCasesStatusResponse,
} from './decoders';

export interface HTTPService {
Expand All @@ -45,19 +41,6 @@ export const getCases = async ({
return convertAllCasesToCamel(decodeCasesFindResponse(res));
};

export const getCasesStatus = async ({
http,
query,
signal,
}: HTTPService & { query: CasesStatusRequest }): Promise<CasesStatus> => {
const response = await http.get<CasesStatusResponse>(CASE_STATUS_URL, {
signal,
query,
});

return convertToCamelCase<CasesStatusResponse, CasesStatus>(decodeCasesStatusResponse(response));
};

export const getCasesMetrics = async ({
http,
signal,
Expand Down
7 changes: 2 additions & 5 deletions x-pack/plugins/cases/public/client/api/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,11 @@ import type {
CasesByAlertIDRequest,
GetRelatedCasesByAlertResponse,
CasesFindRequest,
CasesStatusRequest,
CasesMetricsRequest,
} from '../../../common/types/api';
import { getCasesFromAlertsUrl } from '../../../common/api';
import { bulkGetCases, getCases, getCasesMetrics, getCasesStatus } from '../../api';
import type { CasesFindResponseUI, CasesStatus, CasesMetrics } from '../../../common/ui';
import { bulkGetCases, getCases, getCasesMetrics } from '../../api';
import type { CasesFindResponseUI, CasesMetrics } from '../../../common/ui';
import type { CasesPublicStart } from '../../types';

export const createClientAPI = ({ http }: { http: HttpStart }): CasesPublicStart['api'] => {
Expand All @@ -28,8 +27,6 @@ export const createClientAPI = ({ http }: { http: HttpStart }): CasesPublicStart
cases: {
find: (query: CasesFindRequest, signal?: AbortSignal): Promise<CasesFindResponseUI> =>
getCases({ http, query, signal }),
getCasesStatus: (query: CasesStatusRequest, signal?: AbortSignal): Promise<CasesStatus> =>
getCasesStatus({ http, query, signal }),
getCasesMetrics: (query: CasesMetricsRequest, signal?: AbortSignal): Promise<CasesMetrics> =>
getCasesMetrics({ http, signal, query }),
bulkGet: (params, signal?: AbortSignal) => bulkGetCases({ http, signal, params }),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,27 +10,22 @@ import React from 'react';
import type { AppMockRenderer } from '../../common/mock';
import { createAppMockRenderer } from '../../common/mock';
import { useGetCasesMetrics } from '../../containers/use_get_cases_metrics';
import { useGetCasesStatus } from '../../containers/use_get_cases_status';
import { CasesMetrics } from './cases_metrics';

jest.mock('pretty-ms', () => jest.fn().mockReturnValue('2ms'));
jest.mock('../../containers/use_get_cases_metrics');
jest.mock('../../containers/use_get_cases_status');

const useGetCasesMetricsMock = useGetCasesMetrics as jest.Mock;
const useGetCasesStatusMock = useGetCasesStatus as jest.Mock;

describe('Cases metrics', () => {
let appMockRenderer: AppMockRenderer;

beforeEach(() => {
useGetCasesMetricsMock.mockReturnValue({ isLoading: false, data: { mttr: 2000 } });
useGetCasesStatusMock.mockReturnValue({
useGetCasesMetricsMock.mockReturnValue({
isLoading: false,
data: {
countOpenCases: 20,
countInProgressCases: 40,
countClosedCases: 130,
mttr: 2000,
status: { open: 20, inProgress: 40, closed: 130 },
},
});

Expand Down
25 changes: 8 additions & 17 deletions x-pack/plugins/cases/public/components/all_cases/cases_metrics.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,22 +17,13 @@ import {
} from '@elastic/eui';
import prettyMilliseconds from 'pretty-ms';
import { CaseStatuses } from '../../../common/types/domain';
import { useGetCasesStatus } from '../../containers/use_get_cases_status';
import { StatusStats } from '../status/status_stats';
import { useGetCasesMetrics } from '../../containers/use_get_cases_metrics';
import { ATTC_DESCRIPTION, ATTC_STAT, ATTC_STAT_INFO_ARIA_LABEL } from './translations';

export const CasesMetrics: React.FC = () => {
const {
data: { countOpenCases, countInProgressCases, countClosedCases } = {
countOpenCases: 0,
countInProgressCases: 0,
countClosedCases: 0,
},
isLoading: isCasesStatusLoading,
} = useGetCasesStatus();

const { data: { mttr } = { mttr: 0 }, isLoading: isCasesMetricsLoading } = useGetCasesMetrics();
const { data: { mttr, status } = { mttr: 0 }, isLoading: isCasesMetricsLoading } =
useGetCasesMetrics();

const mttrValue = useMemo(
() => (mttr != null ? prettyMilliseconds(mttr * 1000, { compact: true, verbose: false }) : '-'),
Expand All @@ -46,25 +37,25 @@ export const CasesMetrics: React.FC = () => {
<EuiFlexItem grow={true}>
<StatusStats
dataTestSubj="openStatsHeader"
caseCount={countOpenCases}
caseCount={status?.open ?? 0}
caseStatus={CaseStatuses.open}
isLoading={isCasesStatusLoading}
isLoading={isCasesMetricsLoading}
/>
</EuiFlexItem>
<EuiFlexItem grow={true}>
<StatusStats
dataTestSubj="inProgressStatsHeader"
caseCount={countInProgressCases}
caseCount={status?.inProgress ?? 0}
caseStatus={CaseStatuses['in-progress']}
isLoading={isCasesStatusLoading}
isLoading={isCasesMetricsLoading}
/>
</EuiFlexItem>
<EuiFlexItem grow={true}>
<StatusStats
dataTestSubj="closedStatsHeader"
caseCount={countClosedCases}
caseCount={status?.closed ?? 0}
caseStatus={CaseStatuses.closed}
isLoading={isCasesStatusLoading}
isLoading={isCasesMetricsLoading}
/>
</EuiFlexItem>
<EuiFlexItem grow={true}>
Expand Down
5 changes: 0 additions & 5 deletions x-pack/plugins/cases/public/containers/__mocks__/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import type {
CasesFindResponseUI,
CaseUI,
CasesUI,
CasesStatus,
FetchCasesProps,
FindCaseUserActions,
CaseUICustomField,
Expand All @@ -24,7 +23,6 @@ import {
basicCaseCommentPatch,
basicCasePost,
basicResolvedCase,
casesStatus,
pushedCase,
tags,
categories,
Expand Down Expand Up @@ -69,9 +67,6 @@ export const getSingleCaseMetrics = async (
signal: AbortSignal
): Promise<SingleCaseMetricsResponse> => Promise.resolve(basicCaseMetrics);

export const getCasesStatus = async (signal: AbortSignal): Promise<CasesStatus> =>
Promise.resolve(casesStatus);

export const getTags = async (signal: AbortSignal): Promise<string[]> => Promise.resolve(tags);

export const findAssignees = async (): Promise<UserProfile[]> => userProfiles;
Expand Down
36 changes: 0 additions & 36 deletions x-pack/plugins/cases/public/containers/api.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
* 2.0.
*/

import { httpServiceMock } from '@kbn/core/public/mocks';
import { BASE_RAC_ALERTS_API_PATH } from '@kbn/rule-registry-plugin/common';
import { KibanaServices } from '../common/lib/kibana';

Expand Down Expand Up @@ -51,13 +50,11 @@ import {
basicCaseSnake,
pushedCaseSnake,
categories,
casesStatus,
casesSnake,
cases,
pushedCase,
tags,
findCaseUserActionsResponse,
casesStatusSnake,
basicCaseId,
caseWithRegisteredAttachmentsSnake,
caseWithRegisteredAttachments,
Expand All @@ -69,7 +66,6 @@ import {
} from './mock';

import { DEFAULT_FILTER_OPTIONS, DEFAULT_QUERY_PARAMS } from './constants';
import { getCasesStatus } from '../api';
import { getCaseConnectorsMockResponse } from '../common/mock/connectors';
import { set } from '@kbn/safer-lodash-set';
import { cloneDeep, omit } from 'lodash';
Expand Down Expand Up @@ -531,38 +527,6 @@ describe('Cases API', () => {
});
});

describe('getCasesStatus', () => {
const http = httpServiceMock.createStartContract({ basePath: '' });
http.get.mockResolvedValue(casesStatusSnake);

beforeEach(() => {
fetchMock.mockClear();
});

it('should be called with correct check url, method, signal', async () => {
await getCasesStatus({
http,
signal: abortCtrl.signal,
query: { owner: [SECURITY_SOLUTION_OWNER] },
});

expect(http.get).toHaveBeenCalledWith(`${CASES_URL}/status`, {
signal: abortCtrl.signal,
query: { owner: [SECURITY_SOLUTION_OWNER] },
});
});

it('should return correct response', async () => {
const resp = await getCasesStatus({
http,
signal: abortCtrl.signal,
query: { owner: SECURITY_SOLUTION_OWNER },
});

expect(resp).toEqual(casesStatus);
});
});

describe('findCaseUserActions', () => {
const findCaseUserActionsSnake = {
page: 1,
Expand Down
Loading

0 comments on commit 1b51bc3

Please sign in to comment.