[Synthetics] filters - remove public so client usage (#158095)

Co-authored-by: shahzad31 <shahzad31comp@gmail.com>
This commit is contained in:
Dominique Clarke 2023-05-23 16:01:29 -04:00 committed by GitHub
parent 0deffa4503
commit 8f16d9efc6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
46 changed files with 420 additions and 298 deletions

View file

@ -22,4 +22,5 @@ export enum SYNTHETICS_API_URLS {
NETWORK_EVENTS = `/internal/synthetics/network_events`,
JOURNEY_SCREENSHOT = `/internal/synthetics/journey/screenshot/{checkGroup}/{stepIndex}`,
DELETE_PACKAGE_POLICY = `/internal/synthetics/monitor/policy/{packagePolicyId}`,
FILTERS = '/internal/synthetics/monitor/filters',
}

View file

@ -0,0 +1,25 @@
/*
* 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 t from 'io-ts';
const MonitorFilterCodec = t.interface({
label: t.string,
count: t.number,
});
export type MonitorFilter = t.TypeOf<typeof MonitorFilterCodec>;
export const MonitorFiltersResultCodec = t.interface({
monitorTypes: t.array(MonitorFilterCodec),
tags: t.array(MonitorFilterCodec),
locations: t.array(MonitorFilterCodec),
projects: t.array(MonitorFilterCodec),
schedules: t.array(MonitorFilterCodec),
});
export type MonitorFiltersResult = t.TypeOf<typeof MonitorFiltersResultCodec>;

View file

@ -15,3 +15,4 @@ export * from './locations';
export * from './synthetics_private_locations';
export * from './synthetics_overview_status';
export * from './synthetics_params';
export * from './filters';

View file

@ -18,9 +18,11 @@ import { useMonitorFiltersState } from './use_filters';
export const FilterButton = ({
filter,
handleFilterChange,
loading,
}: {
filter: SyntheticsMonitorFilterItem;
handleFilterChange: ReturnType<typeof useMonitorFiltersState>['handleFilterChange'];
loading: boolean;
}) => {
const { label, values, field } = filter;
@ -48,7 +50,7 @@ export const FilterButton = ({
setQuery={setQuery}
onChange={(selectedValues) => handleFilterChange(field, selectedValues)}
allowExclusions={false}
loading={false}
loading={loading}
asFilterButton={true}
/>
);

View file

@ -52,7 +52,7 @@ export const FilterGroup = ({
label: TYPE_LABEL,
field: 'monitorTypes',
values: getSyntheticsFilterDisplayValues(
mixUrlValues(data.monitorTypes, urlParams.monitorTypes),
mixUrlValues(data?.monitorTypes, urlParams.monitorTypes),
'monitorTypes',
locations
),
@ -62,7 +62,7 @@ export const FilterGroup = ({
field: 'locations',
values: getSyntheticsFilterDisplayValues(
mixUrlValues(
data.locations.map((locationData) => {
data?.locations.map((locationData) => {
const matchingLocation = locations.find(
(location) => location.id === locationData.label
);
@ -81,7 +81,7 @@ export const FilterGroup = ({
label: TAGS_LABEL,
field: 'tags',
values: getSyntheticsFilterDisplayValues(
mixUrlValues(data.tags, urlParams.tags),
mixUrlValues(data?.tags, urlParams.tags),
'tags',
locations
),
@ -90,19 +90,19 @@ export const FilterGroup = ({
label: SCHEDULE_LABEL,
field: 'schedules',
values: getSyntheticsFilterDisplayValues(
mixUrlValues(data.schedules, urlParams.schedules),
mixUrlValues(data?.schedules, urlParams.schedules),
'schedules',
locations
),
},
];
if (data.projects.length > 0) {
if ((data?.projects?.length || 0) > 0) {
filters.push({
label: PROJECT_LABEL,
field: 'projects',
values: getSyntheticsFilterDisplayValues(
mixUrlValues(data.projects, urlParams.projects),
mixUrlValues(data?.projects, urlParams.projects),
'projects',
locations
),
@ -112,7 +112,12 @@ export const FilterGroup = ({
return (
<EuiFilterGroup>
{filters.map((filter, index) => (
<FilterButton key={index} filter={filter} handleFilterChange={handleFilterChange} />
<FilterButton
key={index}
filter={filter}
handleFilterChange={handleFilterChange}
loading={!data}
/>
))}
</EuiFilterGroup>
);

View file

@ -1,119 +0,0 @@
/*
* 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 { renderHook } from '@testing-library/react-hooks';
import { useFilters } from './use_filters';
import { defaultCore, WrappedHelper } from '../../../../utils/testing';
describe('useMonitorListFilters', () => {
it('returns expected results', () => {
const { result } = renderHook(() => useFilters(), { wrapper: WrappedHelper });
expect(result.current).toStrictEqual({
locations: [],
tags: [],
monitorTypes: [],
projects: [],
schedules: [],
});
expect(defaultCore.savedObjects.client.find).toHaveBeenCalledWith({
aggs: {
locations: {
terms: { field: 'synthetics-monitor.attributes.locations.id', size: 10000 },
},
monitorTypes: {
terms: { field: 'synthetics-monitor.attributes.type.keyword', size: 10000 },
},
projects: {
terms: { field: 'synthetics-monitor.attributes.project_id', size: 10000 },
},
schedules: {
terms: { field: 'synthetics-monitor.attributes.schedule.number', size: 10000 },
},
tags: {
terms: { field: 'synthetics-monitor.attributes.tags', size: 10000 },
},
},
perPage: 0,
type: 'synthetics-monitor',
});
});
it('returns expected results after data', async () => {
defaultCore.savedObjects.client.find = jest.fn().mockReturnValue({
aggregations: {
locations: {
buckets: [
{ key: 'Test 1', doc_count: 1 },
{ key: 'Test 2', doc_count: 2 },
],
},
monitorTypes: {
buckets: [
{ key: 'Test 3', doc_count: 3 },
{ key: 'Test 4', doc_count: 4 },
],
},
projects: {
buckets: [
{ key: 'Test 5', doc_count: 5 },
{ key: 'Test 6', doc_count: 6 },
],
},
schedules: {
buckets: [
{ key: 'Test 7', doc_count: 7 },
{ key: 'Test 8', doc_count: 8 },
],
},
tags: {
buckets: [
{ key: 'Test 9', doc_count: 9 },
{ key: 'Test 10', doc_count: 10 },
],
},
},
});
const { result, waitForNextUpdate } = renderHook(() => useFilters(), {
wrapper: WrappedHelper,
});
expect(result.current).toStrictEqual({
locations: [],
tags: [],
monitorTypes: [],
projects: [],
schedules: [],
});
await waitForNextUpdate();
expect(result.current).toStrictEqual({
locations: [
{ label: 'Test 1', count: 1 },
{ label: 'Test 2', count: 2 },
],
monitorTypes: [
{ label: 'Test 3', count: 3 },
{ label: 'Test 4', count: 4 },
],
projects: [
{ label: 'Test 5', count: 5 },
{ label: 'Test 6', count: 6 },
],
schedules: [
{ label: 'Test 7', count: 7 },
{ label: 'Test 8', count: 8 },
],
tags: [
{ label: 'Test 9', count: 9 },
{ label: 'Test 10', count: 10 },
],
});
});
});

View file

@ -0,0 +1,91 @@
/*
* 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 React from 'react';
import { renderHook } from '@testing-library/react-hooks';
import { useFilters } from './use_filters';
import { useDispatch } from 'react-redux';
import { WrappedHelper } from '../../../../utils/testing';
import { fetchMonitorFiltersAction } from '../../../../state';
jest.mock('react-redux', () => ({
...jest.requireActual('react-redux'),
useDispatch: jest.fn().mockReturnValue(jest.fn()),
}));
describe('useMonitorListFilters', () => {
jest.useFakeTimers();
it('returns expected results', () => {
const { result } = renderHook(() => useFilters(), { wrapper: WrappedHelper });
expect(result.current).toStrictEqual({
locations: [],
tags: [],
monitorTypes: [],
projects: [],
schedules: [],
});
});
it('dispatches action when filters are null', () => {
const Wrapper = ({ children }: { children: React.ReactElement }) => {
return (
<WrappedHelper
state={{
monitorList: {
monitorFilterOptions: null,
},
}}
>
{children}
</WrappedHelper>
);
};
const spy = jest.fn();
// @ts-ignore
useDispatch.mockReturnValue(spy);
const { result } = renderHook(() => useFilters(), { wrapper: Wrapper });
expect(result.current).toStrictEqual(null);
expect(spy).toBeCalledWith(fetchMonitorFiltersAction.get());
});
it('picks up results from filters selector', () => {
const filters = {
locations: [
{
label: 'North America',
count: 1,
},
],
tags: [],
monitorTypes: [{ label: 'http', count: 1 }],
projects: [],
schedules: [],
};
const Wrapper = ({ children }: { children: React.ReactElement }) => {
return (
<WrappedHelper
state={{
monitorList: {
monitorFilterOptions: filters,
},
}}
>
{children}
</WrappedHelper>
);
};
const spy = jest.fn();
// @ts-ignore
useDispatch.mockReturnValue(spy);
const { result } = renderHook(() => useFilters(), { wrapper: Wrapper });
expect(result.current).toStrictEqual(filters);
expect(spy).toBeCalledWith(fetchMonitorFiltersAction.get());
});
});

View file

@ -7,18 +7,17 @@
import { useMemo, useEffect, useCallback, useRef } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { useKibana } from '@kbn/kibana-react-plugin/public';
import { useFetcher } from '@kbn/observability-shared-plugin/public';
import { selectFiltersData, setListOfFiltersActions } from '../../../../state/overview_status';
import { ConfigKey } from '../../../../../../../common/runtime_types';
import { syntheticsMonitorType } from '../../../../../../../common/types/saved_objects';
import { MonitorFiltersResult } from '../../../../../../../common/runtime_types';
import {
MonitorFilterState,
selectMonitorFiltersAndQueryState,
setOverviewPageStateAction,
updateManagementPageStateAction,
fetchMonitorFiltersAction,
selectMonitorFilterOptions,
} from '../../../../state';
import { useSyntheticsRefreshContext } from '../../../../contexts';
import { SyntheticsUrlParams } from '../../../../utils/url_params';
import { useUrlParams } from '../../../../hooks';
import {
@ -28,127 +27,16 @@ import {
SyntheticsMonitorFilterField,
} from './filter_fields';
const aggs = {
monitorTypes: {
terms: {
field: `${syntheticsMonitorType}.attributes.${ConfigKey.MONITOR_TYPE}.keyword`,
size: 10000,
},
},
tags: {
terms: {
field: `${syntheticsMonitorType}.attributes.${ConfigKey.TAGS}`,
size: 10000,
},
},
locations: {
terms: {
field: `${syntheticsMonitorType}.attributes.${ConfigKey.LOCATIONS}.id`,
size: 10000,
},
},
projects: {
terms: {
field: `${syntheticsMonitorType}.attributes.${ConfigKey.PROJECT_ID}`,
size: 10000,
},
},
schedules: {
terms: {
field: `${syntheticsMonitorType}.attributes.${ConfigKey.SCHEDULE}.number`,
size: 10000,
},
},
};
type Buckets = Array<{
key: string;
doc_count: number;
}>;
interface AggsResponse {
monitorTypes: {
buckets: Buckets;
};
locations: {
buckets: Buckets;
};
tags: {
buckets: Buckets;
};
projects: {
buckets: Buckets;
};
schedules: {
buckets: Buckets;
};
}
export type FiltersList = Record<
SyntheticsMonitorFilterField,
Array<{ label: string; count: number }>
>;
export const useFilters = (): FiltersList => {
const { savedObjects } = useKibana().services;
const { data } = useFetcher(async () => {
return savedObjects?.client.find({
type: syntheticsMonitorType,
perPage: 0,
aggs,
});
}, []);
const filtersData = useSelector(selectFiltersData);
export const useFilters = (): MonitorFiltersResult | null => {
const dispatch = useDispatch();
const newFiltersData = useMemo(() => {
const { monitorTypes, tags, locations, projects, schedules } =
(data?.aggregations as AggsResponse) ?? {};
return {
monitorTypes:
monitorTypes?.buckets?.map(({ key, doc_count: count }) => ({
label: key,
count,
})) ?? [],
tags:
tags?.buckets?.map(({ key, doc_count: count }) => ({
label: key,
count,
})) ?? [],
locations:
locations?.buckets?.map(({ key, doc_count: count }) => ({
label: key,
count,
})) ?? [],
projects:
projects?.buckets
?.filter(({ key }) => key)
.map(({ key, doc_count: count }) => ({
label: key,
count,
})) ?? [],
schedules:
schedules?.buckets?.map(({ key, doc_count: count }) => ({
label: String(key),
count,
})) ?? [],
};
}, [data]);
const filtersData = useSelector(selectMonitorFilterOptions);
const { lastRefresh } = useSyntheticsRefreshContext();
useEffect(() => {
if (data) {
dispatch(setListOfFiltersActions(newFiltersData));
}
}, [data, dispatch, newFiltersData]);
dispatch(fetchMonitorFiltersAction.get());
}, [lastRefresh, dispatch]);
if (!data && filtersData) {
return filtersData;
}
return newFiltersData;
return filtersData;
};
type FilterFieldWithQuery = SyntheticsMonitorFilterField | 'query';

View file

@ -82,6 +82,7 @@ describe('<MonitorAsyncError />', () => {
sortOrder: 'asc',
sortField: `${ConfigKey.NAME}.keyword`,
},
monitorFilterOptions: null,
} as MonitorListState,
};

View file

@ -5,7 +5,7 @@
* 2.0.
*/
import { EuiFocusTrap, EuiOverlayMask, EuiPanel, EuiSpacer } from '@elastic/eui';
import { EuiFocusTrap, EuiOverlayMask, EuiPanel, EuiSpacer, EuiLoadingSpinner } from '@elastic/eui';
import React, { useRef, useState } from 'react';
import { useSelector } from 'react-redux';
import { get, invert, orderBy } from 'lodash';
@ -39,6 +39,10 @@ export const GridItemsByGroup = ({
const data = useFilters();
if (!data) {
return <EuiLoadingSpinner />;
}
const { monitorTypes, locations, projects, tags } = data;
let selectedGroup = {
key: 'location',

View file

@ -7,7 +7,10 @@
import { createAction } from '@reduxjs/toolkit';
import { UpsertMonitorError, UpsertMonitorRequest, UpsertMonitorResponse } from '..';
import { MonitorManagementListResult } from '../../../../../common/runtime_types';
import {
MonitorManagementListResult,
MonitorFiltersResult,
} from '../../../../../common/runtime_types';
import { createAsyncAction } from '../utils/actions';
import { MonitorListPageState } from './models';
@ -42,3 +45,7 @@ export const updateManagementPageStateAction = createAction<Partial<MonitorListP
);
export const cleanMonitorListState = createAction('cleanMonitorListState');
export const fetchMonitorFiltersAction = createAsyncAction<void, MonitorFiltersResult>(
'fetchMonitorFiltersAction'
);

View file

@ -7,7 +7,7 @@
import { SavedObject } from '@kbn/core-saved-objects-common';
import { UpsertMonitorRequest } from '..';
import { API_URLS } from '../../../../../common/constants';
import { API_URLS, SYNTHETICS_API_URLS } from '../../../../../common/constants';
import {
EncryptedSyntheticsMonitor,
FetchMonitorManagementListQueryArgs,
@ -15,6 +15,7 @@ import {
MonitorManagementListResultCodec,
ServiceLocationErrors,
SyntheticsMonitor,
MonitorFiltersResult,
} from '../../../../../common/runtime_types';
import { apiService } from '../../../../utils/api_service';
@ -76,3 +77,7 @@ export const fetchCreateMonitor = async ({
}): Promise<{ attributes: { errors: ServiceLocationErrors } } | SyntheticsMonitor> => {
return await apiService.post(API_URLS.SYNTHETICS_MONITORS, monitor);
};
export const fetchMonitorFilters = async (): Promise<MonitorFiltersResult> => {
return await apiService.get(SYNTHETICS_API_URLS.FILTERS);
};

View file

@ -6,7 +6,7 @@
*/
import { PayloadAction } from '@reduxjs/toolkit';
import { call, put, takeEvery, select, 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 { enableDefaultAlertingAction } from '../alert_rules';
@ -25,8 +25,9 @@ import {
fetchUpsertMonitorAction,
fetchUpsertSuccessAction,
quietFetchMonitorListAction,
fetchMonitorFiltersAction,
} from './actions';
import { fetchMonitorManagementList, fetchUpsertMonitor } from './api';
import { fetchMonitorManagementList, fetchUpsertMonitor, fetchMonitorFilters } from './api';
import { toastTitle } from './toast_title';
import { UpsertMonitorRequest } from './models';
@ -117,3 +118,14 @@ export function* upsertMonitorEffect() {
function hasPageState(value: any): value is { pageState: MonitorOverviewPageState } {
return Object.keys(value).includes('pageState');
}
export function* fetchMonitorFiltersEffect() {
yield takeLatest(
fetchMonitorFiltersAction.get,
fetchEffectFactory(
fetchMonitorFilters,
fetchMonitorFiltersAction.success,
fetchMonitorFiltersAction.fail
)
);
}

View file

@ -13,6 +13,7 @@ import {
ConfigKey,
MonitorManagementListResult,
SyntheticsMonitor,
MonitorFiltersResult,
} from '../../../../../common/runtime_types';
import { IHttpSerializedFetchError } from '../utils/http_error';
@ -27,6 +28,7 @@ import {
fetchUpsertMonitorAction,
fetchUpsertSuccessAction,
updateManagementPageStateAction,
fetchMonitorFiltersAction,
} from './actions';
export interface MonitorListState {
@ -39,6 +41,7 @@ export interface MonitorListState {
loading: boolean;
loaded: boolean;
error: IHttpSerializedFetchError | null;
monitorFilterOptions: MonitorFiltersResult | null;
}
const initialState: MonitorListState = {
@ -53,6 +56,7 @@ const initialState: MonitorListState = {
loading: false,
loaded: false,
error: null,
monitorFilterOptions: null,
};
export const monitorListReducer = createReducer(initialState, (builder) => {
@ -120,6 +124,12 @@ export const monitorListReducer = createReducer(initialState, (builder) => {
})
.addCase(cleanMonitorListState, (state) => {
return { ...initialState, pageState: state.pageState };
})
.addCase(fetchMonitorFiltersAction.success, (state, action) => {
state.monitorFilterOptions = action.payload;
})
.addCase(fetchMonitorFiltersAction.fail, (state, action) => {
state.error = action.payload;
});
});

View file

@ -36,3 +36,8 @@ export const selectMonitorUpsertStatuses = (state: SyntheticsAppState) =>
export const selectMonitorUpsertStatus = (configId: string) => (state: SyntheticsAppState) =>
state.monitorList.monitorUpsertStatuses?.[configId] ?? null;
export const selectMonitorFilterOptions = createSelector(
selectMonitorListState,
(state) => state.monitorFilterOptions
);

View file

@ -5,7 +5,6 @@
* 2.0.
*/
import { createAction } from '@reduxjs/toolkit';
import { FiltersList } from '../../components/monitors_page/common/monitor_filters/use_filters';
import { MonitorOverviewPageState } from '..';
import { createAsyncAction } from '../utils/actions';
@ -21,6 +20,4 @@ export const quietFetchOverviewStatusAction = createAsyncAction<
OverviewStatus
>('quietFetchOverviewStatusAction');
export const setListOfFiltersActions = createAction<FiltersList>('setListOfFiltersActions');
export const clearOverviewStatusErrorAction = createAction<void>('clearOverviewStatusErrorAction');

View file

@ -7,21 +7,15 @@
import { createReducer } from '@reduxjs/toolkit';
import { FiltersList } from '../../components/monitors_page/common/monitor_filters/use_filters';
import { OverviewStatusState } from '../../../../../common/runtime_types';
import { IHttpSerializedFetchError } from '..';
import {
clearOverviewStatusErrorAction,
fetchOverviewStatusAction,
setListOfFiltersActions,
} from './actions';
import { clearOverviewStatusErrorAction, fetchOverviewStatusAction } from './actions';
export interface OverviewStatusStateReducer {
loading: boolean;
loaded: boolean;
status: OverviewStatusState | null;
error: IHttpSerializedFetchError | null;
filtersData?: FiltersList | null;
}
const initialState: OverviewStatusStateReducer = {
@ -29,7 +23,6 @@ const initialState: OverviewStatusStateReducer = {
loaded: false,
status: null,
error: null,
filtersData: null,
};
export const overviewStatusReducer = createReducer(initialState, (builder) => {
@ -47,9 +40,6 @@ export const overviewStatusReducer = createReducer(initialState, (builder) => {
.addCase(fetchOverviewStatusAction.fail, (state, action) => {
state.error = action.payload;
})
.addCase(setListOfFiltersActions, (state, action) => {
state.filtersData = action.payload;
})
.addCase(clearOverviewStatusErrorAction, (state) => {
state.error = null;
});

View file

@ -10,6 +10,3 @@ import { SyntheticsAppState } from '../root_reducer';
export const selectOverviewStatus = ({
overviewStatus: { status, error, loaded },
}: SyntheticsAppState) => ({ status, error, loaded });
export const selectFiltersData = ({ overviewStatus: { filtersData } }: SyntheticsAppState) =>
filtersData;

View file

@ -24,6 +24,7 @@ import {
enableMonitorAlertEffect,
fetchMonitorListEffect,
upsertMonitorEffect,
fetchMonitorFiltersEffect,
} from './monitor_list';
import { fetchMonitorOverviewEffect } from './overview';
import { fetchServiceLocationsEffect } from './service_locations';
@ -35,6 +36,7 @@ export const rootEffect = function* root(): Generator {
yield all([
fork(fetchSyntheticsEnablementEffect),
fork(upsertMonitorEffect),
fork(fetchMonitorFiltersEffect),
fork(fetchServiceLocationsEffect),
fork(fetchMonitorListEffect),
fork(fetchSyntheticsMonitorEffect),

View file

@ -85,6 +85,13 @@ export const mockState: SyntheticsAppState = {
error: null,
loading: false,
loaded: false,
monitorFilterOptions: {
monitorTypes: [],
tags: [],
locations: [],
projects: [],
schedules: [],
},
},
overview: {
pageState: {

View file

@ -6,13 +6,12 @@
*/
import { DEFAULT_APP_CATEGORIES } from '@kbn/core/server';
import { syntheticsParamType } from '../common/types/saved_objects';
import { syntheticsMonitorType, syntheticsParamType } from '../common/types/saved_objects';
import { SYNTHETICS_RULE_TYPES } from '../common/constants/synthetics_alerts';
import { privateLocationsSavedObjectName } from '../common/saved_objects/private_locations';
import { PLUGIN } from '../common/constants/plugin';
import { UPTIME_RULE_TYPES } from '../common/constants/uptime_alerts';
import { umDynamicSettings } from './legacy_uptime/lib/saved_objects/uptime_settings';
import { syntheticsMonitorType } from './legacy_uptime/lib/saved_objects/synthetics_monitor';
import { syntheticsApiKeyObjectType } from './legacy_uptime/lib/saved_objects/service_api_key';
export const uptimeFeature = {

View file

@ -7,12 +7,12 @@
import { SavedObject, SavedObjectsClientContract } from '@kbn/core/server';
import { EncryptedSavedObjectsClient } from '@kbn/encrypted-saved-objects-plugin/server';
import { syntheticsMonitorType } from '../../../../common/types/saved_objects';
import {
SyntheticsMonitorWithSecrets,
EncryptedSyntheticsMonitor,
SyntheticsMonitor,
} from '../../../../common/runtime_types';
import { syntheticsMonitorType } from '../saved_objects/synthetics_monitor';
import { normalizeSecrets } from '../../../synthetics_service/utils/secrets';
export const getSyntheticsMonitor = async ({

View file

@ -7,6 +7,7 @@
import { EncryptedSavedObjectsPluginSetup } from '@kbn/encrypted-saved-objects-plugin/server';
import { SavedObjectsType } from '@kbn/core/server';
import { i18n } from '@kbn/i18n';
import { syntheticsMonitorType } from '../../../../common/types/saved_objects';
import {
secretKeys,
ConfigKey,
@ -14,8 +15,6 @@ import {
} from '../../../../common/constants/monitor_management';
import { monitorMigrations } from './migrations/monitors';
export const syntheticsMonitorType = 'synthetics-monitor';
const legacyConfigKeys = Object.values(LegacyConfigKey);
export const LEGACY_SYNTHETICS_MONITOR_ENCRYPTED_TYPE = {

View file

@ -9,8 +9,7 @@ import { schema, TypeOf } from '@kbn/config-schema';
import { SavedObjectsFindResponse } from '@kbn/core/server';
import { getAllLocations } from '../synthetics_service/get_all_locations';
import { EncryptedSyntheticsMonitor, ServiceLocations } from '../../common/runtime_types';
import { monitorAttributes } from '../../common/types/saved_objects';
import { syntheticsMonitorType } from '../legacy_uptime/lib/saved_objects/synthetics_monitor';
import { monitorAttributes, syntheticsMonitorType } from '../../common/types/saved_objects';
import { RouteContext } from '../legacy_uptime/routes';
export const QuerySchema = schema.object({

View file

@ -0,0 +1,111 @@
/*
* 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 { syntheticsMonitorType } from '../../../common/types/saved_objects';
import { ConfigKey } from '../../../common/runtime_types';
import { SYNTHETICS_API_URLS } from '../../../common/constants';
import { SyntheticsRestApiRouteFactory } from '../../legacy_uptime/routes/types';
type Buckets = Array<{
key: string;
doc_count: number;
}>;
interface AggsResponse {
monitorTypes: {
buckets: Buckets;
};
locations: {
buckets: Buckets;
};
tags: {
buckets: Buckets;
};
projects: {
buckets: Buckets;
};
schedules: {
buckets: Buckets;
};
}
export const getSyntheticsFilters: SyntheticsRestApiRouteFactory = () => ({
method: 'GET',
path: SYNTHETICS_API_URLS.FILTERS,
validate: {},
handler: async ({ savedObjectsClient, request, response, server }): Promise<any> => {
const data = await savedObjectsClient.find({
type: syntheticsMonitorType,
perPage: 0,
aggs,
});
const { monitorTypes, tags, locations, projects, schedules } =
(data?.aggregations as AggsResponse) ?? {};
return {
monitorTypes:
monitorTypes?.buckets?.map(({ key, doc_count: count }) => ({
label: key,
count,
})) ?? [],
tags:
tags?.buckets?.map(({ key, doc_count: count }) => ({
label: key,
count,
})) ?? [],
locations:
locations?.buckets?.map(({ key, doc_count: count }) => ({
label: key,
count,
})) ?? [],
projects:
projects?.buckets
?.filter(({ key }) => key)
.map(({ key, doc_count: count }) => ({
label: key,
count,
})) ?? [],
schedules:
schedules?.buckets?.map(({ key, doc_count: count }) => ({
label: String(key),
count,
})) ?? [],
};
},
});
const aggs = {
monitorTypes: {
terms: {
field: `${syntheticsMonitorType}.attributes.${ConfigKey.MONITOR_TYPE}.keyword`,
size: 10000,
},
},
tags: {
terms: {
field: `${syntheticsMonitorType}.attributes.${ConfigKey.TAGS}`,
size: 10000,
},
},
locations: {
terms: {
field: `${syntheticsMonitorType}.attributes.${ConfigKey.LOCATIONS}.id`,
size: 10000,
},
},
projects: {
terms: {
field: `${syntheticsMonitorType}.attributes.${ConfigKey.PROJECT_ID}`,
size: 10000,
},
},
schedules: {
terms: {
field: `${syntheticsMonitorType}.attributes.${ConfigKey.SCHEDULE}.number`,
size: 10000,
},
},
};

View file

@ -52,6 +52,7 @@ import { createNetworkEventsRoute } from './network_events';
import { addPrivateLocationRoute } from './settings/private_locations/add_private_location';
import { deletePrivateLocationRoute } from './settings/private_locations/delete_private_location';
import { getPrivateLocationsRoute } from './settings/private_locations/get_private_locations';
import { getSyntheticsFilters } from './filters/filters';
export const syntheticsAppRestApiRoutes: SyntheticsRestApiRouteFactory[] = [
addSyntheticsMonitorRoute,
@ -94,6 +95,7 @@ export const syntheticsAppRestApiRoutes: SyntheticsRestApiRouteFactory[] = [
addPrivateLocationRoute,
deletePrivateLocationRoute,
getPrivateLocationsRoute,
getSyntheticsFilters,
];
export const syntheticsAppStreamingApiRoutes: SyntheticsStreamingRouteFactory[] = [

View file

@ -14,6 +14,7 @@ import {
} from '@kbn/core/server';
import { isValidNamespace } from '@kbn/fleet-plugin/common';
import { DEFAULT_SPACE_ID } from '@kbn/spaces-plugin/common';
import { syntheticsMonitorType } from '../../../common/types/saved_objects';
import { getSyntheticsPrivateLocations } from '../../legacy_uptime/lib/saved_objects/private_locations';
import {
ConfigKey,
@ -29,7 +30,6 @@ import {
DEFAULT_FIELDS,
DEFAULT_NAMESPACE_STRING,
} from '../../../common/constants/monitor_defaults';
import { syntheticsMonitorType } from '../../legacy_uptime/lib/saved_objects/synthetics_monitor';
import { validateMonitor } from './monitor_validation';
import { sendTelemetryEvents, formatTelemetryEvent } from '../telemetry/monitor_upgrade_sender';
import { formatSecrets } from '../../synthetics_service/utils/secrets';

View file

@ -6,6 +6,7 @@
*/
import { SavedObject, SavedObjectsUpdateResponse } from '@kbn/core/server';
import { SavedObjectError } from '@kbn/core-saved-objects-common';
import { syntheticsMonitorType } from '../../../../common/types/saved_objects';
import { FailedPolicyUpdate } from '../../../synthetics_service/private_location/synthetics_private_location';
import { RouteContext } from '../../../legacy_uptime/routes';
import {
@ -17,7 +18,6 @@ import {
SyntheticsMonitor,
SyntheticsMonitorWithSecrets,
} from '../../../../common/runtime_types';
import { syntheticsMonitorType } from '../../../legacy_uptime/lib/saved_objects/synthetics_monitor';
import {
formatTelemetryUpdateEvent,
sendTelemetryEvents,

View file

@ -7,6 +7,7 @@
import { schema } from '@kbn/config-schema';
import { SavedObjectsClientContract, SavedObjectsErrorHelpers } from '@kbn/core/server';
import { DEFAULT_SPACE_ID } from '@kbn/spaces-plugin/common';
import { syntheticsMonitorType } from '../../../common/types/saved_objects';
import { deletePermissionError } from '../../synthetics_service/private_location/synthetics_private_location';
import {
ConfigKey,
@ -17,7 +18,6 @@ import {
} from '../../../common/runtime_types';
import { RouteContext, SyntheticsRestApiRouteFactory } from '../../legacy_uptime/routes/types';
import { API_URLS } from '../../../common/constants';
import { syntheticsMonitorType } from '../../legacy_uptime/lib/saved_objects/synthetics_monitor';
import { getMonitorNotFoundResponse } from '../synthetics_service/service_errors';
import {
formatTelemetryDeleteEvent,

View file

@ -6,10 +6,10 @@
*/
import { schema } from '@kbn/config-schema';
import { i18n } from '@kbn/i18n';
import { syntheticsMonitorType } from '../../../common/types/saved_objects';
import { ConfigKey } from '../../../common/runtime_types';
import { SyntheticsRestApiRouteFactory } from '../../legacy_uptime/routes/types';
import { API_URLS } from '../../../common/constants';
import { syntheticsMonitorType } from '../../legacy_uptime/lib/saved_objects/synthetics_monitor';
import { getMonitors, getKqlFilter } from '../common';
import { INSUFFICIENT_FLEET_PERMISSIONS } from '../../synthetics_service/project_monitor/project_monitor_formatter';
import { deleteMonitorBulk } from './bulk_cruds/delete_monitor_bulk';

View file

@ -9,6 +9,7 @@ import { schema } from '@kbn/config-schema';
import { SavedObjectsUpdateResponse, SavedObject } from '@kbn/core/server';
import { SavedObjectsErrorHelpers } from '@kbn/core/server';
import { DEFAULT_SPACE_ID } from '@kbn/spaces-plugin/common';
import { syntheticsMonitorType } from '../../../common/types/saved_objects';
import { getSyntheticsPrivateLocations } from '../../legacy_uptime/lib/saved_objects/private_locations';
import {
MonitorFields,
@ -19,7 +20,6 @@ import {
} from '../../../common/runtime_types';
import { RouteContext, SyntheticsRestApiRouteFactory } from '../../legacy_uptime/routes/types';
import { API_URLS } from '../../../common/constants';
import { syntheticsMonitorType } from '../../legacy_uptime/lib/saved_objects/synthetics_monitor';
import { validateMonitor } from './monitor_validation';
import { getMonitorNotFoundResponse } from '../synthetics_service/service_errors';
import {

View file

@ -6,6 +6,7 @@
*/
import { schema } from '@kbn/config-schema';
import { SavedObjectsErrorHelpers } from '@kbn/core/server';
import { syntheticsMonitorType } from '../../../common/types/saved_objects';
import { getAllMonitors } from '../../saved_objects/synthetics_monitor/get_all_monitors';
import { isStatusEnabled } from '../../../common/runtime_types/monitor_management/alert_config';
import {
@ -16,7 +17,6 @@ import {
import { UMServerLibs } from '../../legacy_uptime/lib/lib';
import { SyntheticsRestApiRouteFactory } from '../../legacy_uptime/routes/types';
import { API_URLS, SYNTHETICS_API_URLS } from '../../../common/constants';
import { syntheticsMonitorType } from '../../legacy_uptime/lib/saved_objects/synthetics_monitor';
import { getMonitorNotFoundResponse } from '../synthetics_service/service_errors';
import {
getMonitorFilters,

View file

@ -5,10 +5,10 @@
* 2.0.
*/
import { schema } from '@kbn/config-schema';
import { syntheticsMonitorType } from '../../../common/types/saved_objects';
import { ConfigKey } from '../../../common/runtime_types';
import { SyntheticsRestApiRouteFactory } from '../../legacy_uptime/routes/types';
import { API_URLS } from '../../../common/constants';
import { syntheticsMonitorType } from '../../legacy_uptime/lib/saved_objects/synthetics_monitor';
import { getMonitors } from '../common';
const querySchema = schema.object({

View file

@ -7,6 +7,7 @@
import { schema } from '@kbn/config-schema';
import { v4 as uuidv4 } from 'uuid';
import { DEFAULT_SPACE_ID } from '@kbn/spaces-plugin/common';
import { syntheticsMonitorType } from '../../../common/types/saved_objects';
import { TestNowResponse } from '../../../common/types';
import {
ConfigKey,
@ -15,7 +16,6 @@ import {
} from '../../../common/runtime_types';
import { SyntheticsRestApiRouteFactory } from '../../legacy_uptime/routes/types';
import { API_URLS } from '../../../common/constants';
import { syntheticsMonitorType } from '../../legacy_uptime/lib/saved_objects/synthetics_monitor';
import { normalizeSecrets } from '../../synthetics_service/utils/secrets';
export const testNowMonitorRoute: SyntheticsRestApiRouteFactory = () => ({

View file

@ -12,10 +12,10 @@ import {
} from '@kbn/core-saved-objects-api-server';
import pMap from 'p-map';
import { intersection } from 'lodash';
import { syntheticsMonitorType } from '../../../common/types/saved_objects';
import { periodToMs } from '../../routes/overview_status/overview_status';
import { UptimeServerSetup } from '../../legacy_uptime/lib/adapters';
import { getAllLocations } from '../../synthetics_service/get_all_locations';
import { syntheticsMonitorType } from '../../legacy_uptime/lib/saved_objects/synthetics_monitor';
import {
ConfigKey,
EncryptedSyntheticsMonitor,

View file

@ -13,6 +13,7 @@ import {
} from '@kbn/core/server';
import { i18n } from '@kbn/i18n';
import { EncryptedSavedObjectsClient } from '@kbn/encrypted-saved-objects-plugin/server';
import { syntheticsMonitorType } from '../../../common/types/saved_objects';
import { RouteContext } from '../../legacy_uptime/routes';
import { getAllLocations } from '../get_all_locations';
import { syncNewMonitorBulk } from '../../routes/monitor_cruds/bulk_cruds/add_monitor_bulk';
@ -29,7 +30,6 @@ import {
MonitorFields,
PrivateLocation,
} from '../../../common/runtime_types';
import { syntheticsMonitorType } from '../../legacy_uptime/lib/saved_objects/synthetics_monitor';
import type { UptimeServerSetup } from '../../legacy_uptime/lib/adapters';
import { formatSecrets, normalizeSecrets } from '../utils/secrets';
import {

View file

@ -11,6 +11,7 @@ import {
SavedObjectsFindResult,
} from '@kbn/core/server';
import { EncryptedSavedObjectsPluginStart } from '@kbn/encrypted-saved-objects-plugin/server';
import { syntheticsMonitorType } from '../../../common/types/saved_objects';
import { RouteContext } from '../../legacy_uptime/routes';
import { normalizeSecrets } from '../utils';
import { UptimeServerSetup } from '../../legacy_uptime/lib/adapters';
@ -33,7 +34,6 @@ import {
SyntheticsMonitorWithSecrets,
MonitorServiceLocation,
} from '../../../common/runtime_types';
import { syntheticsMonitorType } from '../../legacy_uptime/lib/saved_objects/synthetics_monitor';
export class SyntheticsMonitorClient {
public syntheticsService: SyntheticsService;

View file

@ -19,12 +19,11 @@ import { EncryptedSavedObjectsClient } from '@kbn/encrypted-saved-objects-plugin
import pMap from 'p-map';
import { DEFAULT_SPACE_ID } from '@kbn/spaces-plugin/common';
import { ALL_SPACES_ID } from '@kbn/spaces-plugin/common/constants';
import { syntheticsParamType } from '../../common/types/saved_objects';
import { syntheticsMonitorType, syntheticsParamType } from '../../common/types/saved_objects';
import { sendErrorTelemetryEvents } from '../routes/telemetry/monitor_upgrade_sender';
import { UptimeServerSetup } from '../legacy_uptime/lib/adapters';
import { installSyntheticsIndexTemplates } from '../routes/synthetics_service/install_index_templates';
import { getAPIKeyForSyntheticsService } from './get_api_key';
import { syntheticsMonitorType } from '../legacy_uptime/lib/saved_objects/synthetics_monitor';
import { getEsHosts } from './get_es_hosts';
import { ServiceConfig } from '../../common/config';
import { ServiceAPIClient, ServiceData } from './service_api_client';

View file

@ -13,11 +13,11 @@ import { formatKibanaNamespace } from '@kbn/synthetics-plugin/common/formatters'
import { API_URLS } from '@kbn/synthetics-plugin/common/constants';
import { DEFAULT_FIELDS } from '@kbn/synthetics-plugin/common/constants/monitor_defaults';
import { ALL_SPACES_ID } from '@kbn/security-plugin/common/constants';
import { syntheticsMonitorType } from '@kbn/synthetics-plugin/server/legacy_uptime/lib/saved_objects/synthetics_monitor';
import { format as formatUrl } from 'url';
import supertest from 'supertest';
import { serviceApiKeyPrivileges } from '@kbn/synthetics-plugin/server/synthetics_service/get_api_key';
import { syntheticsMonitorType } from '@kbn/synthetics-plugin/common/types/saved_objects';
import { FtrProviderContext } from '../../ftr_provider_context';
import { getFixtureJson } from '../uptime/rest/helper/get_fixture_json';

View file

@ -13,7 +13,7 @@ import { omit } from 'lodash';
import { secretKeys } from '@kbn/synthetics-plugin/common/constants/monitor_management';
import { PackagePolicy } from '@kbn/fleet-plugin/common';
import expect from '@kbn/expect';
import { syntheticsMonitorType } from '@kbn/synthetics-plugin/server/legacy_uptime/lib/saved_objects/synthetics_monitor';
import { syntheticsMonitorType } from '@kbn/synthetics-plugin/common/types/saved_objects';
import { FtrProviderContext } from '../../ftr_provider_context';
import { getFixtureJson } from '../uptime/rest/helper/get_fixture_json';
import { comparePolicies, getTestSyntheticsPolicy } from './sample_data/test_policy';

View file

@ -9,13 +9,13 @@ import expect from '@kbn/expect';
import { ConfigKey, ProjectMonitorsRequest } from '@kbn/synthetics-plugin/common/runtime_types';
import { API_URLS, SYNTHETICS_API_URLS } from '@kbn/synthetics-plugin/common/constants';
import { formatKibanaNamespace } from '@kbn/synthetics-plugin/common/formatters';
import { syntheticsMonitorType } from '@kbn/synthetics-plugin/server/legacy_uptime/lib/saved_objects/synthetics_monitor';
import { REQUEST_TOO_LARGE } from '@kbn/synthetics-plugin/server/routes/monitor_cruds/add_monitor_project';
import { PackagePolicy } from '@kbn/fleet-plugin/common';
import {
PROFILE_VALUES_ENUM,
PROFILES_MAP,
} from '@kbn/synthetics-plugin/common/constants/monitor_defaults';
import { syntheticsMonitorType } from '@kbn/synthetics-plugin/common/types/saved_objects';
import { FtrProviderContext } from '../../ftr_provider_context';
import { getFixtureJson } from '../uptime/rest/helper/get_fixture_json';
import { PrivateLocationTestService } from './services/private_location_test_service';

View file

@ -9,9 +9,9 @@ import { ConfigKey, ProjectMonitorsRequest } from '@kbn/synthetics-plugin/common
import { INSUFFICIENT_FLEET_PERMISSIONS } from '@kbn/synthetics-plugin/server/synthetics_service/project_monitor/project_monitor_formatter';
import { REQUEST_TOO_LARGE } from '@kbn/synthetics-plugin/server/routes/monitor_cruds/delete_monitor_project';
import { API_URLS } from '@kbn/synthetics-plugin/common/constants';
import { syntheticsMonitorType } from '@kbn/synthetics-plugin/server/legacy_uptime/lib/saved_objects/synthetics_monitor';
import { PackagePolicy } from '@kbn/fleet-plugin/common';
import expect from '@kbn/expect';
import { syntheticsMonitorType } from '@kbn/synthetics-plugin/common/types/saved_objects';
import { FtrProviderContext } from '../../ftr_provider_context';
import { getFixtureJson } from '../uptime/rest/helper/get_fixture_json';
import { PrivateLocationTestService } from './services/private_location_test_service';

View file

@ -10,6 +10,7 @@ import { ConfigKey, HTTPFields } from '@kbn/synthetics-plugin/common/runtime_typ
import { API_URLS, SYNTHETICS_API_URLS } from '@kbn/synthetics-plugin/common/constants';
import { secretKeys } from '@kbn/synthetics-plugin/common/constants/monitor_management';
import { syntheticsMonitorType } from '@kbn/synthetics-plugin/common/types/saved_objects';
import { FtrProviderContext } from '../../ftr_provider_context';
import { getFixtureJson } from '../uptime/rest/helper/get_fixture_json';
import { Spaces } from '../../../alerting_api_integration/spaces_only/scenarios';
@ -30,7 +31,7 @@ export default function ({ getService }: FtrProviderContext) {
after(async () => {
await objectRemover.removeAll();
await kibanaServer.savedObjects.clean({ types: ['synthetics-monitor', 'synthetic-monitor'] });
await kibanaServer.savedObjects.clean({ types: [syntheticsMonitorType] });
});
before(() => {
@ -39,7 +40,7 @@ export default function ({ getService }: FtrProviderContext) {
beforeEach(async () => {
httpMonitorJson = _httpMonitorJson;
await kibanaServer.savedObjects.clean({ types: ['synthetics-monitor', 'synthetic-monitor'] });
await kibanaServer.savedObjects.clean({ types: [syntheticsMonitorType] });
});
afterEach(async () => {

View file

@ -0,0 +1,80 @@
/*
* 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 { API_URLS, SYNTHETICS_API_URLS } from '@kbn/synthetics-plugin/common/constants';
import expect from '@kbn/expect';
import { syntheticsMonitorType } from '@kbn/synthetics-plugin/common/types/saved_objects';
import { FtrProviderContext } from '../../ftr_provider_context';
export default function ({ getService }: FtrProviderContext) {
describe('getMonitorFilters', function () {
this.tags('skipCloud');
const kibanaServer = getService('kibanaServer');
const supertest = getService('supertest');
after(async () => {
await kibanaServer.savedObjects.clean({ types: [syntheticsMonitorType] });
});
beforeEach(async () => {
await kibanaServer.savedObjects.clean({ types: [syntheticsMonitorType] });
});
it('get list of filters', async () => {
const apiResponse = await supertest.get(SYNTHETICS_API_URLS.FILTERS).expect(200);
expect(apiResponse.body).eql({
monitorTypes: [],
tags: [],
locations: [],
projects: [],
schedules: [],
});
});
it('get list of filters with monitorTypes', async () => {
const newMonitor = {
name: 'Sample name',
type: 'http',
urls: 'https://elastic.co',
tags: ['apm', 'synthetics'],
locations: [
{
id: 'eu-west-01',
label: 'Europe West',
geo: {
lat: 33.2343132435,
lon: 73.2342343434,
},
url: 'https://example-url.com',
isServiceManaged: true,
},
],
};
await supertest
.post(API_URLS.SYNTHETICS_MONITORS)
.set('kbn-xsrf', 'true')
.send(newMonitor)
.expect(200);
const apiResponse = await supertest.get(SYNTHETICS_API_URLS.FILTERS).expect(200);
expect(apiResponse.body).eql({
monitorTypes: [{ label: 'http', count: 1 }],
tags: [
{ label: 'apm', count: 1 },
{ label: 'synthetics', count: 1 },
],
locations: [{ label: 'eu-west-01', count: 1 }],
projects: [],
schedules: [{ label: '3', count: 1 }],
});
});
});
}

View file

@ -16,6 +16,7 @@ export default function ({ getService, loadTestFile }: FtrProviderContext) {
await esDeleteAllIndices('synthetics*');
});
loadTestFile(require.resolve('./get_filters'));
loadTestFile(require.resolve('./enable_default_alerting'));
loadTestFile(require.resolve('./get_monitor'));
loadTestFile(require.resolve('./get_monitor_overview'));

View file

@ -6,7 +6,7 @@
*/
import { API_URLS } from '@kbn/synthetics-plugin/common/constants';
import { syntheticsMonitorType } from '@kbn/synthetics-plugin/server/legacy_uptime/lib/saved_objects/synthetics_monitor';
import { syntheticsMonitorType } from '@kbn/synthetics-plugin/common/types/saved_objects';
import { FtrProviderContext } from '../../../ftr_provider_context';
import { KibanaSupertestProvider } from '../../../../../../test/api_integration/services/supertest';