[Synthetics] Sync global parameters is called in the endpoints to add, edit or delete global params (#216197)

This PR closes #215668.

The global parameters are synched in the endpoints where they are
created, edited or deleted.

---------

Co-authored-by: Shahzad <shahzad31comp@gmail.com>
This commit is contained in:
Francesco Fagnani 2025-04-15 16:53:14 +02:00 committed by GitHub
parent 7b629a9908
commit f693e7218e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
17 changed files with 95 additions and 87 deletions

View file

@ -46193,8 +46193,6 @@
"xpack.synthetics.settings.noSpace.error": "Les noms d'index ne doivent pas contenir d'espace",
"xpack.synthetics.settings.saveSuccess": "Paramètres enregistrés !",
"xpack.synthetics.settings.statusRule.inspect": "Impossible d'inspecter le type de règle de statut du moniteur.",
"xpack.synthetics.settings.syncGlobalParams": "Paramètres globaux appliqués correctement à tous les moniteurs",
"xpack.synthetics.settings.syncGlobalParams.fail": "Impossible d'appliquer les paramètres globaux à tous les moniteurs",
"xpack.synthetics.settings.title": "Paramètres",
"xpack.synthetics.settingsBreadcrumbText": "Paramètres",
"xpack.synthetics.settingsRoute.allChecks": "Toutes les vérifications",

View file

@ -46160,8 +46160,6 @@
"xpack.synthetics.settings.noSpace.error": "インデックス名にはスペースを使用できません",
"xpack.synthetics.settings.saveSuccess": "設定が保存されました。",
"xpack.synthetics.settings.statusRule.inspect": "監視ステータスルールタイプを検査できませんでした。",
"xpack.synthetics.settings.syncGlobalParams": "グローバルパラメーターをすべてのモニターに正常に適用しました",
"xpack.synthetics.settings.syncGlobalParams.fail": "グローバルパラメーターをすべてのモニターに適用できませんでした",
"xpack.synthetics.settings.title": "設定",
"xpack.synthetics.settingsBreadcrumbText": "設定",
"xpack.synthetics.settingsRoute.allChecks": "すべてのチェック",

View file

@ -46232,8 +46232,6 @@
"xpack.synthetics.settings.noSpace.error": "索引名称不得包含空格",
"xpack.synthetics.settings.saveSuccess": "设置已保存!",
"xpack.synthetics.settings.statusRule.inspect": "无法检查监测状态规则类型。",
"xpack.synthetics.settings.syncGlobalParams": "已成功将全局参数应用到所有监测",
"xpack.synthetics.settings.syncGlobalParams.fail": "未能将全局参数应用到所有监测",
"xpack.synthetics.settings.title": "设置",
"xpack.synthetics.settingsBreadcrumbText": "设置",
"xpack.synthetics.settingsRoute.allChecks": "所有检查",

View file

@ -35,7 +35,6 @@ import { ListParamItem } from './params_list';
import { SyntheticsParams } from '../../../../../../common/runtime_types';
import { useFormWrapped } from '../../../../../hooks/use_form_wrapped';
import { AddParamForm } from './add_param_form';
import { syncGlobalParamsAction } from '../../../state/settings';
export const AddParamFlyout = ({
items,
@ -114,7 +113,6 @@ export const AddParamFlyout = ({
if (savedData && !isSaving) {
closeFlyout();
dispatch(getGlobalParamAction.get());
dispatch(syncGlobalParamsAction.get());
}
}, [savedData, isSaving, closeFlyout, dispatch]);

View file

@ -15,7 +15,6 @@ import {
deleteGlobalParamsAction,
selectGlobalParamState,
} from '../../../state/global_params';
import { syncGlobalParamsAction } from '../../../state/settings';
import { NO_LABEL, YES_LABEL } from '../../monitors_page/management/monitor_list_table/labels';
import { ListParamItem } from './params_list';
@ -38,7 +37,6 @@ export const DeleteParam = ({
if (!isDeleting && (listOfParams ?? []).length === 0) {
setIsDeleteModalVisible(false);
dispatch(getGlobalParamAction.get());
dispatch(syncGlobalParamsAction.get());
}
}, [isDeleting, setIsDeleteModalVisible, name, dispatch, listOfParams]);

View file

@ -29,7 +29,6 @@ import {
fetchLocationMonitorsEffect,
setDynamicSettingsEffect,
} from './settings/effects';
import { syncGlobalParamsEffect } from './settings';
import { privateLocationsEffects } from './private_locations/effects';
import { fetchNetworkEventsEffect } from './network_events/effects';
import { fetchSyntheticsMonitorEffect } from './monitor_details';
@ -64,7 +63,6 @@ export const rootEffect = function* root(): Generator {
fork(fetchLocationMonitorsEffect),
fork(setDynamicSettingsEffect),
fork(fetchAlertConnectorsEffect),
fork(syncGlobalParamsEffect),
fork(enableDefaultAlertingEffect),
fork(enableMonitorAlertEffect),
fork(updateDefaultAlertingEffect),

View file

@ -14,12 +14,7 @@ import { overviewStatusReducer, OverviewStatusStateReducer } from './overview_st
import { browserJourneyReducer } from './browser_journey';
import { defaultAlertingReducer, DefaultAlertingState } from './alert_rules';
import { manualTestRunsReducer, ManualTestRunsState } from './manual_test_runs';
import {
dynamicSettingsReducer,
DynamicSettingsState,
settingsReducer,
SettingsState,
} from './settings';
import { dynamicSettingsReducer, DynamicSettingsState } from './settings';
import { elasticsearchReducer, QueriesState } from './elasticsearch';
import { PrivateLocationsState, privateLocationsStateReducer } from './private_locations';
import { networkEventsReducer, NetworkEventsState } from './network_events';
@ -51,7 +46,6 @@ export interface SyntheticsAppState {
overviewStatus: OverviewStatusStateReducer;
privateLocations: PrivateLocationsState;
serviceLocations: ServiceLocationsState;
settings: SettingsState;
syntheticsEnablement: SyntheticsEnablementState;
ui: UiState;
}
@ -74,7 +68,6 @@ export const rootReducer = combineReducers<SyntheticsAppState>({
overviewStatus: overviewStatusReducer,
privateLocations: privateLocationsStateReducer,
serviceLocations: serviceLocationsReducer,
settings: settingsReducer,
syntheticsEnablement: syntheticsEnablementReducer,
ui: uiReducer,
});

View file

@ -17,6 +17,4 @@ export const setDynamicSettingsAction = createAsyncAction<DynamicSettings, Dynam
);
export const getConnectorsAction = createAsyncAction<void, ActionConnector[]>('GET CONNECTORS');
export const syncGlobalParamsAction = createAsyncAction<void, boolean>('SYNC GLOBAL PARAMS');
export const getLocationMonitorsAction = createAsyncAction<void, any>('GET LOCATION MONITORS');

View file

@ -73,7 +73,3 @@ export const fetchActionTypes = async (): Promise<ActionType[]> => {
feature_id: 'uptime',
});
};
export const syncGlobalParamsAPI = async (): Promise<boolean> => {
return await apiService.get(SYNTHETICS_API_URLS.SYNC_GLOBAL_PARAMS);
};

View file

@ -15,31 +15,16 @@ import {
getConnectorsAction,
setDynamicSettingsAction,
getDynamicSettingsAction,
syncGlobalParamsAction,
getLocationMonitorsAction,
} from './actions';
import { fetchEffectFactory } from '../utils/fetch_effect';
import {
fetchConnectors,
setDynamicSettings,
syncGlobalParamsAPI,
getDynamicSettings,
fetchLocationMonitors,
} from './api';
export function* syncGlobalParamsEffect() {
yield takeLeading(
syncGlobalParamsAction.get,
fetchEffectFactory(
syncGlobalParamsAPI,
syncGlobalParamsAction.success,
syncGlobalParamsAction.fail,
successMessage,
failureMessage
)
);
}
export function* fetchLocationMonitorsEffect() {
yield takeLeading(
String(getLocationMonitorsAction.get),
@ -62,14 +47,6 @@ export function* fetchDynamicSettingsEffect() {
);
}
const successMessage = i18n.translate('xpack.synthetics.settings.syncGlobalParams', {
defaultMessage: 'Successfully applied global params to all monitors',
});
const failureMessage = i18n.translate('xpack.synthetics.settings.syncGlobalParams.fail', {
defaultMessage: 'Failed to apply global params to all monitors',
});
export function* setDynamicSettingsEffect() {
const couldNotSaveSettingsText = i18n.translate('xpack.synthetics.settings.error.couldNotSave', {
defaultMessage: 'Could not save settings!',

View file

@ -15,7 +15,6 @@ import {
setDynamicSettingsAction,
} from './actions';
import { ActionConnector } from './api';
import { syncGlobalParamsAction } from './actions';
export interface LocationMonitor {
id: string;
@ -85,34 +84,6 @@ export const dynamicSettingsReducer = createReducer(initialState, (builder) => {
});
});
export interface SettingsState {
success: boolean | null;
loading: boolean;
error: IHttpSerializedFetchError | null;
}
const initialSettingState: SettingsState = {
success: null,
loading: false,
error: null,
};
export const settingsReducer = createReducer(initialSettingState, (builder) => {
builder
.addCase(syncGlobalParamsAction.get, (state) => {
state.loading = true;
})
.addCase(syncGlobalParamsAction.success, (state, action) => {
state.success = action.payload;
state.loading = false;
})
.addCase(syncGlobalParamsAction.fail, (state, action) => {
state.error = action.payload;
state.loading = false;
state.success = false;
});
});
export * from './actions';
export * from './effects';
export * from './selectors';

View file

@ -120,11 +120,6 @@ export const mockState: SyntheticsAppState = {
error: null,
data: [],
},
settings: {
loading: false,
error: null,
success: null,
},
dynamicSettings: {
loading: false,
locationMonitors: [],

View file

@ -9,6 +9,7 @@ import { schema } from '@kbn/config-schema';
import { ALL_SPACES_ID } from '@kbn/security-plugin/common/constants';
import { DEFAULT_SPACE_ID } from '@kbn/spaces-plugin/common';
import { SavedObject, SavedObjectsBulkCreateObject } from '@kbn/core-saved-objects-api-server';
import { syncSpaceGlobalParams } from '../../../synthetics_service/sync_global_params';
import { SyntheticsRestApiRouteFactory } from '../../types';
import {
SyntheticsParamRequest,
@ -41,7 +42,7 @@ export const addSyntheticsParamsRoute: SyntheticsRestApiRouteFactory<
body: schema.oneOf([ParamsObjectSchema, schema.arrayOf(ParamsObjectSchema)]),
},
},
handler: async ({ request, response, server, savedObjectsClient }) => {
handler: async ({ request, response, server, savedObjectsClient, syntheticsMonitorClient }) => {
try {
const { id: spaceId } = (await server.spaces?.spacesService.getActiveSpace(request)) ?? {
id: DEFAULT_SPACE_ID,
@ -56,6 +57,14 @@ export const addSyntheticsParamsRoute: SyntheticsRestApiRouteFactory<
savedObjectsData
);
void syncSpaceGlobalParams({
spaceId,
logger: server.logger,
encryptedSavedObjects: server.encryptedSavedObjects,
savedObjects: server.coreStart.savedObjects,
syntheticsMonitorClient,
});
if (savedObjectsData.length > 1) {
return result.saved_objects.map((savedObject) => {
return toClientResponse(savedObject);

View file

@ -7,6 +7,7 @@
import { schema } from '@kbn/config-schema';
import { i18n } from '@kbn/i18n';
import { syncSpaceGlobalParams } from '../../../synthetics_service/sync_global_params';
import { SyntheticsRestApiRouteFactory } from '../../types';
import { syntheticsParamType } from '../../../../common/types/saved_objects';
import { SYNTHETICS_API_URLS } from '../../../../common/constants';
@ -35,7 +36,14 @@ export const deleteSyntheticsParamsRoute: SyntheticsRestApiRouteFactory<
}),
},
},
handler: async ({ savedObjectsClient, request, response }) => {
handler: async ({
savedObjectsClient,
request,
response,
server,
spaceId,
syntheticsMonitorClient,
}) => {
const { ids } = request.body ?? {};
const { id: paramId } = request.params ?? {};
@ -61,6 +69,15 @@ export const deleteSyntheticsParamsRoute: SyntheticsRestApiRouteFactory<
idsToDelete.map((id) => ({ type: syntheticsParamType, id })),
{ force: true }
);
void syncSpaceGlobalParams({
spaceId,
logger: server.logger,
encryptedSavedObjects: server.encryptedSavedObjects,
savedObjects: server.coreStart.savedObjects,
syntheticsMonitorClient,
});
return result.statuses.map(({ id, success }) => ({ id, deleted: success }));
},
});

View file

@ -6,6 +6,7 @@
*/
import { schema } from '@kbn/config-schema';
import { syncSpaceGlobalParams } from '../../../synthetics_service/sync_global_params';
import { SyntheticsRestApiRouteFactory } from '../../types';
import { syntheticsParamType } from '../../../../common/types/saved_objects';
import { SYNTHETICS_API_URLS } from '../../../../common/constants';
@ -27,13 +28,22 @@ export const deleteSyntheticsParamsBulkRoute: SyntheticsRestApiRouteFactory<
}),
},
},
handler: async ({ savedObjectsClient, request }) => {
handler: async ({ savedObjectsClient, request, server, spaceId, syntheticsMonitorClient }) => {
const { ids } = request.body;
const result = await savedObjectsClient.bulkDelete(
ids.map((id) => ({ type: syntheticsParamType, id })),
{ force: true }
);
void syncSpaceGlobalParams({
spaceId,
logger: server.logger,
encryptedSavedObjects: server.encryptedSavedObjects,
savedObjects: server.coreStart.savedObjects,
syntheticsMonitorClient,
});
return result.statuses.map(({ id, success }) => ({ id, deleted: success }));
},
});

View file

@ -8,6 +8,7 @@
import { schema, TypeOf } from '@kbn/config-schema';
import { SavedObject, SavedObjectsErrorHelpers } from '@kbn/core/server';
import { isEmpty } from 'lodash';
import { syncSpaceGlobalParams } from '../../../synthetics_service/sync_global_params';
import { validateRouteSpaceName } from '../../common';
import { SyntheticsRestApiRouteFactory } from '../../types';
import { SyntheticsParamRequest, SyntheticsParams } from '../../../../common/runtime_types';
@ -47,7 +48,8 @@ export const editSyntheticsParamsRoute: SyntheticsRestApiRouteFactory<
},
},
handler: async (routeContext) => {
const { savedObjectsClient, request, response, spaceId, server } = routeContext;
const { savedObjectsClient, request, response, spaceId, server, syntheticsMonitorClient } =
routeContext;
const { invalidResponse } = await validateRouteSpaceName(routeContext);
if (invalidResponse) return invalidResponse;
@ -83,6 +85,14 @@ export const editSyntheticsParamsRoute: SyntheticsRestApiRouteFactory<
newParam
)) as SavedObject<SyntheticsParams>;
void syncSpaceGlobalParams({
spaceId,
logger: server.logger,
encryptedSavedObjects: server.encryptedSavedObjects,
savedObjects: server.coreStart.savedObjects,
syntheticsMonitorClient,
});
return { id: responseId, key, tags, description, namespaces, value };
} catch (getErr) {
if (SavedObjectsErrorHelpers.isNotFoundError(getErr)) {

View file

@ -0,0 +1,44 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import { Logger } from '@kbn/logging';
import { EncryptedSavedObjectsPluginStart } from '@kbn/encrypted-saved-objects-plugin/server/plugin';
import { SavedObjectsServiceStart } from '@kbn/core/server';
import pRetry from 'p-retry';
import { getPrivateLocations } from './get_private_locations';
import { SyntheticsMonitorClient } from './synthetics_monitor/synthetics_monitor_client';
export const syncSpaceGlobalParams = async ({
spaceId,
savedObjects,
logger,
syntheticsMonitorClient,
encryptedSavedObjects,
}: {
spaceId: string;
savedObjects: SavedObjectsServiceStart;
logger: Logger;
syntheticsMonitorClient: SyntheticsMonitorClient;
encryptedSavedObjects: EncryptedSavedObjectsPluginStart;
}) => {
try {
await pRetry(async () => {
logger.debug(`Syncing global parameters of space with id ${spaceId}`);
const savedObjectsClient = savedObjects.createInternalRepository();
const allPrivateLocations = await getPrivateLocations(savedObjectsClient);
await syntheticsMonitorClient.syncGlobalParams({
spaceId,
allPrivateLocations,
soClient: savedObjectsClient,
encryptedSavedObjects,
});
logger.debug(`Sync of global parameters for space with id ${spaceId} succeeded`);
});
} catch (error) {
logger.error(`Sync of global parameters for space with id ${spaceId} failed: ${error.message}`);
}
};