diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/helpers.ts b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/helpers.ts index 2ebfec9a7f257..ba195f0de0e15 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/helpers.ts +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/helpers.ts @@ -27,6 +27,7 @@ import type { } from './types'; const EMPTY_INDEX_NAMES: string[] = []; +export const INTERNAL_API_VERSION = '1'; export const getIndexNames = ({ ilmExplain, @@ -282,7 +283,7 @@ export const getSizeInBytes = ({ }: { indexName: string; stats: Record | null; -}): number => (stats && stats[indexName]?.primaries?.store?.size_in_bytes) ?? 0; +}): number => (stats && stats[indexName]?.primaries?.store?.total_data_set_size_in_bytes) ?? 0; export const getTotalDocsCount = ({ indexNames, diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/mock/pattern_rollup/mock_auditbeat_pattern_rollup.ts b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/mock/pattern_rollup/mock_auditbeat_pattern_rollup.ts index 7c18523e44aa3..2f83f899dc0d2 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/mock/pattern_rollup/mock_auditbeat_pattern_rollup.ts +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/mock/pattern_rollup/mock_auditbeat_pattern_rollup.ts @@ -53,6 +53,7 @@ export const auditbeatNoResults: PatternRollup = { primaries: { store: { size_in_bytes: 18791790, + total_data_set_size_in_bytes: 18791790, reserved_in_bytes: 0, }, }, @@ -70,6 +71,7 @@ export const auditbeatNoResults: PatternRollup = { primaries: { store: { size_in_bytes: 247, + total_data_set_size_in_bytes: 247, reserved_in_bytes: 0, }, }, @@ -87,6 +89,7 @@ export const auditbeatNoResults: PatternRollup = { primaries: { store: { size_in_bytes: 28409, + total_data_set_size_in_bytes: 28409, reserved_in_bytes: 0, }, }, @@ -182,6 +185,7 @@ export const auditbeatWithAllResults: PatternRollup = { primaries: { store: { size_in_bytes: 18791790, + total_data_set_size_in_bytes: 18791790, reserved_in_bytes: 0, }, }, @@ -199,6 +203,7 @@ export const auditbeatWithAllResults: PatternRollup = { primaries: { store: { size_in_bytes: 247, + total_data_set_size_in_bytes: 247, reserved_in_bytes: 0, }, }, @@ -216,6 +221,7 @@ export const auditbeatWithAllResults: PatternRollup = { primaries: { store: { size_in_bytes: 28409, + total_data_set_size_in_bytes: 28409, reserved_in_bytes: 0, }, }, diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/mock/pattern_rollup/mock_packetbeat_pattern_rollup.ts b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/mock/pattern_rollup/mock_packetbeat_pattern_rollup.ts index b04c8bb87600a..369803a44a3dd 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/mock/pattern_rollup/mock_packetbeat_pattern_rollup.ts +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/mock/pattern_rollup/mock_packetbeat_pattern_rollup.ts @@ -51,6 +51,7 @@ export const packetbeatNoResults: PatternRollup = { primaries: { store: { size_in_bytes: 512194751, + total_data_set_size_in_bytes: 512194751, reserved_in_bytes: 0, }, }, @@ -68,6 +69,7 @@ export const packetbeatNoResults: PatternRollup = { primaries: { store: { size_in_bytes: 584326147, + total_data_set_size_in_bytes: 584326147, reserved_in_bytes: 0, }, }, diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/use_ilm_explain/index.tsx b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/use_ilm_explain/index.tsx index ae643745bd805..4e95549338874 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/use_ilm_explain/index.tsx +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/use_ilm_explain/index.tsx @@ -9,6 +9,7 @@ import type { IlmExplainLifecycleLifecycleExplain } from '@elastic/elasticsearch import { useEffect, useState } from 'react'; import { useDataQualityContext } from '../data_quality_panel/data_quality_context'; +import { INTERNAL_API_VERSION } from '../helpers'; import * as i18n from '../translations'; const ILM_EXPLAIN_ENDPOINT = '/internal/ecs_data_quality_dashboard/ilm_explain'; @@ -43,6 +44,7 @@ export const useIlmExplain = (pattern: string): UseIlmExplain => { { method: 'GET', signal: abortController.signal, + version: INTERNAL_API_VERSION, } ); diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/use_mappings/helpers.ts b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/use_mappings/helpers.ts index 8aab64729df2f..809f543c0c0ae 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/use_mappings/helpers.ts +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/use_mappings/helpers.ts @@ -9,6 +9,7 @@ import type { HttpHandler } from '@kbn/core-http-browser'; import type { IndicesGetMappingIndexMappingRecord } from '@elastic/elasticsearch/lib/api/types'; import * as i18n from '../translations'; +import { INTERNAL_API_VERSION } from '../helpers'; export const MAPPINGS_API_ROUTE = '/internal/ecs_data_quality_dashboard/mappings'; @@ -29,6 +30,7 @@ export async function fetchMappings({ { method: 'GET', signal: abortController.signal, + version: INTERNAL_API_VERSION, } ); } catch (e) { diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/use_stats/index.tsx b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/use_stats/index.tsx index 6875dad3d4dfc..fce940de15f75 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/use_stats/index.tsx +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/use_stats/index.tsx @@ -11,6 +11,7 @@ import { HttpFetchQuery } from '@kbn/core/public'; import { useDataQualityContext } from '../data_quality_panel/data_quality_context'; import * as i18n from '../translations'; +import { INTERNAL_API_VERSION } from '../helpers'; const STATS_ENDPOINT = '/internal/ecs_data_quality_dashboard/stats'; @@ -53,6 +54,7 @@ export const useStats = ({ const response = await httpFetch>( `${STATS_ENDPOINT}/${encodedIndexName}`, { + version: INTERNAL_API_VERSION, method: 'GET', signal: abortController.signal, query, diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/use_unallowed_values/helpers.test.ts b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/use_unallowed_values/helpers.test.ts index 7b0a77d9af564..cad285a4bc976 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/use_unallowed_values/helpers.test.ts +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/use_unallowed_values/helpers.test.ts @@ -15,6 +15,7 @@ import { } from './helpers'; import { mockUnallowedValuesResponse } from '../mock/unallowed_values/mock_unallowed_values'; import { UnallowedValueRequestItem, UnallowedValueSearchResult } from '../types'; +import { INTERNAL_API_VERSION } from '../helpers'; describe('helpers', () => { let originalFetch: typeof global['fetch']; @@ -406,6 +407,7 @@ describe('helpers', () => { headers: { 'Content-Type': 'application/json' }, method: 'POST', signal: abortController.signal, + version: INTERNAL_API_VERSION, } ); }); diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/use_unallowed_values/helpers.ts b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/use_unallowed_values/helpers.ts index 5a331e7e1b8da..a193456d4afa9 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/use_unallowed_values/helpers.ts +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/use_unallowed_values/helpers.ts @@ -6,6 +6,7 @@ */ import type { HttpHandler } from '@kbn/core-http-browser'; +import { INTERNAL_API_VERSION } from '../helpers'; import * as i18n from '../translations'; import type { Bucket, @@ -81,6 +82,7 @@ export async function fetchUnallowedValues({ headers: { 'Content-Type': 'application/json' }, method: 'POST', signal: abortController.signal, + version: INTERNAL_API_VERSION, }); } catch (e) { throw new Error( diff --git a/x-pack/plugins/ecs_data_quality_dashboard/common/constants.ts b/x-pack/plugins/ecs_data_quality_dashboard/common/constants.ts index 51455c071b519..52c734797f726 100755 --- a/x-pack/plugins/ecs_data_quality_dashboard/common/constants.ts +++ b/x-pack/plugins/ecs_data_quality_dashboard/common/constants.ts @@ -13,3 +13,4 @@ export const GET_INDEX_STATS = `${BASE_PATH}/stats/{pattern}`; export const GET_INDEX_MAPPINGS = `${BASE_PATH}/mappings/{pattern}`; export const GET_UNALLOWED_FIELD_VALUES = `${BASE_PATH}/unallowed_field_values`; export const GET_ILM_EXPLAIN = `${BASE_PATH}/ilm_explain/{pattern}`; +export const INTERNAL_API_VERSION = '1'; diff --git a/x-pack/plugins/ecs_data_quality_dashboard/server/__mocks__/server.ts b/x-pack/plugins/ecs_data_quality_dashboard/server/__mocks__/server.ts index 7ac44e1beedf1..913c226517ce3 100644 --- a/x-pack/plugins/ecs_data_quality_dashboard/server/__mocks__/server.ts +++ b/x-pack/plugins/ecs_data_quality_dashboard/server/__mocks__/server.ts @@ -5,35 +5,73 @@ * 2.0. */ import { httpServiceMock } from '@kbn/core/server/mocks'; -import type { RequestHandler, RouteConfig, KibanaRequest } from '@kbn/core/server'; +import type { IRouter, RouteMethod, RequestHandler, KibanaRequest } from '@kbn/core/server'; import type { RequestHandlerContext } from '@kbn/core-http-request-handler-context-server'; +import type { RouterMock } from '@kbn/core-http-router-server-mocks'; +import type { AddVersionOpts, VersionedRouteConfig } from '@kbn/core-http-server'; import { requestMock } from './request'; import { responseMock as responseFactoryMock } from './response'; import { requestContextMock } from './request_context'; import { responseAdapter } from './test_adapters'; +import { INTERNAL_API_VERSION } from '../../common/constants'; interface Route { - config: RouteConfig; + config: AddVersionOpts; handler: RequestHandler; } -const getRoute = (routerMock: MockServer['router']): Route => { - const routeCalls = [ - ...routerMock.get.mock.calls, - ...routerMock.post.mock.calls, - ...routerMock.put.mock.calls, - ...routerMock.patch.mock.calls, - ...routerMock.delete.mock.calls, +interface RegisteredVersionedRoute { + routeConfig: VersionedRouteConfig; + versionConfig: AddVersionOpts; + routeHandler: RequestHandler; +} + +type RouterMethod = Extract; + +export const getRegisteredVersionedRouteMock = ( + routerMock: RouterMock, + method: RouterMethod, + path: string, + version: string +): RegisteredVersionedRoute => { + const route = routerMock.versioned.getRoute(method, path); + const routeVersion = route.versions[version]; + + if (!routeVersion) { + throw new Error(`Handler for [${method}][${path}] with version [${version}] no found!`); + } + + return { + routeConfig: route.config, + versionConfig: routeVersion.config, + routeHandler: routeVersion.handler, + }; +}; + +const getRoute = (routerMock: MockServer['router'], request: KibanaRequest): Route => { + const versionedRouteCalls = [ + ...routerMock.versioned.get.mock.calls, + ...routerMock.versioned.post.mock.calls, + ...routerMock.versioned.put.mock.calls, + ...routerMock.versioned.patch.mock.calls, + ...routerMock.versioned.delete.mock.calls, ]; - const [route] = routeCalls; - if (!route) { + const [versionedRoute] = versionedRouteCalls; + + if (!versionedRoute) { throw new Error('No route registered!'); } - const [config, handler] = route; - return { config, handler }; + const { routeHandler, versionConfig } = getRegisteredVersionedRouteMock( + routerMock, + request.route.method, + request.route.path, + INTERNAL_API_VERSION + ); + + return { config: versionConfig, handler: routeHandler }; }; const buildResultMock = () => ({ ok: jest.fn((x) => x), badRequest: jest.fn((x) => x) }); @@ -53,17 +91,19 @@ class MockServer { public async inject(request: KibanaRequest, context: RequestHandlerContext = this.contextMock) { const validatedRequest = this.validateRequest(request); + const [rejection] = this.resultMock.badRequest.mock.calls; if (rejection) { throw new Error(`Request was rejected with message: '${rejection}'`); } - await this.getRoute().handler(context, validatedRequest, this.responseMock); + await this.getRoute(validatedRequest).handler(context, validatedRequest, this.responseMock); + return responseAdapter(this.responseMock); } - private getRoute(): Route { - return getRoute(this.router); + private getRoute(request: KibanaRequest): Route { + return getRoute(this.router, request); } // eslint-disable-next-line @typescript-eslint/no-explicit-any @@ -72,7 +112,8 @@ class MockServer { } private validateRequest(request: KibanaRequest): KibanaRequest { - const validations = this.getRoute().config.validate; + const config = this.getRoute(request).config; + const validations = config.validate && config.validate?.request; if (!validations) { return request; } diff --git a/x-pack/plugins/ecs_data_quality_dashboard/server/plugin.ts b/x-pack/plugins/ecs_data_quality_dashboard/server/plugin.ts index d93766d2f3a7e..0c1cf336dc10d 100755 --- a/x-pack/plugins/ecs_data_quality_dashboard/server/plugin.ts +++ b/x-pack/plugins/ecs_data_quality_dashboard/server/plugin.ts @@ -29,10 +29,10 @@ export class EcsDataQualityDashboardPlugin const router = core.http.createRouter(); // this would be deleted when plugin is removed // Register server side APIs - getIndexMappingsRoute(router); - getIndexStatsRoute(router); - getUnallowedFieldValuesRoute(router); - getILMExplainRoute(router); + getIndexMappingsRoute(router, this.logger); + getIndexStatsRoute(router, this.logger); + getUnallowedFieldValuesRoute(router, this.logger); + getILMExplainRoute(router, this.logger); return {}; } diff --git a/x-pack/plugins/ecs_data_quality_dashboard/server/routes/get_ilm_explain.test.ts b/x-pack/plugins/ecs_data_quality_dashboard/server/routes/get_ilm_explain.test.ts index 737ddf781f1a9..329defab80c2b 100644 --- a/x-pack/plugins/ecs_data_quality_dashboard/server/routes/get_ilm_explain.test.ts +++ b/x-pack/plugins/ecs_data_quality_dashboard/server/routes/get_ilm_explain.test.ts @@ -12,6 +12,7 @@ import { serverMock } from '../__mocks__/server'; import { requestMock } from '../__mocks__/request'; import { requestContextMock } from '../__mocks__/request_context'; import { getILMExplainRoute } from './get_ilm_explain'; +import { loggerMock, MockedLogger } from '@kbn/logging-mocks'; jest.mock('../lib', () => ({ fetchILMExplain: jest.fn(), @@ -20,6 +21,8 @@ jest.mock('../lib', () => ({ describe('getILMExplainRoute route', () => { let server: ReturnType; let { context } = requestContextMock.createTools(); + let logger: MockedLogger; + const req = requestMock.create({ method: 'get', path: GET_ILM_EXPLAIN, @@ -32,9 +35,10 @@ describe('getILMExplainRoute route', () => { jest.clearAllMocks(); server = serverMock.create(); + logger = loggerMock.create(); ({ context } = requestContextMock.createTools()); - getILMExplainRoute(server.router); + getILMExplainRoute(server.router, logger); }); test('Returns index ilm information', async () => { @@ -91,11 +95,13 @@ describe('getILMExplainRoute route', () => { describe('request validation', () => { let server: ReturnType; + let logger: MockedLogger; beforeEach(() => { server = serverMock.create(); + logger = loggerMock.create(); - getILMExplainRoute(server.router); + getILMExplainRoute(server.router, logger); }); test('disallows invalid pattern', () => { diff --git a/x-pack/plugins/ecs_data_quality_dashboard/server/routes/get_ilm_explain.ts b/x-pack/plugins/ecs_data_quality_dashboard/server/routes/get_ilm_explain.ts index dab234eecaae7..c30271c62e313 100644 --- a/x-pack/plugins/ecs_data_quality_dashboard/server/routes/get_ilm_explain.ts +++ b/x-pack/plugins/ecs_data_quality_dashboard/server/routes/get_ilm_explain.ts @@ -5,41 +5,51 @@ * 2.0. */ -import { IRouter } from '@kbn/core/server'; +import { IRouter, Logger } from '@kbn/core/server'; import { transformError } from '@kbn/securitysolution-es-utils'; -import { GET_ILM_EXPLAIN } from '../../common/constants'; +import { GET_ILM_EXPLAIN, INTERNAL_API_VERSION } from '../../common/constants'; import { fetchILMExplain } from '../lib'; import { buildResponse } from '../lib/build_response'; import { buildRouteValidation } from '../schemas/common'; import { GetILMExplainParams } from '../schemas/get_ilm_explain'; -export const getILMExplainRoute = (router: IRouter) => { - router.get( - { +export const getILMExplainRoute = (router: IRouter, logger: Logger) => { + router.versioned + .get({ path: GET_ILM_EXPLAIN, - validate: { params: buildRouteValidation(GetILMExplainParams) }, - }, - async (context, request, response) => { - const resp = buildResponse(response); + access: 'internal', + }) + .addVersion( + { + version: INTERNAL_API_VERSION, + validate: { + request: { + params: buildRouteValidation(GetILMExplainParams), + }, + }, + }, + async (context, request, response) => { + const resp = buildResponse(response); - try { - const { client } = (await context.core).elasticsearch; - const decodedIndexName = decodeURIComponent(request.params.pattern); + try { + const { client } = (await context.core).elasticsearch; + const decodedIndexName = decodeURIComponent(request.params.pattern); - const ilmExplain = await fetchILMExplain(client, decodedIndexName); + const ilmExplain = await fetchILMExplain(client, decodedIndexName); - return response.ok({ - body: ilmExplain.indices, - }); - } catch (err) { - const error = transformError(err); + return response.ok({ + body: ilmExplain.indices, + }); + } catch (err) { + const error = transformError(err); - return resp.error({ - body: error.message, - statusCode: error.statusCode, - }); + logger.error(error.message); + return resp.error({ + body: error.message, + statusCode: error.statusCode, + }); + } } - } - ); + ); }; diff --git a/x-pack/plugins/ecs_data_quality_dashboard/server/routes/get_index_mappings.test.ts b/x-pack/plugins/ecs_data_quality_dashboard/server/routes/get_index_mappings.test.ts index 6c76c84396299..34ce98d4f9378 100644 --- a/x-pack/plugins/ecs_data_quality_dashboard/server/routes/get_index_mappings.test.ts +++ b/x-pack/plugins/ecs_data_quality_dashboard/server/routes/get_index_mappings.test.ts @@ -12,6 +12,7 @@ import { serverMock } from '../__mocks__/server'; import { requestMock } from '../__mocks__/request'; import { requestContextMock } from '../__mocks__/request_context'; import { getIndexMappingsRoute } from './get_index_mappings'; +import { loggerMock, MockedLogger } from '@kbn/logging-mocks'; jest.mock('../lib', () => ({ fetchMappings: jest.fn(), @@ -20,6 +21,8 @@ jest.mock('../lib', () => ({ describe('getIndexMappingsRoute route', () => { let server: ReturnType; let { context } = requestContextMock.createTools(); + let logger: MockedLogger; + const req = requestMock.create({ method: 'get', path: GET_INDEX_MAPPINGS, @@ -32,9 +35,11 @@ describe('getIndexMappingsRoute route', () => { jest.clearAllMocks(); server = serverMock.create(); + logger = loggerMock.create(); + ({ context } = requestContextMock.createTools()); - getIndexMappingsRoute(server.router); + getIndexMappingsRoute(server.router, logger); }); test('Returns index stats', async () => { @@ -58,11 +63,11 @@ describe('getIndexMappingsRoute route', () => { describe('request validation', () => { let server: ReturnType; - + let logger: MockedLogger; beforeEach(() => { server = serverMock.create(); - - getIndexMappingsRoute(server.router); + logger = loggerMock.create(); + getIndexMappingsRoute(server.router, logger); }); test('disallows invalid pattern', () => { diff --git a/x-pack/plugins/ecs_data_quality_dashboard/server/routes/get_index_mappings.ts b/x-pack/plugins/ecs_data_quality_dashboard/server/routes/get_index_mappings.ts index 8b81daebeec8d..c7ab5e1d4a790 100755 --- a/x-pack/plugins/ecs_data_quality_dashboard/server/routes/get_index_mappings.ts +++ b/x-pack/plugins/ecs_data_quality_dashboard/server/routes/get_index_mappings.ts @@ -5,41 +5,47 @@ * 2.0. */ -import { IRouter } from '@kbn/core/server'; +import { IRouter, Logger } from '@kbn/core/server'; import { transformError } from '@kbn/securitysolution-es-utils'; import { fetchMappings } from '../lib'; import { buildResponse } from '../lib/build_response'; -import { GET_INDEX_MAPPINGS } from '../../common/constants'; +import { GET_INDEX_MAPPINGS, INTERNAL_API_VERSION } from '../../common/constants'; import { GetIndexMappingsParams } from '../schemas/get_index_mappings'; import { buildRouteValidation } from '../schemas/common'; -export const getIndexMappingsRoute = (router: IRouter) => { - router.get( - { +export const getIndexMappingsRoute = (router: IRouter, logger: Logger) => { + router.versioned + .get({ path: GET_INDEX_MAPPINGS, - validate: { params: buildRouteValidation(GetIndexMappingsParams) }, - }, - async (context, request, response) => { - const resp = buildResponse(response); + access: 'internal', + }) + .addVersion( + { + version: INTERNAL_API_VERSION, + validate: { request: { params: buildRouteValidation(GetIndexMappingsParams) } }, + }, + async (context, request, response) => { + const resp = buildResponse(response); - try { - const { client } = (await context.core).elasticsearch; - const decodedIndexName = decodeURIComponent(request.params.pattern); + try { + const { client } = (await context.core).elasticsearch; + const decodedIndexName = decodeURIComponent(request.params.pattern); - const mappings = await fetchMappings(client, decodedIndexName); + const mappings = await fetchMappings(client, decodedIndexName); - return response.ok({ - body: mappings, - }); - } catch (err) { - const error = transformError(err); + return response.ok({ + body: mappings, + }); + } catch (err) { + const error = transformError(err); + logger.error(error.message); - return resp.error({ - body: error.message, - statusCode: error.statusCode, - }); + return resp.error({ + body: error.message, + statusCode: error.statusCode, + }); + } } - } - ); + ); }; diff --git a/x-pack/plugins/ecs_data_quality_dashboard/server/routes/get_index_stats.test.ts b/x-pack/plugins/ecs_data_quality_dashboard/server/routes/get_index_stats.test.ts index aa7fc306b47e8..e000809797a01 100644 --- a/x-pack/plugins/ecs_data_quality_dashboard/server/routes/get_index_stats.test.ts +++ b/x-pack/plugins/ecs_data_quality_dashboard/server/routes/get_index_stats.test.ts @@ -12,6 +12,7 @@ import { serverMock } from '../__mocks__/server'; import { requestMock } from '../__mocks__/request'; import { requestContextMock } from '../__mocks__/request_context'; import { getIndexStatsRoute } from './get_index_stats'; +import { loggerMock, MockedLogger } from '@kbn/logging-mocks'; jest.mock('../lib', () => ({ fetchStats: jest.fn(), @@ -21,6 +22,8 @@ jest.mock('../lib', () => ({ describe('getIndexStatsRoute route', () => { let server: ReturnType; let { context } = requestContextMock.createTools(); + let logger: MockedLogger; + const req = requestMock.create({ method: 'get', path: GET_INDEX_STATS, @@ -38,9 +41,11 @@ describe('getIndexStatsRoute route', () => { jest.clearAllMocks(); server = serverMock.create(); + logger = loggerMock.create(); + ({ context } = requestContextMock.createTools()); - getIndexStatsRoute(server.router); + getIndexStatsRoute(server.router, logger); }); test('Returns index stats', async () => { @@ -127,11 +132,13 @@ describe('getIndexStatsRoute route', () => { describe('request validation', () => { let server: ReturnType; + let logger: MockedLogger; beforeEach(() => { server = serverMock.create(); + logger = loggerMock.create(); - getIndexStatsRoute(server.router); + getIndexStatsRoute(server.router, logger); }); test('disallows invalid pattern', () => { diff --git a/x-pack/plugins/ecs_data_quality_dashboard/server/routes/get_index_stats.ts b/x-pack/plugins/ecs_data_quality_dashboard/server/routes/get_index_stats.ts index 839d21931a064..f98fa03c27523 100644 --- a/x-pack/plugins/ecs_data_quality_dashboard/server/routes/get_index_stats.ts +++ b/x-pack/plugins/ecs_data_quality_dashboard/server/routes/get_index_stats.ts @@ -5,87 +5,96 @@ * 2.0. */ import { i18n } from '@kbn/i18n'; -import { IRouter } from '@kbn/core/server'; +import { IRouter, Logger } from '@kbn/core/server'; import { transformError } from '@kbn/securitysolution-es-utils'; import { IndicesStatsIndicesStats } from '@elastic/elasticsearch/lib/api/types'; import { fetchStats, fetchAvailableIndices } from '../lib'; import { buildResponse } from '../lib/build_response'; -import { GET_INDEX_STATS } from '../../common/constants'; +import { GET_INDEX_STATS, INTERNAL_API_VERSION } from '../../common/constants'; import { buildRouteValidation } from '../schemas/common'; import { GetIndexStatsParams, GetIndexStatsQuery } from '../schemas/get_index_stats'; -export const getIndexStatsRoute = (router: IRouter) => { - router.get( - { +export const getIndexStatsRoute = (router: IRouter, logger: Logger) => { + router.versioned + .get({ path: GET_INDEX_STATS, - validate: { - params: buildRouteValidation(GetIndexStatsParams), - query: buildRouteValidation(GetIndexStatsQuery), + access: 'internal', + }) + .addVersion( + { + version: INTERNAL_API_VERSION, + validate: { + request: { + params: buildRouteValidation(GetIndexStatsParams), + query: buildRouteValidation(GetIndexStatsQuery), + }, + }, }, - }, - async (context, request, response) => { - const resp = buildResponse(response); + async (context, request, response) => { + const resp = buildResponse(response); - try { - const { client } = (await context.core).elasticsearch; - const esClient = client.asCurrentUser; + try { + const { client } = (await context.core).elasticsearch; + const esClient = client.asCurrentUser; - const decodedIndexName = decodeURIComponent(request.params.pattern); + const decodedIndexName = decodeURIComponent(request.params.pattern); - const stats = await fetchStats(client, decodedIndexName); - const { isILMAvailable, startDate, endDate } = request.query; + const stats = await fetchStats(client, decodedIndexName); + const { isILMAvailable, startDate, endDate } = request.query; - if (isILMAvailable === true) { - return response.ok({ - body: stats.indices, - }); - } + if (isILMAvailable === true) { + return response.ok({ + body: stats.indices, + }); + } - /** - * If ILM is not available, we need to fetch the available indices with the given date range. - * `fetchAvailableIndices` returns indices that have data in the given date range. - */ - if (startDate && endDate) { - const decodedStartDate = decodeURIComponent(startDate); - const decodedEndDate = decodeURIComponent(endDate); + /** + * If ILM is not available, we need to fetch the available indices with the given date range. + * `fetchAvailableIndices` returns indices that have data in the given date range. + */ + if (startDate && endDate) { + const decodedStartDate = decodeURIComponent(startDate); + const decodedEndDate = decodeURIComponent(endDate); - const indices = await fetchAvailableIndices(esClient, { - indexPattern: decodedIndexName, - startDate: decodedStartDate, - endDate: decodedEndDate, - }); - const availableIndices = indices?.aggregations?.index?.buckets?.reduce( - (acc: Record, { key }: { key: string }) => { - if (stats.indices?.[key]) { - acc[key] = stats.indices?.[key]; - } - return acc; - }, - {} - ); + const indices = await fetchAvailableIndices(esClient, { + indexPattern: decodedIndexName, + startDate: decodedStartDate, + endDate: decodedEndDate, + }); + const availableIndices = indices?.aggregations?.index?.buckets?.reduce( + (acc: Record, { key }: { key: string }) => { + if (stats.indices?.[key]) { + acc[key] = stats.indices?.[key]; + } + return acc; + }, + {} + ); + + return response.ok({ + body: availableIndices, + }); + } else { + return resp.error({ + body: i18n.translate( + 'xpack.ecsDataQualityDashboard.getIndexStats.dateRangeRequiredErrorMessage', + { + defaultMessage: 'startDate and endDate are required', + } + ), + statusCode: 400, + }); + } + } catch (err) { + const error = transformError(err); + logger.error(error.message); - return response.ok({ - body: availableIndices, - }); - } else { return resp.error({ - body: i18n.translate( - 'xpack.ecsDataQualityDashboard.getIndexStats.dateRangeRequiredErrorMessage', - { - defaultMessage: 'startDate and endDate are required', - } - ), - statusCode: 400, + body: error.message, + statusCode: error.statusCode, }); } - } catch (err) { - const error = transformError(err); - return resp.error({ - body: error.message, - statusCode: error.statusCode, - }); } - } - ); + ); }; diff --git a/x-pack/plugins/ecs_data_quality_dashboard/server/routes/get_unallowed_field_values.test.ts b/x-pack/plugins/ecs_data_quality_dashboard/server/routes/get_unallowed_field_values.test.ts index bb59356111699..fe18893acaec1 100644 --- a/x-pack/plugins/ecs_data_quality_dashboard/server/routes/get_unallowed_field_values.test.ts +++ b/x-pack/plugins/ecs_data_quality_dashboard/server/routes/get_unallowed_field_values.test.ts @@ -12,6 +12,7 @@ import { serverMock } from '../__mocks__/server'; import { requestMock } from '../__mocks__/request'; import { requestContextMock } from '../__mocks__/request_context'; import { getUnallowedFieldValuesRoute } from './get_unallowed_field_values'; +import { loggerMock, MockedLogger } from '@kbn/logging-mocks'; jest.mock('../lib', () => ({ getUnallowedFieldValues: jest.fn(), @@ -20,6 +21,8 @@ jest.mock('../lib', () => ({ describe('getUnallowedFieldValuesRoute route', () => { let server: ReturnType; let { context } = requestContextMock.createTools(); + let logger: MockedLogger; + const req = requestMock.create({ method: 'post', path: GET_UNALLOWED_FIELD_VALUES, @@ -37,8 +40,9 @@ describe('getUnallowedFieldValuesRoute route', () => { server = serverMock.create(); ({ context } = requestContextMock.createTools()); + logger = loggerMock.create(); - getUnallowedFieldValuesRoute(server.router); + getUnallowedFieldValuesRoute(server.router, logger); }); test('Returns unallowedValues', async () => { @@ -107,11 +111,13 @@ describe('getUnallowedFieldValuesRoute route', () => { describe('request validation', () => { let server: ReturnType; + let logger: MockedLogger; beforeEach(() => { server = serverMock.create(); + logger = loggerMock.create(); - getUnallowedFieldValuesRoute(server.router); + getUnallowedFieldValuesRoute(server.router, logger); }); test('disallows invalid pattern', () => { diff --git a/x-pack/plugins/ecs_data_quality_dashboard/server/routes/get_unallowed_field_values.ts b/x-pack/plugins/ecs_data_quality_dashboard/server/routes/get_unallowed_field_values.ts index be504a812e16b..db8887c2dfa66 100644 --- a/x-pack/plugins/ecs_data_quality_dashboard/server/routes/get_unallowed_field_values.ts +++ b/x-pack/plugins/ecs_data_quality_dashboard/server/routes/get_unallowed_field_values.ts @@ -5,40 +5,46 @@ * 2.0. */ -import { IRouter } from '@kbn/core/server'; +import { IRouter, Logger } from '@kbn/core/server'; import { transformError } from '@kbn/securitysolution-es-utils'; import { getUnallowedFieldValues } from '../lib'; import { buildResponse } from '../lib/build_response'; -import { GET_UNALLOWED_FIELD_VALUES } from '../../common/constants'; +import { GET_UNALLOWED_FIELD_VALUES, INTERNAL_API_VERSION } from '../../common/constants'; import { buildRouteValidation } from '../schemas/common'; import { GetUnallowedFieldValuesBody } from '../schemas/get_unallowed_field_values'; -export const getUnallowedFieldValuesRoute = (router: IRouter) => { - router.post( - { +export const getUnallowedFieldValuesRoute = (router: IRouter, logger: Logger) => { + router.versioned + .post({ path: GET_UNALLOWED_FIELD_VALUES, - validate: { body: buildRouteValidation(GetUnallowedFieldValuesBody) }, - }, - async (context, request, response) => { - const resp = buildResponse(response); - const esClient = (await context.core).elasticsearch.client.asCurrentUser; + access: 'internal', + }) + .addVersion( + { + version: INTERNAL_API_VERSION, + validate: { request: { body: buildRouteValidation(GetUnallowedFieldValuesBody) } }, + }, + async (context, request, response) => { + const resp = buildResponse(response); + const esClient = (await context.core).elasticsearch.client.asCurrentUser; - try { - const items = request.body; + try { + const items = request.body; - const { responses } = await getUnallowedFieldValues(esClient, items); - return response.ok({ - body: responses, - }); - } catch (err) { - const error = transformError(err); + const { responses } = await getUnallowedFieldValues(esClient, items); + return response.ok({ + body: responses, + }); + } catch (err) { + const error = transformError(err); + logger.error(error.message); - return resp.error({ - body: error.message, - statusCode: error.statusCode, - }); + return resp.error({ + body: error.message, + statusCode: error.statusCode, + }); + } } - } - ); + ); }; diff --git a/x-pack/plugins/ecs_data_quality_dashboard/server/schemas/common.ts b/x-pack/plugins/ecs_data_quality_dashboard/server/schemas/common.ts index 00e97a9326c5e..57dc45d4071f7 100644 --- a/x-pack/plugins/ecs_data_quality_dashboard/server/schemas/common.ts +++ b/x-pack/plugins/ecs_data_quality_dashboard/server/schemas/common.ts @@ -7,7 +7,7 @@ import { fold } from 'fp-ts/lib/Either'; import { pipe } from 'fp-ts/lib/pipeable'; -import type * as rt from 'io-ts'; +import * as rt from 'io-ts'; import { exactCheck, formatErrors } from '@kbn/securitysolution-io-ts-utils'; import type { RouteValidationFunction, diff --git a/x-pack/plugins/ecs_data_quality_dashboard/tsconfig.json b/x-pack/plugins/ecs_data_quality_dashboard/tsconfig.json index b5c1ad152b232..c0603ef91df6b 100644 --- a/x-pack/plugins/ecs_data_quality_dashboard/tsconfig.json +++ b/x-pack/plugins/ecs_data_quality_dashboard/tsconfig.json @@ -20,6 +20,8 @@ "@kbn/securitysolution-io-ts-utils", "@kbn/securitysolution-io-ts-types", "@kbn/i18n", + "@kbn/core-http-router-server-mocks", + "@kbn/logging-mocks", ], "exclude": [ "target/**/*",