Skip to content

Commit

Permalink
[SecuritySolution][DataQualityDashboard] Migrate data quality dashboa…
Browse files Browse the repository at this point in the history
…rd APIs to versioned router (elastic#169037)

## Summary

elastic#168334
elastic#166271


Before:

<img width="2560" alt="Screenshot 2023-10-16 at 21 45 02"
src="https://github.com/elastic/kibana/assets/6295984/2945179a-fb5b-4946-8b51-4769d20ad30f">
<img width="2558" alt="Screenshot 2023-10-16 at 21 45 09"
src="https://github.com/elastic/kibana/assets/6295984/254e00dd-bee9-4325-b418-e7ee481dea5d">

After:

<img width="2546" alt="Screenshot 2023-10-16 at 22 41 31"
src="https://github.com/elastic/kibana/assets/6295984/166a99a0-6f28-453a-a785-1197508170b5">

---------

Co-authored-by: kibanamachine <[email protected]>
  • Loading branch information
2 people authored and hop-dev committed Oct 18, 2023
1 parent 36e5a13 commit d9ff342
Show file tree
Hide file tree
Showing 21 changed files with 285 additions and 167 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import type {
} from './types';

const EMPTY_INDEX_NAMES: string[] = [];
export const INTERNAL_API_VERSION = '1';

export const getIndexNames = ({
ilmExplain,
Expand Down Expand Up @@ -282,7 +283,7 @@ export const getSizeInBytes = ({
}: {
indexName: string;
stats: Record<string, IndicesStatsIndicesStats> | 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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
},
},
Expand All @@ -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,
},
},
Expand All @@ -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,
},
},
Expand Down Expand Up @@ -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,
},
},
Expand All @@ -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,
},
},
Expand All @@ -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,
},
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
},
},
Expand All @@ -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,
},
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -43,6 +44,7 @@ export const useIlmExplain = (pattern: string): UseIlmExplain => {
{
method: 'GET',
signal: abortController.signal,
version: INTERNAL_API_VERSION,
}
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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';

Expand All @@ -29,6 +30,7 @@ export async function fetchMappings({
{
method: 'GET',
signal: abortController.signal,
version: INTERNAL_API_VERSION,
}
);
} catch (e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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';

Expand Down Expand Up @@ -53,6 +54,7 @@ export const useStats = ({
const response = await httpFetch<Record<string, IndicesStatsIndicesStats>>(
`${STATS_ENDPOINT}/${encodedIndexName}`,
{
version: INTERNAL_API_VERSION,
method: 'GET',
signal: abortController.signal,
query,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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'];
Expand Down Expand Up @@ -406,6 +407,7 @@ describe('helpers', () => {
headers: { 'Content-Type': 'application/json' },
method: 'POST',
signal: abortController.signal,
version: INTERNAL_API_VERSION,
}
);
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Original file line number Diff line number Diff line change
Expand Up @@ -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<unknown, unknown, unknown, 'get' | 'post' | 'delete' | 'patch' | 'put'>;
config: AddVersionOpts<unknown, unknown, unknown>;
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<RouterMethod>;
versionConfig: AddVersionOpts<unknown, unknown, unknown>;
routeHandler: RequestHandler;
}

type RouterMethod = Extract<keyof IRouter, RouteMethod>;

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) });
Expand All @@ -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
Expand All @@ -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;
}
Expand Down
8 changes: 4 additions & 4 deletions x-pack/plugins/ecs_data_quality_dashboard/server/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {};
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
Expand All @@ -20,6 +21,8 @@ jest.mock('../lib', () => ({
describe('getILMExplainRoute route', () => {
let server: ReturnType<typeof serverMock.create>;
let { context } = requestContextMock.createTools();
let logger: MockedLogger;

const req = requestMock.create({
method: 'get',
path: GET_ILM_EXPLAIN,
Expand All @@ -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 () => {
Expand Down Expand Up @@ -91,11 +95,13 @@ describe('getILMExplainRoute route', () => {

describe('request validation', () => {
let server: ReturnType<typeof serverMock.create>;
let logger: MockedLogger;

beforeEach(() => {
server = serverMock.create();
logger = loggerMock.create();

getILMExplainRoute(server.router);
getILMExplainRoute(server.router, logger);
});

test('disallows invalid pattern', () => {
Expand Down
Loading

0 comments on commit d9ff342

Please sign in to comment.