diff --git a/x-pack/plugins/synthetics/common/constants/synthetics/rest_api.ts b/x-pack/plugins/synthetics/common/constants/synthetics/rest_api.ts index 7e61e0a9e5e08..a0875d9df4977 100644 --- a/x-pack/plugins/synthetics/common/constants/synthetics/rest_api.ts +++ b/x-pack/plugins/synthetics/common/constants/synthetics/rest_api.ts @@ -12,6 +12,7 @@ export enum SYNTHETICS_API_URLS { OVERVIEW_STATUS = `/internal/synthetics/overview_status`, INDEX_SIZE = `/internal/synthetics/index_size`, PARAMS = `/synthetics/params`, + PRIVATE_LOCATIONS = `/synthetics/private_locations`, SYNC_GLOBAL_PARAMS = `/synthetics/sync_global_params`, ENABLE_DEFAULT_ALERTING = `/synthetics/enable_default_alerting`, JOURNEY = `/internal/synthetics/journey/{checkGroup}`, diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/hooks/use_locations_api.test.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/hooks/use_locations_api.test.tsx index e343e9faf1aec..ce80c7d97e71e 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/hooks/use_locations_api.test.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/hooks/use_locations_api.test.tsx @@ -5,12 +5,25 @@ * 2.0. */ -import { renderHook } from '@testing-library/react-hooks'; -import { defaultCore, WrappedHelper } from '../../../../utils/testing'; - +import { renderHook, act } from '@testing-library/react-hooks'; +import { WrappedHelper } from '../../../../utils/testing'; +import { getServiceLocations } from '../../../../state/service_locations'; +import { setAddingNewPrivateLocation } from '../../../../state/private_locations'; import { useLocationsAPI } from './use_locations_api'; +import * as locationAPI from '../../../../state/private_locations/api'; +import * as reduxHooks from 'react-redux'; describe('useLocationsAPI', () => { + const dispatch = jest.fn(); + const addAPI = jest.spyOn(locationAPI, 'addSyntheticsPrivateLocations').mockResolvedValue({ + locations: [], + }); + const deletedAPI = jest.spyOn(locationAPI, 'deleteSyntheticsPrivateLocations').mockResolvedValue({ + locations: [], + }); + const getAPI = jest.spyOn(locationAPI, 'getSyntheticsPrivateLocations'); + jest.spyOn(reduxHooks, 'useDispatch').mockReturnValue(dispatch); + it('returns expected results', () => { const { result } = renderHook(() => useLocationsAPI(), { wrapper: WrappedHelper, @@ -22,20 +35,15 @@ describe('useLocationsAPI', () => { privateLocations: [], }) ); - expect(defaultCore.savedObjects.client.get).toHaveBeenCalledWith( - 'synthetics-privates-locations', - 'synthetics-privates-locations-singleton' - ); + expect(getAPI).toHaveBeenCalledTimes(1); }); - defaultCore.savedObjects.client.get = jest.fn().mockReturnValue({ - attributes: { - locations: [ - { - id: 'Test', - agentPolicyId: 'testPolicy', - }, - ], - }, + jest.spyOn(locationAPI, 'getSyntheticsPrivateLocations').mockResolvedValue({ + locations: [ + { + id: 'Test', + agentPolicyId: 'testPolicy', + } as any, + ], }); it('returns expected results after data', async () => { const { result, waitForNextUpdate } = renderHook(() => useLocationsAPI(), { @@ -71,77 +79,50 @@ describe('useLocationsAPI', () => { await waitForNextUpdate(); - result.current.onSubmit({ - id: 'new', - agentPolicyId: 'newPolicy', - label: 'new', + act(() => { + result.current.onSubmit({ + id: 'new', + agentPolicyId: 'newPolicy', + label: 'new', + concurrentMonitors: 1, + geo: { + lat: 0, + lon: 0, + }, + }); + }); + + await waitForNextUpdate(); + + expect(addAPI).toHaveBeenCalledWith({ concurrentMonitors: 1, + id: 'newPolicy', geo: { lat: 0, lon: 0, }, + label: 'new', + agentPolicyId: 'newPolicy', }); - - await waitForNextUpdate(); - - expect(defaultCore.savedObjects.client.create).toHaveBeenCalledWith( - 'synthetics-privates-locations', - { - locations: [ - { id: 'Test', agentPolicyId: 'testPolicy' }, - { - concurrentMonitors: 1, - id: 'newPolicy', - geo: { - lat: 0, - lon: 0, - }, - label: 'new', - agentPolicyId: 'newPolicy', - }, - ], - }, - { id: 'synthetics-privates-locations-singleton', overwrite: true } - ); + expect(dispatch).toBeCalledWith(setAddingNewPrivateLocation(false)); + expect(dispatch).toBeCalledWith(getServiceLocations()); }); it('deletes location on delete', async () => { - defaultCore.savedObjects.client.get = jest.fn().mockReturnValue({ - attributes: { - locations: [ - { - id: 'Test', - agentPolicyId: 'testPolicy', - }, - { - id: 'Test1', - agentPolicyId: 'testPolicy1', - }, - ], - }, - }); - const { result, waitForNextUpdate } = renderHook(() => useLocationsAPI(), { wrapper: WrappedHelper, }); await waitForNextUpdate(); - result.current.onDelete('Test'); + act(() => { + result.current.onDelete('Test'); + }); await waitForNextUpdate(); - expect(defaultCore.savedObjects.client.create).toHaveBeenLastCalledWith( - 'synthetics-privates-locations', - { - locations: [ - { - id: 'Test1', - agentPolicyId: 'testPolicy1', - }, - ], - }, - { id: 'synthetics-privates-locations-singleton', overwrite: true } - ); + expect(deletedAPI).toHaveBeenLastCalledWith('Test'); + expect(dispatch).toBeCalledWith(setAddingNewPrivateLocation(false)); + expect(dispatch).toBeCalledWith(getServiceLocations()); }); }); diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/hooks/use_locations_api.ts b/x-pack/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/hooks/use_locations_api.ts index 6b35e79152c87..8678328445a62 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/hooks/use_locations_api.ts +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/hooks/use_locations_api.ts @@ -7,12 +7,13 @@ import { useFetcher } from '@kbn/observability-plugin/public'; import { useState } from 'react'; -import { useKibana } from '@kbn/kibana-react-plugin/public'; import { useDispatch } from 'react-redux'; +import { getServiceLocations } from '../../../../state/service_locations'; import { setAddingNewPrivateLocation } from '../../../../state/private_locations'; import { + addSyntheticsPrivateLocations, + deleteSyntheticsPrivateLocations, getSyntheticsPrivateLocations, - setSyntheticsPrivateLocations, } from '../../../../state/private_locations/api'; import { PrivateLocation } from '../../../../../../../common/runtime_types'; @@ -21,31 +22,29 @@ export const useLocationsAPI = () => { const [deleteId, setDeleteId] = useState(); const [privateLocations, setPrivateLocations] = useState([]); - const { savedObjects } = useKibana().services; - const dispatch = useDispatch(); const setIsAddingNew = (val: boolean) => dispatch(setAddingNewPrivateLocation(val)); const { loading: fetchLoading } = useFetcher(async () => { - const result = await getSyntheticsPrivateLocations(savedObjects?.client!); - setPrivateLocations(result); + const result = await getSyntheticsPrivateLocations(); + setPrivateLocations(result.locations); return result; }, []); const { loading: saveLoading } = useFetcher(async () => { - if (privateLocations && formData) { - const existingLocations = privateLocations.filter((loc) => loc.id !== formData.agentPolicyId); - - const result = await setSyntheticsPrivateLocations(savedObjects?.client!, { - locations: [...(existingLocations ?? []), { ...formData, id: formData.agentPolicyId }], + if (formData) { + const result = await addSyntheticsPrivateLocations({ + ...formData, + id: formData.agentPolicyId, }); setPrivateLocations(result.locations); setFormData(undefined); setIsAddingNew(false); + dispatch(getServiceLocations()); return result; } - }, [formData, privateLocations]); + }, [formData]); const onSubmit = (data: PrivateLocation) => { setFormData(data); @@ -57,14 +56,13 @@ export const useLocationsAPI = () => { const { loading: deleteLoading } = useFetcher(async () => { if (deleteId) { - const result = await setSyntheticsPrivateLocations(savedObjects?.client!, { - locations: (privateLocations ?? []).filter((loc) => loc.id !== deleteId), - }); + const result = await deleteSyntheticsPrivateLocations(deleteId); setPrivateLocations(result.locations); setDeleteId(undefined); + dispatch(getServiceLocations()); return result; } - }, [deleteId, privateLocations]); + }, [deleteId]); return { formData, diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/location_form.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/location_form.tsx index 38bdac2592fb7..a001c503697b1 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/location_form.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/location_form.tsx @@ -33,8 +33,10 @@ export const LocationForm = ({ hasPermissions: boolean; }) => { const { data } = useSelector(selectAgentPolicies); - const { control, register } = useFormContext(); + const { control, register, watch } = useFormContext(); const { errors } = useFormState(); + const selectedPolicyId = watch('agentPolicyId'); + const selectedPolicy = data?.items.find((item) => item.id === selectedPolicyId); const tagsList = privateLocations.reduce((acc, item) => { const tags = item.tags || []; @@ -97,6 +99,39 @@ export const LocationForm = ({ }

+ + + {selectedPolicy?.agents === 0 && ( + +

+ { + + + + ), + }} + /> + } +

+
+ )} ); @@ -109,6 +144,13 @@ export const AGENT_CALLOUT_TITLE = i18n.translate( } ); +export const AGENT_MISSING_CALLOUT_TITLE = i18n.translate( + 'xpack.synthetics.monitorManagement.agentMissingCallout.title', + { + defaultMessage: 'Selected agent policy has no agents', + } +); + export const LOCATION_NAME_LABEL = i18n.translate( 'xpack.synthetics.monitorManagement.locationName', { diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/manage_private_locations.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/manage_private_locations.tsx index dd140ffd3b3f5..e8246aa13221e 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/manage_private_locations.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/manage_private_locations.tsx @@ -26,7 +26,6 @@ export const ManagePrivateLocations = () => { const dispatch = useDispatch(); const isAddingNew = useSelector(selectAddingNewPrivateLocation); - const setIsAddingNew = (val: boolean) => dispatch(setAddingNewPrivateLocation(val)); const { onSubmit, loading, privateLocations, onDelete, deleteLoading } = useLocationsAPI(); diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/policy_name.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/policy_name.tsx index a1a4f586e63bf..2c44bc80fed36 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/policy_name.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/policy_name.tsx @@ -6,7 +6,7 @@ */ import React from 'react'; -import { EuiLink, EuiLoadingSpinner, EuiText, EuiTextColor } from '@elastic/eui'; +import { EuiBadge, EuiLink, EuiLoadingSpinner, EuiText, EuiTextColor } from '@elastic/eui'; import { useSelector } from 'react-redux'; import { i18n } from '@kbn/i18n'; import { useSyntheticsSettingsContext } from '../../../contexts'; @@ -28,7 +28,7 @@ export const PolicyName = ({ agentPolicyId }: { agentPolicyId: string }) => { return ( - {canReadAgentPolicies && ( + {canReadAgentPolicies ? ( {policy ? ( @@ -40,7 +40,14 @@ export const PolicyName = ({ agentPolicyId }: { agentPolicyId: string }) => { )} + ) : ( + agentPolicyId )} +     + + {AGENTS_LABEL} + {policy?.agents} + ); }; @@ -48,3 +55,7 @@ export const PolicyName = ({ agentPolicyId }: { agentPolicyId: string }) => { const POLICY_IS_DELETED = i18n.translate('xpack.synthetics.monitorManagement.deletedPolicy', { defaultMessage: 'Policy is deleted', }); + +const AGENTS_LABEL = i18n.translate('xpack.synthetics.monitorManagement.agents', { + defaultMessage: 'Agents: ', +}); diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/settings/route_config.ts b/x-pack/plugins/synthetics/public/apps/synthetics/components/settings/route_config.ts index ee9b6c34bd8f9..51ddf14ee5f67 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/settings/route_config.ts +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/settings/route_config.ts @@ -17,32 +17,27 @@ export const getSettingsRouteConfig = ( syntheticsPath: string, baseTitle: string ) => { + const sharedProps = { + title: i18n.translate('xpack.synthetics.settingsRoute.title', { + defaultMessage: 'Settings | {baseTitle}', + values: { baseTitle }, + }), + component: SettingsPage, + pageHeader: getSettingsPageHeader(history, syntheticsPath), + dataTestSubj: 'syntheticsSettingsPage', + pageSectionProps: { + paddingSize: 'm', + }, + }; + return [ { - title: i18n.translate('xpack.synthetics.settingsRoute.title', { - defaultMessage: 'Settings | {baseTitle}', - values: { baseTitle }, - }), + ...sharedProps, path: SETTINGS_ROUTE, - component: SettingsPage, - dataTestSubj: 'syntheticsSettingsPage', - pageSectionProps: { - paddingSize: 'm', - }, - pageHeader: getSettingsPageHeader(history, syntheticsPath), }, { - title: i18n.translate('xpack.synthetics.settingsRoute.title', { - defaultMessage: 'Settings | {baseTitle}', - values: { baseTitle }, - }), + ...sharedProps, path: SYNTHETICS_SETTINGS_ROUTE, - component: SettingsPage, - dataTestSubj: 'syntheticsSettingsPage', - pageSectionProps: { - paddingSize: 'm', - }, - pageHeader: getSettingsPageHeader(history, syntheticsPath), }, ] as RouteProps[]; }; diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/state/private_locations/api.ts b/x-pack/plugins/synthetics/public/apps/synthetics/state/private_locations/api.ts index 3c48696c685b9..50683fdd87a35 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/state/private_locations/api.ts +++ b/x-pack/plugins/synthetics/public/apps/synthetics/state/private_locations/api.ts @@ -5,14 +5,10 @@ * 2.0. */ -import { SavedObjectsClientContract } from '@kbn/core/public'; -import { SyntheticsPrivateLocations } from '../../../../../common/runtime_types'; +import { SYNTHETICS_API_URLS } from '../../../../../common/constants'; +import { PrivateLocation, SyntheticsPrivateLocations } from '../../../../../common/runtime_types'; import { apiService } from '../../../../utils/api_service/api_service'; import { AgentPoliciesList } from '.'; -import { - privateLocationsSavedObjectId, - privateLocationsSavedObjectName, -} from '../../../../../common/saved_objects/private_locations'; const FLEET_URLS = { AGENT_POLICIES: '/api/fleet/agent_policies', @@ -33,26 +29,18 @@ export const fetchAgentPolicies = async (): Promise => { ); }; -export const setSyntheticsPrivateLocations = async ( - client: SavedObjectsClientContract, - privateLocations: SyntheticsPrivateLocations -) => { - const result = await client.create(privateLocationsSavedObjectName, privateLocations, { - id: privateLocationsSavedObjectId, - overwrite: true, - }); +export const addSyntheticsPrivateLocations = async ( + newLocation: PrivateLocation +): Promise => { + return await apiService.post(SYNTHETICS_API_URLS.PRIVATE_LOCATIONS, newLocation); +}; - return result.attributes; +export const getSyntheticsPrivateLocations = async (): Promise => { + return await apiService.get(SYNTHETICS_API_URLS.PRIVATE_LOCATIONS); }; -export const getSyntheticsPrivateLocations = async (client: SavedObjectsClientContract) => { - try { - const obj = await client.get( - privateLocationsSavedObjectName, - privateLocationsSavedObjectId - ); - return obj?.attributes.locations ?? []; - } catch (getErr) { - return []; - } +export const deleteSyntheticsPrivateLocations = async ( + locationId: string +): Promise => { + return await apiService.delete(SYNTHETICS_API_URLS.PRIVATE_LOCATIONS + `/${locationId}`); }; diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/state/root_effect.ts b/x-pack/plugins/synthetics/public/apps/synthetics/state/root_effect.ts index ced9c212e83cf..371e054476c79 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/state/root_effect.ts +++ b/x-pack/plugins/synthetics/public/apps/synthetics/state/root_effect.ts @@ -45,7 +45,6 @@ export const rootEffect = function* root(): Generator { fork(fetchAgentPoliciesEffect), fork(fetchDynamicSettingsEffect), fork(setDynamicSettingsEffect), - fork(fetchAgentPoliciesEffect), fork(fetchAlertConnectorsEffect), fork(syncGlobalParamsEffect), fork(enableDefaultAlertingEffect), diff --git a/x-pack/plugins/synthetics/server/routes/index.ts b/x-pack/plugins/synthetics/server/routes/index.ts index 6978a38b2be46..b394c53f20142 100644 --- a/x-pack/plugins/synthetics/server/routes/index.ts +++ b/x-pack/plugins/synthetics/server/routes/index.ts @@ -44,6 +44,9 @@ import { getHasIntegrationMonitorsRoute } from './fleet/get_has_integration_moni import { addSyntheticsParamsRoute } from './settings/add_param'; import { enableDefaultAlertingRoute } from './default_alerts/enable_default_alert'; import { getDefaultAlertingRoute } from './default_alerts/get_default_alert'; +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'; export const syntheticsAppRestApiRoutes: SyntheticsRestApiRouteFactory[] = [ addSyntheticsMonitorRoute, @@ -77,6 +80,9 @@ export const syntheticsAppRestApiRoutes: SyntheticsRestApiRouteFactory[] = [ getDefaultAlertingRoute, updateDefaultAlertingRoute, createJourneyRoute, + addPrivateLocationRoute, + deletePrivateLocationRoute, + getPrivateLocationsRoute, ]; export const syntheticsAppStreamingApiRoutes: SyntheticsStreamingRouteFactory[] = [ diff --git a/x-pack/plugins/synthetics/server/routes/settings/private_locations/add_private_location.ts b/x-pack/plugins/synthetics/server/routes/settings/private_locations/add_private_location.ts new file mode 100644 index 0000000000000..9edd4bf53f81a --- /dev/null +++ b/x-pack/plugins/synthetics/server/routes/settings/private_locations/add_private_location.ts @@ -0,0 +1,56 @@ +/* + * 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 { schema } from '@kbn/config-schema'; +import { getAllPrivateLocations } from './get_private_locations'; +import { + privateLocationsSavedObjectId, + privateLocationsSavedObjectName, +} from '../../../../common/saved_objects/private_locations'; +import { SyntheticsRestApiRouteFactory } from '../../../legacy_uptime/routes'; +import { SYNTHETICS_API_URLS } from '../../../../common/constants'; +import { PrivateLocation } from '../../../../common/runtime_types'; + +export const PrivateLocationSchema = schema.object({ + label: schema.string(), + id: schema.string(), + agentPolicyId: schema.string(), + concurrentMonitors: schema.number(), + tags: schema.maybe(schema.arrayOf(schema.string())), + geo: schema.maybe( + schema.object({ + lat: schema.oneOf([schema.number(), schema.string()]), + lon: schema.oneOf([schema.number(), schema.string()]), + }) + ), +}); + +export const addPrivateLocationRoute: SyntheticsRestApiRouteFactory = () => ({ + method: 'POST', + path: SYNTHETICS_API_URLS.PRIVATE_LOCATIONS, + validate: { + body: PrivateLocationSchema, + }, + writeAccess: true, + handler: async ({ request, server, savedObjectsClient }): Promise => { + const location = request.body as PrivateLocation; + + const { locations } = await getAllPrivateLocations(savedObjectsClient); + const existingLocations = locations.filter((loc) => loc.id !== location.agentPolicyId); + + const result = await savedObjectsClient.create( + privateLocationsSavedObjectName, + { locations: [...existingLocations, location] }, + { + id: privateLocationsSavedObjectId, + overwrite: true, + } + ); + + return result.attributes; + }, +}); diff --git a/x-pack/plugins/synthetics/server/routes/settings/private_locations/delete_private_location.ts b/x-pack/plugins/synthetics/server/routes/settings/private_locations/delete_private_location.ts new file mode 100644 index 0000000000000..7360adfbc0b60 --- /dev/null +++ b/x-pack/plugins/synthetics/server/routes/settings/private_locations/delete_private_location.ts @@ -0,0 +1,43 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { schema } from '@kbn/config-schema'; +import { getAllPrivateLocations } from './get_private_locations'; +import { SyntheticsRestApiRouteFactory } from '../../../legacy_uptime/routes'; +import { SYNTHETICS_API_URLS } from '../../../../common/constants'; +import { + privateLocationsSavedObjectId, + privateLocationsSavedObjectName, +} from '../../../../common/saved_objects/private_locations'; + +export const deletePrivateLocationRoute: SyntheticsRestApiRouteFactory = () => ({ + method: 'DELETE', + path: SYNTHETICS_API_URLS.PRIVATE_LOCATIONS + '/{locationId}', + validate: { + params: schema.object({ + locationId: schema.string({ minLength: 1, maxLength: 1024 }), + }), + }, + writeAccess: true, + handler: async ({ savedObjectsClient, request, server }): Promise => { + const { locationId } = request.params as { locationId: string }; + + const { locations } = await getAllPrivateLocations(savedObjectsClient); + const remainingLocations = locations.filter((loc) => loc.id !== locationId); + + const result = await savedObjectsClient.create( + privateLocationsSavedObjectName, + { locations: remainingLocations }, + { + id: privateLocationsSavedObjectId, + overwrite: true, + } + ); + + return result.attributes; + }, +}); diff --git a/x-pack/plugins/synthetics/server/routes/settings/private_locations/get_private_locations.ts b/x-pack/plugins/synthetics/server/routes/settings/private_locations/get_private_locations.ts new file mode 100644 index 0000000000000..82b1f4f4e0e8a --- /dev/null +++ b/x-pack/plugins/synthetics/server/routes/settings/private_locations/get_private_locations.ts @@ -0,0 +1,38 @@ +/* + * 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 { SavedObjectsClientContract } from '@kbn/core-saved-objects-api-server'; +import { SyntheticsPrivateLocations } from '../../../../common/runtime_types'; +import { SyntheticsRestApiRouteFactory } from '../../../legacy_uptime/routes'; +import { SYNTHETICS_API_URLS } from '../../../../common/constants'; +import { + privateLocationsSavedObjectId, + privateLocationsSavedObjectName, +} from '../../../../common/saved_objects/private_locations'; + +export const getPrivateLocationsRoute: SyntheticsRestApiRouteFactory = () => ({ + method: 'GET', + path: SYNTHETICS_API_URLS.PRIVATE_LOCATIONS, + validate: {}, + handler: async ({ savedObjectsClient }): Promise => { + return await getAllPrivateLocations(savedObjectsClient); + }, +}); + +export const getAllPrivateLocations = async ( + savedObjectsClient: SavedObjectsClientContract +): Promise => { + try { + const obj = await savedObjectsClient.get( + privateLocationsSavedObjectName, + privateLocationsSavedObjectId + ); + return obj?.attributes ?? { locations: [] }; + } catch (getErr) { + return { locations: [] }; + } +};