Skip to content

Commit

Permalink
[7.x] [Logs UI] Reimplement log source configuration routes in plain …
Browse files Browse the repository at this point in the history
…HTTP+JSON (#64021) (#64626)

Backports the following commits to 7.x:
 - [Logs UI] Reimplement log source configuration routes in plain HTTP+JSON (#64021)
  • Loading branch information
weltenwort authored Apr 28, 2020
1 parent 9c969e7 commit 4778517
Show file tree
Hide file tree
Showing 47 changed files with 2,340 additions and 95 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

import * as rt from 'io-ts';
import { badRequestErrorRT, forbiddenErrorRT, routeTimingMetadataRT } from '../shared';
import { logSourceConfigurationRT } from './log_source_configuration';

/**
* request
*/

export const getLogSourceConfigurationRequestParamsRT = rt.type({
// the id of the source configuration
sourceId: rt.string,
});

export type GetLogSourceConfigurationRequestParams = rt.TypeOf<
typeof getLogSourceConfigurationRequestParamsRT
>;

/**
* response
*/

export const getLogSourceConfigurationSuccessResponsePayloadRT = rt.intersection([
rt.type({
data: logSourceConfigurationRT,
}),
rt.partial({
timing: routeTimingMetadataRT,
}),
]);

export type GetLogSourceConfigurationSuccessResponsePayload = rt.TypeOf<
typeof getLogSourceConfigurationSuccessResponsePayloadRT
>;

export const getLogSourceConfigurationErrorResponsePayloadRT = rt.union([
badRequestErrorRT,
forbiddenErrorRT,
]);

export type GetLogSourceConfigurationErrorReponsePayload = rt.TypeOf<
typeof getLogSourceConfigurationErrorResponsePayloadRT
>;

export const getLogSourceConfigurationResponsePayloadRT = rt.union([
getLogSourceConfigurationSuccessResponsePayloadRT,
getLogSourceConfigurationErrorResponsePayloadRT,
]);

export type GetLogSourceConfigurationReponsePayload = rt.TypeOf<
typeof getLogSourceConfigurationResponsePayloadRT
>;
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

import * as rt from 'io-ts';
import { routeTimingMetadataRT } from '../shared';
import {
getLogSourceConfigurationPath,
LOG_SOURCE_CONFIGURATION_PATH,
} from './log_source_configuration';

export const LOG_SOURCE_STATUS_PATH_SUFFIX = 'status';
export const LOG_SOURCE_STATUS_PATH = `${LOG_SOURCE_CONFIGURATION_PATH}/${LOG_SOURCE_STATUS_PATH_SUFFIX}`;
export const getLogSourceStatusPath = (sourceId: string) =>
`${getLogSourceConfigurationPath(sourceId)}/${LOG_SOURCE_STATUS_PATH_SUFFIX}`;

/**
* request
*/

export const getLogSourceStatusRequestParamsRT = rt.type({
// the id of the source configuration
sourceId: rt.string,
});

export type GetLogSourceStatusRequestParams = rt.TypeOf<typeof getLogSourceStatusRequestParamsRT>;

/**
* response
*/

const logIndexFieldRT = rt.strict({
name: rt.string,
type: rt.string,
searchable: rt.boolean,
aggregatable: rt.boolean,
});

export type LogIndexField = rt.TypeOf<typeof logIndexFieldRT>;

const logSourceStatusRT = rt.strict({
logIndexFields: rt.array(logIndexFieldRT),
logIndexNames: rt.array(rt.string),
});

export type LogSourceStatus = rt.TypeOf<typeof logSourceStatusRT>;

export const getLogSourceStatusSuccessResponsePayloadRT = rt.intersection([
rt.type({
data: logSourceStatusRT,
}),
rt.partial({
timing: routeTimingMetadataRT,
}),
]);

export type GetLogSourceStatusSuccessResponsePayload = rt.TypeOf<
typeof getLogSourceStatusSuccessResponsePayloadRT
>;
10 changes: 10 additions & 0 deletions x-pack/plugins/infra/common/http_api/log_sources/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;
* you may not use this file except in compliance with the Elastic License.
*/

export * from './get_log_source_configuration';
export * from './get_log_source_status';
export * from './log_source_configuration';
export * from './patch_log_source_configuration';
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

import * as rt from 'io-ts';

export const LOG_SOURCE_CONFIGURATION_PATH_PREFIX = '/api/infra/log_source_configurations';
export const LOG_SOURCE_CONFIGURATION_PATH = `${LOG_SOURCE_CONFIGURATION_PATH_PREFIX}/{sourceId}`;
export const getLogSourceConfigurationPath = (sourceId: string) =>
`${LOG_SOURCE_CONFIGURATION_PATH_PREFIX}/${sourceId}`;

export const logSourceConfigurationOriginRT = rt.keyof({
fallback: null,
internal: null,
stored: null,
});

export type LogSourceConfigurationOrigin = rt.TypeOf<typeof logSourceConfigurationOriginRT>;

const logSourceFieldsConfigurationRT = rt.strict({
timestamp: rt.string,
tiebreaker: rt.string,
});

const logSourceCommonColumnConfigurationRT = rt.strict({
id: rt.string,
});

const logSourceTimestampColumnConfigurationRT = rt.strict({
timestampColumn: logSourceCommonColumnConfigurationRT,
});

const logSourceMessageColumnConfigurationRT = rt.strict({
messageColumn: logSourceCommonColumnConfigurationRT,
});

const logSourceFieldColumnConfigurationRT = rt.strict({
fieldColumn: rt.intersection([
logSourceCommonColumnConfigurationRT,
rt.strict({
field: rt.string,
}),
]),
});

const logSourceColumnConfigurationRT = rt.union([
logSourceTimestampColumnConfigurationRT,
logSourceMessageColumnConfigurationRT,
logSourceFieldColumnConfigurationRT,
]);

export const logSourceConfigurationPropertiesRT = rt.strict({
name: rt.string,
description: rt.string,
logAlias: rt.string,
fields: logSourceFieldsConfigurationRT,
logColumns: rt.array(logSourceColumnConfigurationRT),
});

export type LogSourceConfigurationProperties = rt.TypeOf<typeof logSourceConfigurationPropertiesRT>;

export const logSourceConfigurationRT = rt.exact(
rt.intersection([
rt.type({
id: rt.string,
origin: logSourceConfigurationOriginRT,
configuration: logSourceConfigurationPropertiesRT,
}),
rt.partial({
updatedAt: rt.number,
version: rt.string,
}),
])
);

export type LogSourceConfiguration = rt.TypeOf<typeof logSourceConfigurationRT>;
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

import * as rt from 'io-ts';
import { badRequestErrorRT, forbiddenErrorRT } from '../shared';
import { getLogSourceConfigurationSuccessResponsePayloadRT } from './get_log_source_configuration';
import { logSourceConfigurationPropertiesRT } from './log_source_configuration';

/**
* request
*/

export const patchLogSourceConfigurationRequestParamsRT = rt.type({
// the id of the source configuration
sourceId: rt.string,
});

export type PatchLogSourceConfigurationRequestParams = rt.TypeOf<
typeof patchLogSourceConfigurationRequestParamsRT
>;

const logSourceConfigurationProperiesPatchRT = rt.partial({
...logSourceConfigurationPropertiesRT.type.props,
fields: rt.partial(logSourceConfigurationPropertiesRT.type.props.fields.type.props),
});

export type LogSourceConfigurationPropertiesPatch = rt.TypeOf<
typeof logSourceConfigurationProperiesPatchRT
>;

export const patchLogSourceConfigurationRequestBodyRT = rt.type({
data: logSourceConfigurationProperiesPatchRT,
});

export type PatchLogSourceConfigurationRequestBody = rt.TypeOf<
typeof patchLogSourceConfigurationRequestBodyRT
>;

/**
* response
*/

export const patchLogSourceConfigurationSuccessResponsePayloadRT = getLogSourceConfigurationSuccessResponsePayloadRT;

export type PatchLogSourceConfigurationSuccessResponsePayload = rt.TypeOf<
typeof patchLogSourceConfigurationSuccessResponsePayloadRT
>;

export const patchLogSourceConfigurationResponsePayloadRT = rt.union([
patchLogSourceConfigurationSuccessResponsePayloadRT,
badRequestErrorRT,
forbiddenErrorRT,
]);

export type PatchLogSourceConfigurationReponsePayload = rt.TypeOf<
typeof patchLogSourceConfigurationResponsePayloadRT
>;
20 changes: 17 additions & 3 deletions x-pack/plugins/infra/common/runtime_types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { identity } from 'fp-ts/lib/function';
import { pipe } from 'fp-ts/lib/pipeable';
import { Errors, Type } from 'io-ts';
import { failure } from 'io-ts/lib/PathReporter';
import { RouteValidationFunction } from 'kibana/server';

type ErrorFactory = (message: string) => Error;

Expand All @@ -18,8 +19,21 @@ export const throwErrors = (createError: ErrorFactory) => (errors: Errors) => {
throw createError(failure(errors).join('\n'));
};

export const decodeOrThrow = <A, O, I>(
runtimeType: Type<A, O, I>,
export const decodeOrThrow = <DecodedValue, EncodedValue, InputValue>(
runtimeType: Type<DecodedValue, EncodedValue, InputValue>,
createError: ErrorFactory = createPlainError
) => (inputValue: I) =>
) => (inputValue: InputValue) =>
pipe(runtimeType.decode(inputValue), fold(throwErrors(createError), identity));

type ValdidationResult<Value> = ReturnType<RouteValidationFunction<Value>>;

export const createValidationFunction = <DecodedValue, EncodedValue, InputValue>(
runtimeType: Type<DecodedValue, EncodedValue, InputValue>
): RouteValidationFunction<DecodedValue> => (inputValue, { badRequest, ok }) =>
pipe(
runtimeType.decode(inputValue),
fold<Errors, DecodedValue, ValdidationResult<DecodedValue>>(
(errors: Errors) => badRequest(failure(errors).join('\n')),
(result: DecodedValue) => ok(result)
)
);
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@
* you may not use this file except in compliance with the Elastic License.
*/

export * from './input_fields';
export { SourceConfigurationSettings } from './source_configuration_settings';
export { ViewSourceConfigurationButton } from './view_source_configuration_button';
6 changes: 3 additions & 3 deletions x-pack/plugins/infra/public/containers/logs/log_flyout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ import createContainer from 'constate';
import { isString } from 'lodash';
import React, { useContext, useEffect, useMemo, useState } from 'react';

import { LogEntriesItem } from '../../../common/http_api';
import { UrlStateContainer } from '../../utils/url_state';
import { useTrackedPromise } from '../../utils/use_tracked_promise';
import { Source } from '../source';
import { fetchLogEntriesItem } from './log_entries/api/fetch_log_entries_item';
import { LogEntriesItem } from '../../../common/http_api';
import { useLogSourceContext } from './log_source';

export enum FlyoutVisibility {
hidden = 'hidden',
Expand All @@ -26,7 +26,7 @@ export interface FlyoutOptionsUrlState {
}

export const useLogFlyout = () => {
const { sourceId } = useContext(Source.Context);
const { sourceId } = useLogSourceContext();
const [flyoutVisible, setFlyoutVisibility] = useState<boolean>(false);
const [flyoutId, setFlyoutId] = useState<string | null>(null);
const [flyoutItem, setFlyoutItem] = useState<LogEntriesItem | null>(null);
Expand Down
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;
* you may not use this file except in compliance with the Elastic License.
*/

import {
getLogSourceConfigurationPath,
getLogSourceConfigurationSuccessResponsePayloadRT,
} from '../../../../../common/http_api/log_sources';
import { decodeOrThrow } from '../../../../../common/runtime_types';
import { npStart } from '../../../../legacy_singletons';

export const callFetchLogSourceConfigurationAPI = async (sourceId: string) => {
const response = await npStart.http.fetch(getLogSourceConfigurationPath(sourceId), {
method: 'GET',
});

return decodeOrThrow(getLogSourceConfigurationSuccessResponsePayloadRT)(response);
};
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;
* you may not use this file except in compliance with the Elastic License.
*/

import {
getLogSourceStatusPath,
getLogSourceStatusSuccessResponsePayloadRT,
} from '../../../../../common/http_api/log_sources';
import { decodeOrThrow } from '../../../../../common/runtime_types';
import { npStart } from '../../../../legacy_singletons';

export const callFetchLogSourceStatusAPI = async (sourceId: string) => {
const response = await npStart.http.fetch(getLogSourceStatusPath(sourceId), {
method: 'GET',
});

return decodeOrThrow(getLogSourceStatusSuccessResponsePayloadRT)(response);
};
Loading

0 comments on commit 4778517

Please sign in to comment.