Skip to content

Commit

Permalink
[Stack Monitoring] Convert setup routes to TypeScript (elastic#131265)
Browse files Browse the repository at this point in the history
  • Loading branch information
weltenwort authored May 20, 2022
1 parent 065ea3e commit ecca231
Show file tree
Hide file tree
Showing 43 changed files with 753 additions and 367 deletions.
34 changes: 34 additions & 0 deletions x-pack/plugins/infra/server/mocks.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
* 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 {
createLogViewsServiceSetupMock,
createLogViewsServiceStartMock,
} from './services/log_views/log_views_service.mock';
import { InfraPluginSetup, InfraPluginStart } from './types';

const createInfraSetupMock = () => {
const infraSetupMock: jest.Mocked<InfraPluginSetup> = {
defineInternalSourceConfiguration: jest.fn(),
logViews: createLogViewsServiceSetupMock(),
};

return infraSetupMock;
};

const createInfraStartMock = () => {
const infraStartMock: jest.Mocked<InfraPluginStart> = {
getMetricIndices: jest.fn(),
logViews: createLogViewsServiceStartMock(),
};
return infraStartMock;
};

export const infraPluginMock = {
createSetupContract: createInfraSetupMock,
createStartContract: createInfraStartMock,
};
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,11 @@
*/

import { createLogViewsClientMock } from './log_views_client.mock';
import { LogViewsServiceStart } from './types';
import { LogViewsServiceSetup, LogViewsServiceStart } from './types';

export const createLogViewsServiceSetupMock = (): jest.Mocked<LogViewsServiceSetup> => ({
defineInternalLogView: jest.fn(),
});

export const createLogViewsServiceStartMock = (): jest.Mocked<LogViewsServiceStart> => ({
getClient: jest.fn((_savedObjectsClient: any, _elasticsearchClient: any) =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,5 @@
* 2.0.
*/

export { clusterSetupStatusRoute } from './cluster_setup_status';
export { nodeSetupStatusRoute } from './node_setup_status';
export { disableElasticsearchInternalCollectionRoute } from './disable_elasticsearch_internal_collection';
export * from './post_cluster';
export * from './post_clusters';
29 changes: 29 additions & 0 deletions x-pack/plugins/monitoring/common/http_api/cluster/post_cluster.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
* 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 * as rt from 'io-ts';
import { ccsRT, clusterUuidRT, timeRangeRT } from '../shared';

export const postClusterRequestParamsRT = rt.type({
clusterUuid: clusterUuidRT,
});

export const postClusterRequestPayloadRT = rt.intersection([
rt.partial({
ccs: ccsRT,
}),
rt.type({
timeRange: timeRangeRT,
codePaths: rt.array(rt.string),
}),
]);

export type PostClusterRequestPayload = rt.TypeOf<typeof postClusterRequestPayloadRT>;

export const postClusterResponsePayloadRT = rt.type({
// TODO: add payload entries
});
20 changes: 20 additions & 0 deletions x-pack/plugins/monitoring/common/http_api/cluster/post_clusters.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/*
* 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 * as rt from 'io-ts';
import { timeRangeRT } from '../shared';

export const postClustersRequestPayloadRT = rt.type({
timeRange: timeRangeRT,
codePaths: rt.array(rt.string),
});

export type PostClustersRequestPayload = rt.TypeOf<typeof postClustersRequestPayloadRT>;

export const postClustersResponsePayloadRT = rt.type({
// TODO: add payload entries
});
10 changes: 10 additions & 0 deletions x-pack/plugins/monitoring/common/http_api/setup/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/*
* 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.
*/

export * from './post_cluster_setup_status';
export * from './post_node_setup_status';
export * from './post_disable_internal_collection';
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*
* 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 * as rt from 'io-ts';
import {
booleanFromStringRT,
ccsRT,
clusterUuidRT,
createLiteralValueFromUndefinedRT,
timeRangeRT,
} from '../shared';

export const postClusterSetupStatusRequestParamsRT = rt.partial({
clusterUuid: clusterUuidRT,
});

export const postClusterSetupStatusRequestQueryRT = rt.partial({
// This flag is not intended to be used in production. It was introduced
// as a way to ensure consistent API testing - the typical data source
// for API tests are archived data, where the cluster configuration and data
// are consistent from environment to environment. However, this endpoint
// also attempts to retrieve data from the running stack products (ES and Kibana)
// which will vary from environment to environment making it difficult
// to write tests against. Therefore, this flag exists and should only be used
// in our testing environment.
skipLiveData: rt.union([booleanFromStringRT, createLiteralValueFromUndefinedRT(false)]),
});

export const postClusterSetupStatusRequestPayloadRT = rt.partial({
ccs: ccsRT,
timeRange: timeRangeRT,
});

export type PostClusterSetupStatusRequestPayload = rt.TypeOf<
typeof postClusterSetupStatusRequestPayloadRT
>;

export const postClusterSetupStatusResponsePayloadRT = rt.type({
// TODO: add payload entries
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/*
* 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 * as rt from 'io-ts';
import { clusterUuidRT } from '../shared';

export const postDisableInternalCollectionRequestParamsRT = rt.partial({
// the cluster uuid seems to be required but never used
clusterUuid: clusterUuidRT,
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
* 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 * as rt from 'io-ts';
import {
booleanFromStringRT,
ccsRT,
createLiteralValueFromUndefinedRT,
timeRangeRT,
} from '../shared';

export const postNodeSetupStatusRequestParamsRT = rt.type({
nodeUuid: rt.string,
});

export const postNodeSetupStatusRequestQueryRT = rt.partial({
// This flag is not intended to be used in production. It was introduced
// as a way to ensure consistent API testing - the typical data source
// for API tests are archived data, where the cluster configuration and data
// are consistent from environment to environment. However, this endpoint
// also attempts to retrieve data from the running stack products (ES and Kibana)
// which will vary from environment to environment making it difficult
// to write tests against. Therefore, this flag exists and should only be used
// in our testing environment.
skipLiveData: rt.union([booleanFromStringRT, createLiteralValueFromUndefinedRT(false)]),
});

export const postNodeSetupStatusRequestPayloadRT = rt.partial({
ccs: ccsRT,
timeRange: timeRangeRT,
});

export type PostNodeSetupStatusRequestPayload = rt.TypeOf<
typeof postNodeSetupStatusRequestPayloadRT
>;

export const postNodeSetupStatusResponsePayloadRT = rt.type({
// TODO: add payload entries
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* 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 { either } from 'fp-ts';
import * as rt from 'io-ts';
import { createLiteralValueFromUndefinedRT } from './literal_value';

describe('LiteralValueFromUndefined runtime type', () => {
it('decodes undefined to a given literal value', () => {
expect(createLiteralValueFromUndefinedRT('SOME_VALUE').decode(undefined)).toEqual(
either.right('SOME_VALUE')
);
});

it('can be used to define default values when decoding', () => {
expect(
rt.union([rt.boolean, createLiteralValueFromUndefinedRT(true)]).decode(undefined)
).toEqual(either.right(true));
});

it('rejects other values', () => {
expect(
either.isLeft(createLiteralValueFromUndefinedRT('SOME_VALUE').decode('DEFINED'))
).toBeTruthy();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
* 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 { either } from 'fp-ts';
import { booleanFromStringRT } from './query_string_boolean';

describe('BooleanFromString runtime type', () => {
it('decodes string "true" to a boolean', () => {
expect(booleanFromStringRT.decode('true')).toEqual(either.right(true));
});

it('decodes string "false" to a boolean', () => {
expect(booleanFromStringRT.decode('false')).toEqual(either.right(false));
});

it('rejects other strings', () => {
expect(either.isLeft(booleanFromStringRT.decode('maybe'))).toBeTruthy();
});
});
19 changes: 11 additions & 8 deletions x-pack/plugins/monitoring/server/debug_logger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,33 +4,36 @@
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import { RouteMethod } from '@kbn/core/server';
import fs from 'fs';
import { MonitoringConfig } from './config';
import { RouteDependencies } from './types';
import { LegacyRequest, MonitoringCore, MonitoringRouteConfig, RouteDependencies } from './types';

export function decorateDebugServer(
_server: any,
server: MonitoringCore,
config: MonitoringConfig,
logger: RouteDependencies['logger']
) {
): MonitoringCore {
// bail if the proper config value is not set (extra protection)
if (!config.ui.debug_mode) {
return _server;
return server;
}

// create a debug logger that will either write to file (if debug_log_path exists) or log out via logger
const debugLog = createDebugLogger({ path: config.ui.debug_log_path, logger });

return {
// maintain the rest of _server untouched
..._server,
...server,
// TODO: replace any
route: (options: any) => {
route: <Params, Query, Body, Method extends RouteMethod>(
options: MonitoringRouteConfig<Params, Query, Body, Method>
) => {
const apiPath = options.path;
return _server.route({
return server.route({
...options,
// TODO: replace any
handler: async (req: any) => {
handler: async (req: LegacyRequest<Params, Query, Body>): Promise<any> => {
const { elasticsearch: cached } = req.server.plugins;
const apiRequestHeaders = req.headers;
req.server.plugins.elasticsearch = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,18 @@
*/

import { STANDALONE_CLUSTER_CLUSTER_UUID } from '../../../common/constants';
import { TimeRange } from '../../../common/http_api/shared';
import { ElasticsearchResponse } from '../../../common/types/es';
import { LegacyRequest, Cluster } from '../../types';
import { getNewIndexPatterns } from './get_index_patterns';
import { Globals } from '../../static_globals';
import { Cluster, LegacyRequest } from '../../types';
import { getNewIndexPatterns } from './get_index_patterns';

export interface FindSupportClusterRequestPayload {
timeRange: TimeRange;
}

async function findSupportedBasicLicenseCluster(
req: LegacyRequest,
req: LegacyRequest<unknown, unknown, FindSupportClusterRequestPayload>,
clusters: Cluster[],
ccs: string,
kibanaUuid: string,
Expand Down Expand Up @@ -53,7 +58,7 @@ async function findSupportedBasicLicenseCluster(
},
},
{ term: { 'kibana_stats.kibana.uuid': kibanaUuid } },
{ range: { timestamp: { gte, lte, format: 'strict_date_optional_time' } } },
{ range: { timestamp: { gte, lte, format: 'epoch_millis' } } },
],
},
},
Expand Down Expand Up @@ -86,7 +91,10 @@ async function findSupportedBasicLicenseCluster(
* Non-Basic license clusters and any cluster in a single-cluster environment
* are also flagged as supported in this method.
*/
export function flagSupportedClusters(req: LegacyRequest, ccs: string) {
export function flagSupportedClusters(
req: LegacyRequest<unknown, unknown, FindSupportClusterRequestPayload>,
ccs: string
) {
const serverLog = (message: string) => req.getLogger('supported-clusters').debug(message);
const flagAllSupported = (clusters: Cluster[]) => {
clusters.forEach((cluster) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
* 2.0.
*/

import { LegacyServer } from '../../types';
import { prefixIndexPatternWithCcs } from '../../../common/ccs_utils';
import {
INDEX_PATTERN_ELASTICSEARCH,
Expand All @@ -20,14 +19,13 @@ import {
INDEX_PATTERN_ENTERPRISE_SEARCH,
CCS_REMOTE_PATTERN,
} from '../../../common/constants';
import { MonitoringConfig } from '../..';
import { MonitoringConfig } from '../../config';

export function getIndexPatterns(
server: LegacyServer,
config: MonitoringConfig,
additionalPatterns: Record<string, string> = {},
ccs: string = CCS_REMOTE_PATTERN
) {
const config = server.config;
const esIndexPattern = prefixIndexPatternWithCcs(config, INDEX_PATTERN_ELASTICSEARCH, ccs);
const kbnIndexPattern = prefixIndexPatternWithCcs(config, INDEX_PATTERN_KIBANA, ccs);
const lsIndexPattern = prefixIndexPatternWithCcs(config, INDEX_PATTERN_LOGSTASH, ccs);
Expand Down
Loading

0 comments on commit ecca231

Please sign in to comment.