[Synthetics] Isolate Add/Edit API routes HTTP interface from SavedObject type (#162519)

Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
Co-authored-by: Shahzad <shahzad31comp@gmail.com>
This commit is contained in:
Abdul Wahab Zahid 2023-07-31 10:27:12 +02:00 committed by GitHub
parent 8749d5f006
commit d7e16b39f3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
27 changed files with 239 additions and 179 deletions

View file

@ -138,10 +138,16 @@ export type ManifestLocation = t.TypeOf<typeof ManifestLocationCodec>;
export type ServiceLocation = t.TypeOf<typeof ServiceLocationCodec>; export type ServiceLocation = t.TypeOf<typeof ServiceLocationCodec>;
export type ServiceLocations = t.TypeOf<typeof ServiceLocationsCodec>; export type ServiceLocations = t.TypeOf<typeof ServiceLocationsCodec>;
export type MonitorServiceLocation = t.TypeOf<typeof MonitorServiceLocationCodec>; export type MonitorServiceLocation = t.TypeOf<typeof MonitorServiceLocationCodec>;
export type MonitorServiceLocations = t.TypeOf<typeof MonitorServiceLocationsCodec>;
export type ServiceLocationsApiResponse = t.TypeOf<typeof ServiceLocationsApiResponseCodec>;
export type ServiceLocationErrors = t.TypeOf<typeof ServiceLocationErrors>; export type ServiceLocationErrors = t.TypeOf<typeof ServiceLocationErrors>;
export type ThrottlingOptions = t.TypeOf<typeof ThrottlingOptionsCodec>; export type ThrottlingOptions = t.TypeOf<typeof ThrottlingOptionsCodec>;
export type Locations = t.TypeOf<typeof LocationsCodec>; export type Locations = t.TypeOf<typeof LocationsCodec>;
export type PublicLocation = t.TypeOf<typeof PublicLocationCodec>; export type PublicLocation = t.TypeOf<typeof PublicLocationCodec>;
export type PublicLocations = t.TypeOf<typeof PublicLocationsCodec>; export type PublicLocations = t.TypeOf<typeof PublicLocationsCodec>;
export interface ServiceLocationErrorsResponse {
attributes: { message: string; errors: ServiceLocationErrors; id?: string };
}
// TODO: Remove if not needed
// export type MonitorServiceLocations = t.TypeOf<typeof MonitorServiceLocationsCodec>;
// export type ServiceLocationsApiResponse = t.TypeOf<typeof ServiceLocationsApiResponseCodec>;

View file

@ -12,13 +12,13 @@ import { useDispatch, useSelector } from 'react-redux';
import { useSyntheticsRefreshContext } from '../../contexts'; import { useSyntheticsRefreshContext } from '../../contexts';
import { cleanMonitorListState, selectServiceLocationsState } from '../../state'; import { cleanMonitorListState, selectServiceLocationsState } from '../../state';
import { showSyncErrors } from '../monitors_page/management/show_sync_errors'; import { showSyncErrors } from '../monitors_page/management/show_sync_errors';
import { createGettingStartedMonitor } from '../../state'; import { createGettingStartedMonitor, UpsertMonitorResponse } from '../../state';
import { DEFAULT_FIELDS } from '../../../../../common/constants/monitor_defaults'; import { DEFAULT_FIELDS } from '../../../../../common/constants/monitor_defaults';
import { ConfigKey } from '../../../../../common/constants/monitor_management'; import { ConfigKey } from '../../../../../common/constants/monitor_management';
import { import {
DataStream, DataStream,
EncryptedSyntheticsSavedMonitor,
ServiceLocationErrors, ServiceLocationErrors,
SyntheticsMonitorWithId,
} from '../../../../../common/runtime_types'; } from '../../../../../common/runtime_types';
import { import {
MONITOR_SUCCESS_LABEL, MONITOR_SUCCESS_LABEL,
@ -56,7 +56,7 @@ export const useSimpleMonitor = ({ monitorData }: { monitorData?: SimpleFormData
}, [monitorData]); }, [monitorData]);
useEffect(() => { useEffect(() => {
const newMonitor = data as SyntheticsMonitorWithId; const newMonitor = data as UpsertMonitorResponse;
const hasErrors = data && 'attributes' in data && data.attributes.errors?.length > 0; const hasErrors = data && 'attributes' in data && data.attributes.errors?.length > 0;
if (hasErrors && !loading) { if (hasErrors && !loading) {
showSyncErrors( showSyncErrors(
@ -71,7 +71,7 @@ export const useSimpleMonitor = ({ monitorData }: { monitorData?: SimpleFormData
title: MONITOR_FAILURE_LABEL, title: MONITOR_FAILURE_LABEL,
toastLifeTimeMs: 3000, toastLifeTimeMs: 3000,
}); });
} else if (!loading && newMonitor?.id) { } else if (!loading && (newMonitor as EncryptedSyntheticsSavedMonitor)?.id) {
kibanaService.toasts.addSuccess({ kibanaService.toasts.addSuccess({
title: MONITOR_SUCCESS_LABEL, title: MONITOR_SUCCESS_LABEL,
toastLifeTimeMs: 3000, toastLifeTimeMs: 3000,
@ -82,5 +82,5 @@ export const useSimpleMonitor = ({ monitorData }: { monitorData?: SimpleFormData
} }
}, [application, data, status, dispatch, loading, refreshApp, serviceLocations]); }, [application, data, status, dispatch, loading, refreshApp, serviceLocations]);
return { data: data as SyntheticsMonitorWithId, loading }; return { data: data as EncryptedSyntheticsSavedMonitor, loading };
}; };

View file

@ -24,10 +24,11 @@ export const MonitorDetailsPanelContainer = (props: Partial<MonitorDetailsPanelP
const { monitor, loading } = useSelectedMonitor(); const { monitor, loading } = useSelectedMonitor();
if ( const isPingRelevant =
(latestPing && latestPing?.config_id !== configId) || latestPing?.config_id === monitor?.[ConfigKey.CONFIG_ID] ||
(monitor && monitor[ConfigKey.CONFIG_ID] !== configId) latestPing?.monitor?.id === monitor?.[ConfigKey.MONITOR_QUERY_ID];
) {
if (!monitor || !isPingRelevant) {
return <EuiSkeletonText lines={6} />; return <EuiSkeletonText lines={6} />;
} }

View file

@ -9,7 +9,7 @@ import { useSelector } from 'react-redux';
import { useMemo } from 'react'; import { useMemo } from 'react';
import { useEsSearch } from '@kbn/observability-shared-plugin/public'; import { useEsSearch } from '@kbn/observability-shared-plugin/public';
import { selectEncryptedSyntheticsSavedMonitors } from '../../../state'; import { selectEncryptedSyntheticsSavedMonitors } from '../../../state';
import { Ping } from '../../../../../../common/runtime_types'; import { ConfigKey, Ping } from '../../../../../../common/runtime_types';
import { import {
EXCLUDE_RUN_ONCE_FILTER, EXCLUDE_RUN_ONCE_FILTER,
getTimeSpanFilter, getTimeSpanFilter,
@ -70,7 +70,7 @@ export function useInlineErrors({
const { lastRefresh } = useSyntheticsRefreshContext(); const { lastRefresh } = useSyntheticsRefreshContext();
const configIds = syntheticsMonitors.map((monitor) => monitor.id); const configIds = syntheticsMonitors.map((monitor) => monitor[ConfigKey.CONFIG_ID]);
const doFetch = configIds.length > 0 || onlyInvalidMonitors; const doFetch = configIds.length > 0 || onlyInvalidMonitors;

View file

@ -251,7 +251,7 @@ export function MonitorDetailFlyout(props: Props) {
const upsertSuccess = upsertStatus?.status === 'success'; const upsertSuccess = upsertStatus?.status === 'success';
const { const {
data: monitorSavedObject, data: monitorObject,
error, error,
status, status,
loading, loading,
@ -262,7 +262,7 @@ export function MonitorDetailFlyout(props: Props) {
const monitorDetail = useMonitorDetail(configId, props.location); const monitorDetail = useMonitorDetail(configId, props.location);
const { locations } = useStatusByLocation({ const { locations } = useStatusByLocation({
configId, configId,
monitorLocations: monitorSavedObject?.locations, monitorLocations: monitorObject?.locations,
}); });
const isOverlay = useIsWithinMaxBreakpoint('xl'); const isOverlay = useIsWithinMaxBreakpoint('xl');
@ -276,14 +276,14 @@ export function MonitorDetailFlyout(props: Props) {
> >
{status === FETCH_STATUS.FAILURE && <EuiErrorBoundary>{error?.message}</EuiErrorBoundary>} {status === FETCH_STATUS.FAILURE && <EuiErrorBoundary>{error?.message}</EuiErrorBoundary>}
{status === FETCH_STATUS.LOADING && <LoadingState />} {status === FETCH_STATUS.LOADING && <LoadingState />}
{status === FETCH_STATUS.SUCCESS && monitorSavedObject && ( {status === FETCH_STATUS.SUCCESS && monitorObject && (
<> <>
<EuiFlyoutHeader hasBorder> <EuiFlyoutHeader hasBorder>
<EuiPanel hasBorder={false} hasShadow={false} paddingSize="l"> <EuiPanel hasBorder={false} hasShadow={false} paddingSize="l">
<EuiFlexGroup responsive={false} gutterSize="s"> <EuiFlexGroup responsive={false} gutterSize="s">
<EuiFlexItem grow={false}> <EuiFlexItem grow={false}>
<EuiTitle size="s"> <EuiTitle size="s">
<h2>{monitorSavedObject?.[ConfigKey.NAME]}</h2> <h2>{monitorObject?.[ConfigKey.NAME]}</h2>
</EuiTitle> </EuiTitle>
</EuiFlexItem> </EuiFlexItem>
<EuiFlexItem grow={false}> <EuiFlexItem grow={false}>
@ -307,7 +307,7 @@ export function MonitorDetailFlyout(props: Props) {
locations={locations} locations={locations}
setCurrentLocation={setLocation} setCurrentLocation={setLocation}
configId={configId} configId={configId}
monitor={monitorSavedObject} monitor={monitorObject}
onEnabledChange={props.onEnabledChange} onEnabledChange={props.onEnabledChange}
/> />
</EuiPanel> </EuiPanel>
@ -320,10 +320,8 @@ export function MonitorDetailFlyout(props: Props) {
latestPing={monitorDetail.data} latestPing={monitorDetail.data}
configId={configId} configId={configId}
monitor={{ monitor={{
...monitorSavedObject, ...monitorObject,
id, id,
updated_at: monitorSavedObject.updated_at!,
created_at: monitorSavedObject.created_at!,
}} }}
loading={Boolean(loading)} loading={Boolean(loading)}
/> />

View file

@ -19,3 +19,5 @@ export * from './overview';
export * from './browser_journey'; export * from './browser_journey';
export * from './ping_status'; export * from './ping_status';
export * from './private_locations'; export * from './private_locations';
export type { UpsertMonitorResponse } from './monitor_management/api';

View file

@ -108,7 +108,7 @@ export const monitorDetailsReducer = createReducer(initialState, (builder) => {
}) })
.addCase(enableMonitorAlertAction.success, (state, action) => { .addCase(enableMonitorAlertAction.success, (state, action) => {
if ('updated_at' in action.payload && state.syntheticsMonitor) { if ('updated_at' in action.payload && state.syntheticsMonitor) {
state.syntheticsMonitor = action.payload.attributes as EncryptedSyntheticsSavedMonitor; state.syntheticsMonitor = action.payload;
} }
}); });
}); });

View file

@ -6,10 +6,11 @@
*/ */
import { createAction } from '@reduxjs/toolkit'; import { createAction } from '@reduxjs/toolkit';
import { UpsertMonitorError, UpsertMonitorRequest, UpsertMonitorResponse } from '..'; import { UpsertMonitorError, UpsertMonitorRequest } from '..';
import { import {
MonitorManagementListResult, MonitorManagementListResult,
MonitorFiltersResult, MonitorFiltersResult,
EncryptedSyntheticsSavedMonitor,
} from '../../../../../common/runtime_types'; } from '../../../../../common/runtime_types';
import { createAsyncAction } from '../utils/actions'; import { createAsyncAction } from '../utils/actions';
@ -24,17 +25,16 @@ export const quietFetchMonitorListAction = createAction<MonitorListPageState>(
); );
export const fetchUpsertMonitorAction = createAction<UpsertMonitorRequest>('fetchUpsertMonitor'); export const fetchUpsertMonitorAction = createAction<UpsertMonitorRequest>('fetchUpsertMonitor');
export const fetchUpsertSuccessAction = createAction<{ export const fetchUpsertSuccessAction = createAction<EncryptedSyntheticsSavedMonitor>(
id: string; 'fetchUpsertMonitorSuccess'
attributes: { enabled: boolean }; );
}>('fetchUpsertMonitorSuccess');
export const fetchUpsertFailureAction = createAction<UpsertMonitorError>( export const fetchUpsertFailureAction = createAction<UpsertMonitorError>(
'fetchUpsertMonitorFailure' 'fetchUpsertMonitorFailure'
); );
export const enableMonitorAlertAction = createAsyncAction< export const enableMonitorAlertAction = createAsyncAction<
UpsertMonitorRequest, UpsertMonitorRequest,
UpsertMonitorResponse, EncryptedSyntheticsSavedMonitor,
UpsertMonitorError UpsertMonitorError
>('enableMonitorAlertAction'); >('enableMonitorAlertAction');

View file

@ -5,15 +5,14 @@
* 2.0. * 2.0.
*/ */
import { SavedObject } from '@kbn/core-saved-objects-common';
import { UpsertMonitorRequest } from '..'; import { UpsertMonitorRequest } from '..';
import { UpsertMonitorResponse } from '../monitor_management/api';
import { SYNTHETICS_API_URLS } from '../../../../../common/constants'; import { SYNTHETICS_API_URLS } from '../../../../../common/constants';
import { import {
EncryptedSyntheticsMonitor, EncryptedSyntheticsMonitor,
FetchMonitorManagementListQueryArgs, FetchMonitorManagementListQueryArgs,
MonitorManagementListResult, MonitorManagementListResult,
MonitorManagementListResultCodec, MonitorManagementListResultCodec,
ServiceLocationErrors,
SyntheticsMonitor, SyntheticsMonitor,
MonitorFiltersResult, MonitorFiltersResult,
} from '../../../../../common/runtime_types'; } from '../../../../../common/runtime_types';
@ -56,10 +55,6 @@ export const fetchDeleteMonitor = async ({ configId }: { configId: string }): Pr
return await apiService.delete(`${SYNTHETICS_API_URLS.SYNTHETICS_MONITORS}/${configId}`); return await apiService.delete(`${SYNTHETICS_API_URLS.SYNTHETICS_MONITORS}/${configId}`);
}; };
export type UpsertMonitorResponse =
| { attributes: { errors: ServiceLocationErrors }; id: string }
| SavedObject<SyntheticsMonitor>;
export const fetchUpsertMonitor = async ({ export const fetchUpsertMonitor = async ({
monitor, monitor,
configId, configId,
@ -75,7 +70,7 @@ export const createGettingStartedMonitor = async ({
monitor, monitor,
}: { }: {
monitor: SyntheticsMonitor | EncryptedSyntheticsMonitor; monitor: SyntheticsMonitor | EncryptedSyntheticsMonitor;
}): Promise<{ attributes: { errors: ServiceLocationErrors } } | SyntheticsMonitor> => { }): Promise<UpsertMonitorResponse> => {
return await apiService.post(SYNTHETICS_API_URLS.SYNTHETICS_MONITORS, monitor, undefined, { return await apiService.post(SYNTHETICS_API_URLS.SYNTHETICS_MONITORS, monitor, undefined, {
gettingStarted: true, gettingStarted: true,
}); });

View file

@ -7,10 +7,9 @@
import { PayloadAction } from '@reduxjs/toolkit'; import { PayloadAction } from '@reduxjs/toolkit';
import { call, put, takeEvery, select, takeLatest, debounce } from 'redux-saga/effects'; import { call, put, takeEvery, select, takeLatest, debounce } from 'redux-saga/effects';
import { SavedObject } from '@kbn/core-saved-objects-common';
import { quietFetchOverviewStatusAction } from '../overview_status'; import { quietFetchOverviewStatusAction } from '../overview_status';
import { enableDefaultAlertingAction } from '../alert_rules'; import { enableDefaultAlertingAction } from '../alert_rules';
import { ConfigKey, SyntheticsMonitor } from '../../../../../common/runtime_types'; import { ConfigKey, EncryptedSyntheticsSavedMonitor } from '../../../../../common/runtime_types';
import { kibanaService } from '../../../../utils/kibana_service'; import { kibanaService } from '../../../../utils/kibana_service';
import { MonitorOverviewPageState } from '../overview'; import { MonitorOverviewPageState } from '../overview';
import { quietFetchOverviewAction } from '../overview/actions'; import { quietFetchOverviewAction } from '../overview/actions';
@ -27,12 +26,8 @@ import {
quietFetchMonitorListAction, quietFetchMonitorListAction,
fetchMonitorFiltersAction, fetchMonitorFiltersAction,
} from './actions'; } from './actions';
import { import { fetchMonitorManagementList, fetchUpsertMonitor, fetchMonitorFilters } from './api';
fetchMonitorManagementList,
fetchUpsertMonitor,
fetchMonitorFilters,
UpsertMonitorResponse,
} from './api';
import { toastTitle } from './toast_title'; import { toastTitle } from './toast_title';
import { UpsertMonitorRequest } from './models'; import { UpsertMonitorRequest } from './models';
@ -54,11 +49,10 @@ export function* enableMonitorAlertEffect() {
function* (action: PayloadAction<UpsertMonitorRequest>): Generator { function* (action: PayloadAction<UpsertMonitorRequest>): Generator {
try { try {
const response = yield call(fetchUpsertMonitor, action.payload); const response = yield call(fetchUpsertMonitor, action.payload);
yield put(enableMonitorAlertAction.success(response as UpsertMonitorResponse)); yield put(enableMonitorAlertAction.success(response as EncryptedSyntheticsSavedMonitor));
sendSuccessToast(action.payload.success); sendSuccessToast(action.payload.success);
if ( if (
(response as SavedObject<SyntheticsMonitor>).attributes[ConfigKey.ALERT_CONFIG]?.status (response as EncryptedSyntheticsSavedMonitor)[ConfigKey.ALERT_CONFIG]?.status?.enabled
?.enabled
) { ) {
yield put(enableDefaultAlertingAction.get()); yield put(enableDefaultAlertingAction.get());
} }
@ -81,9 +75,7 @@ export function* upsertMonitorEffect() {
function* (action: PayloadAction<UpsertMonitorRequest>): Generator { function* (action: PayloadAction<UpsertMonitorRequest>): Generator {
try { try {
const response = yield call(fetchUpsertMonitor, action.payload); const response = yield call(fetchUpsertMonitor, action.payload);
yield put( yield put(fetchUpsertSuccessAction(response as EncryptedSyntheticsSavedMonitor));
fetchUpsertSuccessAction(response as { id: string; attributes: { enabled: boolean } })
);
kibanaService.toasts.addSuccess({ kibanaService.toasts.addSuccess({
title: toastTitle({ title: toastTitle({
title: action.payload.success.message, title: action.payload.success.message,

View file

@ -79,9 +79,9 @@ export const monitorListReducer = createReducer(initialState, (builder) => {
}; };
}) })
.addCase(fetchUpsertSuccessAction, (state, action) => { .addCase(fetchUpsertSuccessAction, (state, action) => {
state.monitorUpsertStatuses[action.payload.id] = { state.monitorUpsertStatuses[action.payload.config_id] = {
status: FETCH_STATUS.SUCCESS, status: FETCH_STATUS.SUCCESS,
enabled: action.payload.attributes.enabled, enabled: action.payload.enabled,
}; };
}) })
.addCase(fetchUpsertFailureAction, (state, action) => { .addCase(fetchUpsertFailureAction, (state, action) => {
@ -94,15 +94,15 @@ export const monitorListReducer = createReducer(initialState, (builder) => {
}; };
}) })
.addCase(enableMonitorAlertAction.success, (state, action) => { .addCase(enableMonitorAlertAction.success, (state, action) => {
state.monitorUpsertStatuses[action.payload.id] = { state.monitorUpsertStatuses[action.payload.config_id] = {
...state.monitorUpsertStatuses[action.payload.id], ...state.monitorUpsertStatuses[action.payload.config_id],
alertStatus: FETCH_STATUS.SUCCESS, alertStatus: FETCH_STATUS.SUCCESS,
}; };
if ('updated_at' in action.payload) { if ('updated_at' in action.payload) {
state.data.monitors = state.data.monitors.map<EncryptedSyntheticsSavedMonitor>( state.data.monitors = state.data.monitors.map<EncryptedSyntheticsSavedMonitor>(
(monitor: any) => { (monitor: any) => {
if (monitor.config_id === action.payload.id) { if (monitor.config_id === action.payload.config_id) {
return action.payload.attributes; return action.payload;
} }
return monitor; return monitor;
} }

View file

@ -9,18 +9,19 @@ import { PackagePolicy } from '@kbn/fleet-plugin/common';
import { apiService } from '../../../../utils/api_service'; import { apiService } from '../../../../utils/api_service';
import { import {
EncryptedSyntheticsMonitor, EncryptedSyntheticsMonitor,
ServiceLocationErrors,
SyntheticsMonitor, SyntheticsMonitor,
SyntheticsMonitorWithId,
SyntheticsMonitorCodec, SyntheticsMonitorCodec,
ServiceLocationErrorsResponse,
} from '../../../../../common/runtime_types'; } from '../../../../../common/runtime_types';
import { SYNTHETICS_API_URLS } from '../../../../../common/constants'; import { SYNTHETICS_API_URLS } from '../../../../../common/constants';
export type UpsertMonitorResponse = ServiceLocationErrorsResponse | EncryptedSyntheticsMonitor;
export const createMonitorAPI = async ({ export const createMonitorAPI = async ({
monitor, monitor,
}: { }: {
monitor: SyntheticsMonitor | EncryptedSyntheticsMonitor; monitor: SyntheticsMonitor | EncryptedSyntheticsMonitor;
}): Promise<{ attributes: { errors: ServiceLocationErrors } } | SyntheticsMonitor> => { }): Promise<UpsertMonitorResponse> => {
return await apiService.post(SYNTHETICS_API_URLS.SYNTHETICS_MONITORS, monitor); return await apiService.post(SYNTHETICS_API_URLS.SYNTHETICS_MONITORS, monitor);
}; };
@ -47,7 +48,7 @@ export const updateMonitorAPI = async ({
}: { }: {
monitor: SyntheticsMonitor | EncryptedSyntheticsMonitor; monitor: SyntheticsMonitor | EncryptedSyntheticsMonitor;
id: string; id: string;
}): Promise<{ attributes: { errors: ServiceLocationErrors } } | SyntheticsMonitorWithId> => { }): Promise<UpsertMonitorResponse> => {
return await apiService.put(`${SYNTHETICS_API_URLS.SYNTHETICS_MONITORS}/${id}`, monitor); return await apiService.put(`${SYNTHETICS_API_URLS.SYNTHETICS_MONITORS}/${id}`, monitor);
}; };

View file

@ -70,13 +70,13 @@ export const monitorOverviewReducer = createReducer(initialState, (builder) => {
state.flyoutConfig = action.payload; state.flyoutConfig = action.payload;
}) })
.addCase(enableMonitorAlertAction.success, (state, action) => { .addCase(enableMonitorAlertAction.success, (state, action) => {
const attrs = action.payload.attributes; const monitorObject = action.payload;
if (!('errors' in attrs)) { if (!('errors' in monitorObject)) {
const isStatusAlertEnabled = isStatusEnabled(attrs[ConfigKey.ALERT_CONFIG]); const isStatusAlertEnabled = isStatusEnabled(monitorObject[ConfigKey.ALERT_CONFIG]);
state.data.monitors = state.data.monitors.map((monitor) => { state.data.monitors = state.data.monitors.map((monitor) => {
if ( if (
monitor.id === action.payload.id || monitor.id === monitorObject[ConfigKey.CONFIG_ID] ||
attrs[ConfigKey.MONITOR_QUERY_ID] === monitor.id monitor.id === monitorObject[ConfigKey.MONITOR_QUERY_ID]
) { ) {
return { return {
...monitor, ...monitor,

View file

@ -37,6 +37,7 @@ import { validateMonitor } from './monitor_validation';
import { sendTelemetryEvents, formatTelemetryEvent } from '../telemetry/monitor_upgrade_sender'; import { sendTelemetryEvents, formatTelemetryEvent } from '../telemetry/monitor_upgrade_sender';
import { formatSecrets } from '../../synthetics_service/utils/secrets'; import { formatSecrets } from '../../synthetics_service/utils/secrets';
import { deleteMonitor } from './delete_monitor'; import { deleteMonitor } from './delete_monitor';
import { mapSavedObjectToMonitor } from './helper';
export const addSyntheticsMonitorRoute: SyntheticsRestApiRouteFactory = () => ({ export const addSyntheticsMonitorRoute: SyntheticsRestApiRouteFactory = () => ({
method: 'POST', method: 'POST',
@ -96,7 +97,7 @@ export const addSyntheticsMonitorRoute: SyntheticsRestApiRouteFactory = () => ({
initDefaultAlerts(newMonitor.attributes.name, routeContext); initDefaultAlerts(newMonitor.attributes.name, routeContext);
setupGettingStarted(newMonitor.id, routeContext); setupGettingStarted(newMonitor.id, routeContext);
return response.ok({ body: newMonitor }); return response.ok({ body: mapSavedObjectToMonitor(newMonitor) });
} catch (getErr) { } catch (getErr) {
server.logger.error(getErr); server.logger.error(getErr);
if (SavedObjectsErrorHelpers.isForbiddenError(getErr)) { if (SavedObjectsErrorHelpers.isForbiddenError(getErr)) {

View file

@ -27,6 +27,7 @@ import {
formatTelemetryUpdateEvent, formatTelemetryUpdateEvent,
} from '../telemetry/monitor_upgrade_sender'; } from '../telemetry/monitor_upgrade_sender';
import { formatSecrets, normalizeSecrets } from '../../synthetics_service/utils/secrets'; import { formatSecrets, normalizeSecrets } from '../../synthetics_service/utils/secrets';
import { mapSavedObjectToMonitor } from './helper';
// Simplify return promise type and type it with runtime_types // Simplify return promise type and type it with runtime_types
export const editSyntheticsMonitorRoute: SyntheticsRestApiRouteFactory = () => ({ export const editSyntheticsMonitorRoute: SyntheticsRestApiRouteFactory = () => ({
@ -113,7 +114,9 @@ export const editSyntheticsMonitorRoute: SyntheticsRestApiRouteFactory = () => (
}); });
} }
return editedMonitorSavedObject; return mapSavedObjectToMonitor(
editedMonitorSavedObject as SavedObject<EncryptedSyntheticsMonitorAttributes>
);
} catch (updateErr) { } catch (updateErr) {
if (SavedObjectsErrorHelpers.isNotFoundError(updateErr)) { if (SavedObjectsErrorHelpers.isNotFoundError(updateErr)) {
return getMonitorNotFoundResponse(response, monitorId); return getMonitorNotFoundResponse(response, monitorId);

View file

@ -5,6 +5,7 @@
* 2.0. * 2.0.
*/ */
import expect from '@kbn/expect'; import expect from '@kbn/expect';
import moment from 'moment/moment';
import { v4 as uuidv4 } from 'uuid'; import { v4 as uuidv4 } from 'uuid';
import { omit } from 'lodash'; import { omit } from 'lodash';
import { secretKeys } from '@kbn/synthetics-plugin/common/constants/monitor_management'; import { secretKeys } from '@kbn/synthetics-plugin/common/constants/monitor_management';
@ -49,12 +50,17 @@ export default function ({ getService }: FtrProviderContext) {
.set('kbn-xsrf', 'true') .set('kbn-xsrf', 'true')
.send(newMonitor); .send(newMonitor);
expect(apiResponse.body.attributes).eql( const { created_at: createdAt, updated_at: updatedAt } = apiResponse.body;
expect([createdAt, updatedAt].map((d) => moment(d).isValid())).eql([true, true]);
expect(apiResponse.body).eql(
omit( omit(
{ {
...newMonitor, ...newMonitor,
[ConfigKey.MONITOR_QUERY_ID]: apiResponse.body.id, [ConfigKey.MONITOR_QUERY_ID]: apiResponse.body.id,
[ConfigKey.CONFIG_ID]: apiResponse.body.id, [ConfigKey.CONFIG_ID]: apiResponse.body.id,
created_at: createdAt,
updated_at: updatedAt,
}, },
secretKeys secretKeys
) )
@ -111,13 +117,19 @@ export default function ({ getService }: FtrProviderContext) {
.send(newMonitor); .send(newMonitor);
expect(apiResponse.status).eql(200); expect(apiResponse.status).eql(200);
expect(apiResponse.body.attributes).eql(
const { created_at: createdAt, updated_at: updatedAt } = apiResponse.body;
expect([createdAt, updatedAt].map((d) => moment(d).isValid())).eql([true, true]);
expect(apiResponse.body).eql(
omit( omit(
{ {
...DEFAULT_FIELDS[DataStream.HTTP], ...DEFAULT_FIELDS[DataStream.HTTP],
...newMonitor, ...newMonitor,
[ConfigKey.MONITOR_QUERY_ID]: apiResponse.body.id, [ConfigKey.MONITOR_QUERY_ID]: apiResponse.body.id,
[ConfigKey.CONFIG_ID]: apiResponse.body.id, [ConfigKey.CONFIG_ID]: apiResponse.body.id,
created_at: createdAt,
updated_at: updatedAt,
revision: 1, revision: 1,
}, },
secretKeys secretKeys
@ -180,7 +192,12 @@ export default function ({ getService }: FtrProviderContext) {
.expect(200); .expect(200);
const response = await supertestAPI const response = await supertestAPI
.get(SYNTHETICS_API_URLS.GET_SYNTHETICS_MONITOR.replace('{monitorId}', apiResponse.body.id)) .get(
SYNTHETICS_API_URLS.GET_SYNTHETICS_MONITOR.replace(
'{monitorId}',
apiResponse.body.config_id
)
)
.set('kbn-xsrf', 'true') .set('kbn-xsrf', 'true')
.expect(200); .expect(200);
@ -375,7 +392,7 @@ export default function ({ getService }: FtrProviderContext) {
.send(monitor) .send(monitor)
.expect(200); .expect(200);
monitorId = apiResponse.body.id; monitorId = apiResponse.body.id;
expect(apiResponse.body.attributes[ConfigKey.NAMESPACE]).eql(EXPECTED_NAMESPACE); expect(apiResponse.body[ConfigKey.NAMESPACE]).eql(EXPECTED_NAMESPACE);
} finally { } finally {
await security.user.delete(username); await security.user.delete(username);
await security.role.delete(roleName); await security.role.delete(roleName);
@ -423,7 +440,7 @@ export default function ({ getService }: FtrProviderContext) {
.send(monitor) .send(monitor)
.expect(200); .expect(200);
monitorId = apiResponse.body.id; monitorId = apiResponse.body.id;
expect(apiResponse.body.attributes[ConfigKey.NAMESPACE]).eql('default'); expect(apiResponse.body[ConfigKey.NAMESPACE]).eql('default');
} finally { } finally {
await security.user.delete(username); await security.user.delete(username);
await security.role.delete(roleName); await security.role.delete(roleName);
@ -467,7 +484,7 @@ export default function ({ getService }: FtrProviderContext) {
.send(monitor) .send(monitor)
.expect(200); .expect(200);
monitorId = apiResponse.body.id; monitorId = apiResponse.body.id;
expect(apiResponse.body.attributes[ConfigKey.NAMESPACE]).eql(monitor[ConfigKey.NAMESPACE]); expect(apiResponse.body[ConfigKey.NAMESPACE]).eql(monitor[ConfigKey.NAMESPACE]);
} finally { } finally {
await security.user.delete(username); await security.user.delete(username);
await security.role.delete(roleName); await security.role.delete(roleName);

View file

@ -4,6 +4,7 @@
* 2.0; you may not use this file except in compliance with the Elastic License * 2.0; you may not use this file except in compliance with the Elastic License
* 2.0. * 2.0.
*/ */
import moment from 'moment';
import semver from 'semver'; import semver from 'semver';
import { v4 as uuidv4 } from 'uuid'; import { v4 as uuidv4 } from 'uuid';
import { ConfigKey, HTTPFields } from '@kbn/synthetics-plugin/common/runtime_types'; import { ConfigKey, HTTPFields } from '@kbn/synthetics-plugin/common/runtime_types';
@ -131,12 +132,17 @@ export default function ({ getService }: FtrProviderContext) {
.send(newMonitor) .send(newMonitor)
.expect(200); .expect(200);
expect(apiResponse.body.attributes).eql( const { created_at: createdAt, updated_at: updatedAt } = apiResponse.body;
expect([createdAt, updatedAt].map((d) => moment(d).isValid())).eql([true, true]);
expect(apiResponse.body).eql(
omit( omit(
{ {
...newMonitor, ...newMonitor,
[ConfigKey.MONITOR_QUERY_ID]: apiResponse.body.id, [ConfigKey.MONITOR_QUERY_ID]: apiResponse.body.id,
[ConfigKey.CONFIG_ID]: apiResponse.body.id, [ConfigKey.CONFIG_ID]: apiResponse.body.id,
created_at: createdAt,
updated_at: updatedAt,
}, },
secretKeys secretKeys
) )
@ -185,12 +191,16 @@ export default function ({ getService }: FtrProviderContext) {
.set('kbn-xsrf', 'true') .set('kbn-xsrf', 'true')
.send(httpMonitorJson); .send(httpMonitorJson);
expect(apiResponse.body.attributes).eql( const { created_at: createdAt, updated_at: updatedAt } = apiResponse.body;
expect([createdAt, updatedAt].map((d) => moment(d).isValid())).eql([true, true]);
expect(apiResponse.body).eql(
omit( omit(
{ {
...httpMonitorJson, ...httpMonitorJson,
[ConfigKey.MONITOR_QUERY_ID]: apiResponse.body.id, [ConfigKey.MONITOR_QUERY_ID]: apiResponse.body.id,
[ConfigKey.CONFIG_ID]: apiResponse.body.id, [ConfigKey.CONFIG_ID]: apiResponse.body.id,
updated_at: updatedAt,
revision: 2, revision: 2,
}, },
secretKeys secretKeys
@ -341,13 +351,18 @@ export default function ({ getService }: FtrProviderContext) {
.send(monitor) .send(monitor)
.expect(200); .expect(200);
expect(apiResponse.body.attributes).eql( const { created_at: createdAt, updated_at: updatedAt } = apiResponse.body;
expect([createdAt, updatedAt].map((d) => moment(d).isValid())).eql([true, true]);
expect(apiResponse.body).eql(
omit( omit(
{ {
...monitor, ...monitor,
[ConfigKey.MONITOR_QUERY_ID]: apiResponse.body.id, [ConfigKey.MONITOR_QUERY_ID]: apiResponse.body.id,
[ConfigKey.CONFIG_ID]: apiResponse.body.id, [ConfigKey.CONFIG_ID]: apiResponse.body.id,
[ConfigKey.NAMESPACE]: formatKibanaNamespace(SPACE_ID), [ConfigKey.NAMESPACE]: formatKibanaNamespace(SPACE_ID),
created_at: createdAt,
updated_at: updatedAt,
}, },
secretKeys secretKeys
) )

View file

@ -1216,7 +1216,7 @@ export default function ({ getService }: FtrProviderContext) {
[ConfigKey.PORT]: 443, [ConfigKey.PORT]: 443,
}; };
const modifiedMonitor = { ...monitors[0]?.attributes, ...updates }; const modifiedMonitor = { ...monitors[0], ...updates };
await supertest await supertest
.put(SYNTHETICS_API_URLS.SYNTHETICS_MONITORS + '/' + monitors[0]?.config_id) .put(SYNTHETICS_API_URLS.SYNTHETICS_MONITORS + '/' + monitors[0]?.config_id)

View file

@ -5,7 +5,11 @@
* 2.0. * 2.0.
*/ */
import { v4 as uuidv4 } from 'uuid'; import { v4 as uuidv4 } from 'uuid';
import { HTTPFields, MonitorFields } from '@kbn/synthetics-plugin/common/runtime_types'; import {
EncryptedSyntheticsSavedMonitor,
HTTPFields,
MonitorFields,
} from '@kbn/synthetics-plugin/common/runtime_types';
import { SYNTHETICS_API_URLS } from '@kbn/synthetics-plugin/common/constants'; import { SYNTHETICS_API_URLS } from '@kbn/synthetics-plugin/common/constants';
import expect from '@kbn/expect'; import expect from '@kbn/expect';
import { PACKAGE_POLICY_SAVED_OBJECT_TYPE } from '@kbn/fleet-plugin/common'; import { PACKAGE_POLICY_SAVED_OBJECT_TYPE } from '@kbn/fleet-plugin/common';
@ -31,7 +35,9 @@ export default function ({ getService }: FtrProviderContext) {
let httpMonitorJson: HTTPFields; let httpMonitorJson: HTTPFields;
let testPolicyId = ''; let testPolicyId = '';
const saveMonitor = async (monitor: MonitorFields) => { const saveMonitor = async (
monitor: MonitorFields
): Promise<EncryptedSyntheticsSavedMonitor> => {
const res = await supertest const res = await supertest
.post(SYNTHETICS_API_URLS.SYNTHETICS_MONITORS) .post(SYNTHETICS_API_URLS.SYNTHETICS_MONITORS)
.set('kbn-xsrf', 'true') .set('kbn-xsrf', 'true')

View file

@ -4,15 +4,20 @@
* 2.0; you may not use this file except in compliance with the Elastic License * 2.0; you may not use this file except in compliance with the Elastic License
* 2.0. * 2.0.
*/ */
import moment from 'moment';
import { v4 as uuidv4 } from 'uuid'; import { v4 as uuidv4 } from 'uuid';
import { omit } from 'lodash'; import { omit } from 'lodash';
import { SimpleSavedObject } from '@kbn/core/public'; import {
import { secretKeys } from '@kbn/synthetics-plugin/common/constants/monitor_management'; ConfigKey,
import { ConfigKey, HTTPFields, MonitorFields } from '@kbn/synthetics-plugin/common/runtime_types'; EncryptedSyntheticsSavedMonitor,
HTTPFields,
MonitorFields,
} from '@kbn/synthetics-plugin/common/runtime_types';
import { SYNTHETICS_API_URLS } from '@kbn/synthetics-plugin/common/constants'; import { SYNTHETICS_API_URLS } from '@kbn/synthetics-plugin/common/constants';
import expect from '@kbn/expect'; import expect from '@kbn/expect';
import { FtrProviderContext } from '../../ftr_provider_context'; import { FtrProviderContext } from '../../ftr_provider_context';
import { getFixtureJson } from './helper/get_fixture_json'; import { getFixtureJson } from './helper/get_fixture_json';
import { omitTimestamps, omitTimestampsAndSecrets } from './helper/monitor';
import { PrivateLocationTestService } from './services/private_location_test_service'; import { PrivateLocationTestService } from './services/private_location_test_service';
import { SyntheticsMonitorTestService } from './services/synthetics_monitor_test_service'; import { SyntheticsMonitorTestService } from './services/synthetics_monitor_test_service';
@ -39,7 +44,7 @@ export default function ({ getService }: FtrProviderContext) {
.send(monitor) .send(monitor)
.expect(200); .expect(200);
return res.body as SimpleSavedObject<MonitorFields>; return res.body as EncryptedSyntheticsSavedMonitor;
}; };
before(async () => { before(async () => {
@ -68,19 +73,18 @@ export default function ({ getService }: FtrProviderContext) {
it('edits the monitor', async () => { it('edits the monitor', async () => {
const newMonitor = httpMonitorJson; const newMonitor = httpMonitorJson;
const { id: monitorId, attributes: savedMonitor } = await saveMonitor( const savedMonitor = await saveMonitor(newMonitor as MonitorFields);
newMonitor as MonitorFields const monitorId = savedMonitor[ConfigKey.CONFIG_ID];
);
expect(savedMonitor).eql( const { created_at: createdAt, updated_at: updatedAt } = savedMonitor;
omit( expect([createdAt, updatedAt].map((d) => moment(d).isValid())).eql([true, true]);
{
...newMonitor, expect(omitTimestamps(savedMonitor)).eql(
[ConfigKey.MONITOR_QUERY_ID]: monitorId, omitTimestampsAndSecrets({
[ConfigKey.CONFIG_ID]: monitorId, ...newMonitor,
}, [ConfigKey.MONITOR_QUERY_ID]: monitorId,
secretKeys [ConfigKey.CONFIG_ID]: monitorId,
) })
); );
const updates: Partial<HTTPFields> = { const updates: Partial<HTTPFields> = {
@ -124,27 +128,29 @@ export default function ({ getService }: FtrProviderContext) {
.send(modifiedMonitor) .send(modifiedMonitor)
.expect(200); .expect(200);
expect(editResponse.body.attributes).eql( expect(omitTimestamps(editResponse.body)).eql(
omit({ ...modifiedMonitor, revision: 2 }, secretKeys) omitTimestampsAndSecrets({
...modifiedMonitor,
revision: 2,
})
); );
}); });
it('strips unknown keys from monitor edits', async () => { it('strips unknown keys from monitor edits', async () => {
const newMonitor = httpMonitorJson; const newMonitor = httpMonitorJson;
const { id: monitorId, attributes: savedMonitor } = await saveMonitor( const savedMonitor = await saveMonitor(newMonitor as MonitorFields);
newMonitor as MonitorFields const monitorId = savedMonitor[ConfigKey.CONFIG_ID];
);
expect(savedMonitor).eql( const { created_at: createdAt, updated_at: updatedAt } = savedMonitor;
omit( expect([createdAt, updatedAt].map((d) => moment(d).isValid())).eql([true, true]);
{
...newMonitor, expect(omitTimestamps(savedMonitor)).eql(
[ConfigKey.MONITOR_QUERY_ID]: monitorId, omitTimestampsAndSecrets({
[ConfigKey.CONFIG_ID]: monitorId, ...newMonitor,
}, [ConfigKey.MONITOR_QUERY_ID]: monitorId,
secretKeys [ConfigKey.CONFIG_ID]: monitorId,
) })
); );
const updates: Partial<HTTPFields> = { const updates: Partial<HTTPFields> = {
@ -191,17 +197,14 @@ export default function ({ getService }: FtrProviderContext) {
.send(modifiedMonitor) .send(modifiedMonitor)
.expect(200); .expect(200);
expect(editResponse.body.attributes).eql( expect(omitTimestamps(editResponse.body)).eql(
omit( omitTimestampsAndSecrets({
{ ...savedMonitor,
...savedMonitor, ...modifiedMonitor,
...modifiedMonitor, revision: 2,
revision: 2, })
},
secretKeys
)
); );
expect(editResponse.body.attributes).not.to.have.keys('unknownkey'); expect(editResponse.body).not.to.have.keys('unknownkey');
}); });
it('returns 404 if monitor id is not present', async () => { it('returns 404 if monitor id is not present', async () => {
@ -253,21 +256,21 @@ export default function ({ getService }: FtrProviderContext) {
const newMonitor = httpMonitorJson; const newMonitor = httpMonitorJson;
const configHash = 'djrhefje'; const configHash = 'djrhefje';
const { id: monitorId, attributes: savedMonitor } = await saveMonitor({ const savedMonitor = await saveMonitor({
...(newMonitor as MonitorFields), ...(newMonitor as MonitorFields),
[ConfigKey.CONFIG_HASH]: configHash, [ConfigKey.CONFIG_HASH]: configHash,
}); });
const monitorId = savedMonitor[ConfigKey.CONFIG_ID];
const { created_at: createdAt, updated_at: updatedAt } = savedMonitor;
expect([createdAt, updatedAt].map((d) => moment(d).isValid())).eql([true, true]);
expect(savedMonitor).eql( expect(omitTimestamps(savedMonitor)).eql(
omit( omitTimestampsAndSecrets({
{ ...newMonitor,
...newMonitor, [ConfigKey.CONFIG_ID]: monitorId,
[ConfigKey.CONFIG_ID]: monitorId, [ConfigKey.MONITOR_QUERY_ID]: monitorId,
[ConfigKey.MONITOR_QUERY_ID]: monitorId, [ConfigKey.CONFIG_HASH]: configHash,
[ConfigKey.CONFIG_HASH]: configHash, })
},
secretKeys
)
); );
const updates: Partial<HTTPFields> = { const updates: Partial<HTTPFields> = {
@ -289,17 +292,14 @@ export default function ({ getService }: FtrProviderContext) {
.send(modifiedMonitor) .send(modifiedMonitor)
.expect(200); .expect(200);
expect(editResponse.body.attributes).eql( expect(omitTimestamps(editResponse.body)).eql(
omit( omitTimestampsAndSecrets({
{ ...modifiedMonitor,
...modifiedMonitor, [ConfigKey.CONFIG_ID]: monitorId,
[ConfigKey.CONFIG_ID]: monitorId, [ConfigKey.MONITOR_QUERY_ID]: monitorId,
[ConfigKey.MONITOR_QUERY_ID]: monitorId, [ConfigKey.CONFIG_HASH]: '',
[ConfigKey.CONFIG_HASH]: '', revision: 2,
revision: 2, })
},
secretKeys
)
); );
expect(editResponse.body).not.to.have.keys('unknownkey'); expect(editResponse.body).not.to.have.keys('unknownkey');
}); });
@ -346,8 +346,8 @@ export default function ({ getService }: FtrProviderContext) {
roles: [roleName], roles: [roleName],
full_name: 'a kibana user', full_name: 'a kibana user',
}); });
const { id, attributes: savedMonitor } = await saveMonitor(newMonitor as MonitorFields); const savedMonitor = await saveMonitor(newMonitor as MonitorFields);
monitorId = id; monitorId = savedMonitor[ConfigKey.CONFIG_ID];
const toUpdate = { const toUpdate = {
...savedMonitor, ...savedMonitor,
name: '!@#$%^&*()_++[\\-\\]- wow', name: '!@#$%^&*()_++[\\-\\]- wow',
@ -393,7 +393,6 @@ export default function ({ getService }: FtrProviderContext) {
const SPACE_ID = `test-space-${uuidv4()}`; const SPACE_ID = `test-space-${uuidv4()}`;
const SPACE_NAME = `test-space-name ${uuidv4()}`; const SPACE_NAME = `test-space-name ${uuidv4()}`;
let monitorId = '';
await kibanaServer.spaces.create({ id: SPACE_ID, name: SPACE_NAME }); await kibanaServer.spaces.create({ id: SPACE_ID, name: SPACE_NAME });
@ -403,8 +402,8 @@ export default function ({ getService }: FtrProviderContext) {
.send(newMonitor) .send(newMonitor)
.expect(200); .expect(200);
const { id, attributes: savedMonitor } = response.body; const savedMonitor = response.body;
monitorId = id; const monitorId = savedMonitor[ConfigKey.CONFIG_ID];
const toUpdate = { const toUpdate = {
...savedMonitor, ...savedMonitor,
urls: 'https://google.com', urls: 'https://google.com',

View file

@ -72,12 +72,14 @@ export default function ({ getService }: FtrProviderContext) {
.set('kbn-xsrf', 'true') .set('kbn-xsrf', 'true')
.send(newMonitor); .send(newMonitor);
expect(apiResponse.body.attributes).eql( expect(apiResponse.body).eql(
omit( omit(
{ {
...newMonitor, ...newMonitor,
[ConfigKey.MONITOR_QUERY_ID]: apiResponse.body.id, [ConfigKey.MONITOR_QUERY_ID]: apiResponse.body.id,
[ConfigKey.CONFIG_ID]: apiResponse.body.id, [ConfigKey.CONFIG_ID]: apiResponse.body.id,
created_at: apiResponse.body.created_at,
updated_at: apiResponse.body.updated_at,
}, },
secretKeys secretKeys
) )

View file

@ -33,7 +33,7 @@ export default function ({ getService }: FtrProviderContext) {
.send(monitor) .send(monitor)
.expect(200); .expect(200);
return res.body as MonitorFields; return res.body as EncryptedSyntheticsSavedMonitor;
}; };
before(async () => { before(async () => {
@ -82,7 +82,7 @@ export default function ({ getService }: FtrProviderContext) {
}); });
expect(foundMonitors.map((fm) => omit(fm, 'updated_at', 'created_at'))).eql( expect(foundMonitors.map((fm) => omit(fm, 'updated_at', 'created_at'))).eql(
expected.map(({ attributes }: any) => attributes) expected.map((expectedMon) => omit(expectedMon, 'updated_at', 'created_at'))
); );
}); });

View file

@ -5,12 +5,11 @@
* 2.0. * 2.0.
*/ */
import { v4 as uuidv4 } from 'uuid'; import { v4 as uuidv4 } from 'uuid';
import { SimpleSavedObject } from '@kbn/core/public';
import { import {
ConfigKey, ConfigKey,
SyntheticsMonitor,
MonitorFields, MonitorFields,
MonitorOverviewItem, MonitorOverviewItem,
EncryptedSyntheticsSavedMonitor,
} from '@kbn/synthetics-plugin/common/runtime_types'; } from '@kbn/synthetics-plugin/common/runtime_types';
import { SYNTHETICS_API_URLS } from '@kbn/synthetics-plugin/common/constants'; import { SYNTHETICS_API_URLS } from '@kbn/synthetics-plugin/common/constants';
import expect from '@kbn/expect'; import expect from '@kbn/expect';
@ -52,7 +51,7 @@ export default function ({ getService }: FtrProviderContext) {
.set('kbn-xsrf', 'true') .set('kbn-xsrf', 'true')
.send(monitor); .send(monitor);
return res.body as SimpleSavedObject<MonitorFields>; return res.body as EncryptedSyntheticsSavedMonitor;
}; };
before(async () => { before(async () => {
@ -81,7 +80,7 @@ export default function ({ getService }: FtrProviderContext) {
.set('kbn-xsrf', 'true') .set('kbn-xsrf', 'true')
.expect(200); .expect(200);
await Promise.all([ await Promise.all([
(body.monitors as Array<SimpleSavedObject<MonitorFields>>).map((monitor) => { (body.monitors as EncryptedSyntheticsSavedMonitor[]).map((monitor) => {
return deleteMonitor(monitor.id); return deleteMonitor(monitor.id);
}), }),
]); ]);
@ -106,10 +105,9 @@ export default function ({ getService }: FtrProviderContext) {
}); });
it('returns the correct response', async () => { it('returns the correct response', async () => {
let savedMonitors: SimpleSavedObject[] = []; let savedMonitors: EncryptedSyntheticsSavedMonitor[] = [];
try { try {
const savedResponse = await Promise.all(monitors.map(saveMonitor)); savedMonitors = await Promise.all(monitors.map(saveMonitor));
savedMonitors = savedResponse;
const apiResponse = await supertest.get( const apiResponse = await supertest.get(
`/s/${SPACE_ID}${SYNTHETICS_API_URLS.SYNTHETICS_OVERVIEW}` `/s/${SPACE_ID}${SYNTHETICS_API_URLS.SYNTHETICS_OVERVIEW}`
@ -130,10 +128,9 @@ export default function ({ getService }: FtrProviderContext) {
}); });
it('accepts search queries', async () => { it('accepts search queries', async () => {
let savedMonitors: Array<SimpleSavedObject<SyntheticsMonitor>> = []; let savedMonitors: EncryptedSyntheticsSavedMonitor[] = [];
try { try {
const savedResponse = await Promise.all(monitors.map(saveMonitor)); savedMonitors = await Promise.all(monitors.map(saveMonitor));
savedMonitors = savedResponse;
const apiResponse = await supertest const apiResponse = await supertest
.get(`/s/${SPACE_ID}${SYNTHETICS_API_URLS.SYNTHETICS_OVERVIEW}`) .get(`/s/${SPACE_ID}${SYNTHETICS_API_URLS.SYNTHETICS_OVERVIEW}`)
@ -144,7 +141,7 @@ export default function ({ getService }: FtrProviderContext) {
expect(apiResponse.body.total).eql(2); expect(apiResponse.body.total).eql(2);
expect(apiResponse.body.allMonitorIds.sort()).eql( expect(apiResponse.body.allMonitorIds.sort()).eql(
savedMonitors savedMonitors
.filter((monitor) => monitor.attributes.name.includes('19')) .filter((monitor) => monitor.name.includes('19'))
.map((monitor) => monitor.id) .map((monitor) => monitor.id)
); );
expect(apiResponse.body.monitors.length).eql(2); expect(apiResponse.body.monitors.length).eql(2);
@ -157,11 +154,11 @@ export default function ({ getService }: FtrProviderContext) {
} }
}); });
it('returns the correct response', async () => { it('returns the correct response for customHeartbeatId', async () => {
let savedMonitors: Array<SimpleSavedObject<SyntheticsMonitor>> = []; let savedMonitors: EncryptedSyntheticsSavedMonitor[] = [];
const customHeartbeatId = 'example_custom_heartbeat_id'; const customHeartbeatId = 'example_custom_heartbeat_id';
try { try {
const savedResponse = await Promise.all( savedMonitors = await Promise.all(
[ [
{ ...monitors[0], name: 'test monitor a' }, { ...monitors[0], name: 'test monitor a' },
{ {
@ -171,7 +168,6 @@ export default function ({ getService }: FtrProviderContext) {
}, },
].map(saveMonitor) ].map(saveMonitor)
); );
savedMonitors = savedResponse;
const apiResponse = await supertest const apiResponse = await supertest
.get(`/s/${SPACE_ID}${SYNTHETICS_API_URLS.SYNTHETICS_OVERVIEW}`) .get(`/s/${SPACE_ID}${SYNTHETICS_API_URLS.SYNTHETICS_OVERVIEW}`)
@ -179,8 +175,8 @@ export default function ({ getService }: FtrProviderContext) {
const expected: MonitorOverviewItem[] = [ const expected: MonitorOverviewItem[] = [
{ {
id: savedMonitors[0].attributes[ConfigKey.MONITOR_QUERY_ID], id: savedMonitors[0][ConfigKey.MONITOR_QUERY_ID],
configId: savedMonitors[0].id, configId: savedMonitors[0].config_id,
name: 'test monitor a', name: 'test monitor a',
location: { location: {
id: 'eu-west-01', id: 'eu-west-01',
@ -199,8 +195,8 @@ export default function ({ getService }: FtrProviderContext) {
schedule: '5', schedule: '5',
}, },
{ {
id: savedMonitors[0].attributes[ConfigKey.MONITOR_QUERY_ID], id: savedMonitors[0][ConfigKey.MONITOR_QUERY_ID],
configId: savedMonitors[0].id, configId: savedMonitors[0].config_id,
name: 'test monitor a', name: 'test monitor a',
location: { location: {
id: 'eu-west-02', id: 'eu-west-02',
@ -219,8 +215,8 @@ export default function ({ getService }: FtrProviderContext) {
schedule: '5', schedule: '5',
}, },
{ {
id: savedMonitors[1].attributes[ConfigKey.MONITOR_QUERY_ID], id: savedMonitors[1][ConfigKey.MONITOR_QUERY_ID],
configId: savedMonitors[1].id, configId: savedMonitors[1].config_id,
name: 'test monitor b', name: 'test monitor b',
location: { location: {
id: 'eu-west-01', id: 'eu-west-01',
@ -239,8 +235,8 @@ export default function ({ getService }: FtrProviderContext) {
schedule: '5', schedule: '5',
}, },
{ {
id: savedMonitors[1].attributes[ConfigKey.MONITOR_QUERY_ID], id: savedMonitors[1][ConfigKey.MONITOR_QUERY_ID],
configId: savedMonitors[1].id, configId: savedMonitors[1].config_id,
name: 'test monitor b', name: 'test monitor b',
location: { location: {
id: 'eu-west-02', id: 'eu-west-02',
@ -261,11 +257,11 @@ export default function ({ getService }: FtrProviderContext) {
]; ];
expect(apiResponse.body.monitors).eql(expected); expect(apiResponse.body.monitors).eql(expected);
expect(savedMonitors[1].attributes[ConfigKey.MONITOR_QUERY_ID]).eql(customHeartbeatId); expect(savedMonitors[1][ConfigKey.MONITOR_QUERY_ID]).eql(customHeartbeatId);
} finally { } finally {
await Promise.all( await Promise.all(
savedMonitors.map((monitor) => { savedMonitors.map((monitor) => {
return deleteMonitor(monitor.id); return deleteMonitor(monitor.config_id);
}) })
); );
} }

View file

@ -0,0 +1,17 @@
/*
* 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 { omit } from 'lodash';
import { secretKeys } from '@kbn/synthetics-plugin/common/constants/monitor_management';
export function omitTimestamps(monitor: object) {
return omit(monitor, ['created_at', 'updated_at']);
}
export function omitTimestampsAndSecrets(monitor: object) {
return omit(monitor, ['created_at', 'updated_at', ...secretKeys]);
}

View file

@ -7,8 +7,7 @@
import { SYNTHETICS_API_URLS } from '@kbn/synthetics-plugin/common/constants'; import { SYNTHETICS_API_URLS } from '@kbn/synthetics-plugin/common/constants';
import { syntheticsMonitorType } from '@kbn/synthetics-plugin/common/types/saved_objects'; import { syntheticsMonitorType } from '@kbn/synthetics-plugin/common/types/saved_objects';
import { SavedObject } from '@kbn/core-saved-objects-common/src/server_types'; import { EncryptedSyntheticsSavedMonitor } from '@kbn/synthetics-plugin/common/runtime_types';
import { MonitorFields } from '@kbn/synthetics-plugin/common/runtime_types';
import { MonitorInspectResponse } from '@kbn/synthetics-plugin/public/apps/synthetics/state/monitor_management/api'; import { MonitorInspectResponse } from '@kbn/synthetics-plugin/public/apps/synthetics/state/monitor_management/api';
import { v4 as uuidv4 } from 'uuid'; import { v4 as uuidv4 } from 'uuid';
import { FtrProviderContext } from '../../../ftr_provider_context'; import { FtrProviderContext } from '../../../ftr_provider_context';
@ -40,7 +39,7 @@ export class SyntheticsMonitorTestService {
.send(monitor) .send(monitor)
.expect(200); .expect(200);
return res.body as SavedObject<MonitorFields>; return res.body as EncryptedSyntheticsSavedMonitor;
} }
async inspectMonitor(monitor: any, hideParams: boolean = true) { async inspectMonitor(monitor: any, hideParams: boolean = true) {

View file

@ -4,6 +4,7 @@
* 2.0; you may not use this file except in compliance with the Elastic License * 2.0; you may not use this file except in compliance with the Elastic License
* 2.0. * 2.0.
*/ */
import moment from 'moment';
import { import {
ConfigKey, ConfigKey,
HTTPFields, HTTPFields,
@ -103,12 +104,17 @@ export default function ({ getService }: FtrProviderContext) {
.set('kbn-xsrf', 'true') .set('kbn-xsrf', 'true')
.send(newMonitor); .send(newMonitor);
expect(apiResponse.body.attributes).eql( const { created_at: createdAt, updated_at: updatedAt } = apiResponse.body;
expect([createdAt, updatedAt].map((d) => moment(d).isValid())).eql([true, true]);
expect(apiResponse.body).eql(
omit( omit(
{ {
...newMonitor, ...newMonitor,
[ConfigKey.MONITOR_QUERY_ID]: apiResponse.body.id, [ConfigKey.MONITOR_QUERY_ID]: apiResponse.body.id,
[ConfigKey.CONFIG_ID]: apiResponse.body.id, [ConfigKey.CONFIG_ID]: apiResponse.body.id,
created_at: createdAt,
updated_at: updatedAt,
}, },
secretKeys secretKeys
) )
@ -210,12 +216,17 @@ export default function ({ getService }: FtrProviderContext) {
.set('kbn-xsrf', 'true') .set('kbn-xsrf', 'true')
.send(newMonitor); .send(newMonitor);
expect(apiResponse.body.attributes).eql( const { created_at: createdAt, updated_at: updatedAt } = apiResponse.body;
expect([createdAt, updatedAt].map((d) => moment(d).isValid())).eql([true, true]);
expect(apiResponse.body).eql(
omit( omit(
{ {
...newMonitor, ...newMonitor,
[ConfigKey.MONITOR_QUERY_ID]: apiResponse.body.id, [ConfigKey.MONITOR_QUERY_ID]: apiResponse.body.id,
[ConfigKey.CONFIG_ID]: apiResponse.body.id, [ConfigKey.CONFIG_ID]: apiResponse.body.id,
created_at: createdAt,
updated_at: updatedAt,
}, },
secretKeys secretKeys
) )

View file

@ -125,7 +125,6 @@
"@kbn/observability-shared-plugin", "@kbn/observability-shared-plugin",
"@kbn/maps-vector-tile-utils", "@kbn/maps-vector-tile-utils",
"@kbn/server-route-repository", "@kbn/server-route-repository",
"@kbn/core-saved-objects-common",
"@kbn/core-http-common", "@kbn/core-http-common",
"@kbn/slo-schema", "@kbn/slo-schema",
"@kbn/lens-plugin", "@kbn/lens-plugin",