);
- const notifyOnCreation = getNotifyCreation(policy);
- const notifyOnDeletion = getNotifyDeletion(policy);
- const notifyOnFailure = getNotifyFailure(policy);
-
- let showNotificationChannel = false;
- if (notifyOnCreation || notifyOnDeletion || notifyOnFailure) {
- showNotificationChannel = true;
- }
+ const showNotificationChannel = showNotification(policy);
return (
@@ -535,9 +549,15 @@ export default class CreateSnapshotPolicy extends Component
{
- this.setState({ creationScheduleFrequencyType: e.target.value });
+ const frequencyType = e.target.value;
+ let maxAgeUnitToChange = maxAgeUnit;
+ if (frequencyType == "hourly" && !deleteConditionEnabled) {
+ maxAgeUnitToChange = "h";
+ }
+ this.setState({ creationScheduleFrequencyType: e.target.value, maxAgeUnit: maxAgeUnitToChange });
}}
showTimezone={true}
timezone={_.get(policy, "creation.schedule.cron.timezone")}
@@ -598,7 +618,11 @@ export default class CreateSnapshotPolicy extends Component
-
+
@@ -611,23 +635,25 @@ export default class CreateSnapshotPolicy extends Component
- Deletion schedule
+ Deletion frequency
- Delete snapshots that are outside the retention period
+ Configure when to check retention conditions and delete snapshots.
{
this.setState({ deletionScheduleEnabled: !deletionScheduleEnabled });
}}
/>
+
{deletionScheduleEnabled ? (
{
this.setState({ deletionScheduleFrequencyType: e.target.value });
@@ -639,7 +665,7 @@ export default class CreateSnapshotPolicy extends Component
) : null}
- {" "}
+
>
) : null}
@@ -652,9 +678,9 @@ export default class CreateSnapshotPolicy extends Component
) => {
this.setState({ policy: this.setPolicyHelper("notification.conditions.creation", e.target.checked) });
}}
@@ -663,9 +689,9 @@ export default class CreateSnapshotPolicy extends Component
) => {
this.setState({ policy: this.setPolicyHelper("notification.conditions.deletion", e.target.checked) });
}}
@@ -674,17 +700,17 @@ export default class CreateSnapshotPolicy extends Component
) => {
this.setState({ policy: this.setPolicyHelper("notification.conditions.failure", e.target.checked) });
}}
/>
{showNotificationChannel ? (
-
-
+ {/* TODO SM Haven't fininalized the design for this before 2.1 release */}
+ {/*
Snapshot naming settings
@@ -740,10 +767,13 @@ export default class CreateSnapshotPolicy extends Component
{
- this.setState({ policy: this.setPolicyHelper("snapshot_config.date_format", e.target.value) });
+ let dateFormat = e.target.value;
+ if (!dateFormat) {
+ dateFormat = DEFAULT_DATE_FORMAT;
+ }
+ this.setState({ dateFormat });
}}
/>
@@ -755,13 +785,14 @@ export default class CreateSnapshotPolicy extends Component `${tz} (${moment.tz(tz).format("Z")})`}
- selectedOptions={[{ label: _.get(policy, "snapshot_config.date_format_timezone") ?? "" }]}
+ selectedOptions={[{ label: _.get(policy, "snapshot_config.date_format_timezone") ?? DEFAULT_DATE_FORMAT_TIMEZONE }]}
onChange={(options) => {
- const timezone = _.first(options)?.label;
+ let timezone = _.first(options)?.label;
+ if (!timezone) timezone = DEFAULT_DATE_FORMAT_TIMEZONE;
this.setState({ policy: this.setPolicyHelper("snapshot_config.date_format_timezone", timezone) });
}}
/>
-
+
*/}
>
)}
@@ -783,16 +814,6 @@ export default class CreateSnapshotPolicy extends Component {
- const maxAge = policy.deletion?.condition?.max_age;
- if (maxAge) {
- this.setState({
- maxAgeNum: parseInt(maxAge.substring(0, maxAge.length - 1)),
- maxAgeUnit: maxAge[maxAge.length - 1],
- });
- }
- };
-
onChangeMaxCount = (e: ChangeEvent) => {
// Received NaN for the `value` attribute. If this is expected, cast the value to a string.
const maxCount = isNaN(parseInt(e.target.value)) ? undefined : parseInt(e.target.value);
diff --git a/public/pages/CreateSnapshotPolicy/containers/helper.ts b/public/pages/CreateSnapshotPolicy/containers/helper.ts
index af0f7650c..a68ec0d4c 100644
--- a/public/pages/CreateSnapshotPolicy/containers/helper.ts
+++ b/public/pages/CreateSnapshotPolicy/containers/helper.ts
@@ -28,3 +28,16 @@ export const getNotifyDeletion = (policy: SMPolicy) => {
export const getNotifyFailure = (policy: SMPolicy) => {
return String(_.get(policy, "notification.conditions.failure", false)) == "true";
};
+
+export const showNotification = (policy: SMPolicy) => {
+ const notifyOnCreation = getNotifyCreation(policy);
+ const notifyOnDeletion = getNotifyDeletion(policy);
+ const notifyOnFailure = getNotifyFailure(policy);
+
+ let showNotificationChannel = false;
+ if (notifyOnCreation || notifyOnDeletion || notifyOnFailure) {
+ showNotificationChannel = true;
+ }
+
+ return showNotificationChannel;
+};
diff --git a/public/pages/Main/Main.tsx b/public/pages/Main/Main.tsx
index d8a111ee7..caa574bab 100644
--- a/public/pages/Main/Main.tsx
+++ b/public/pages/Main/Main.tsx
@@ -74,7 +74,9 @@ const HIDDEN_NAV_ROUTES = [
ROUTES.EDIT_SNAPSHOT_POLICY,
];
-interface MainProps extends RouteComponentProps {}
+interface MainProps extends RouteComponentProps {
+ landingPage: string;
+}
export default class Main extends Component {
render() {
@@ -145,6 +147,9 @@ export default class Main extends Component {
],
},
];
+
+ const { landingPage } = this.props;
+
return (
{(core: CoreStart | null) =>
@@ -188,7 +193,11 @@ export default class Main extends Component {
(
-
+
)}
/>
{
)}
/>
-
+
diff --git a/public/pages/Repositories/components/CreateRepositoryFlyout/CreateRepositoryFlyout.tsx b/public/pages/Repositories/components/CreateRepositoryFlyout/CreateRepositoryFlyout.tsx
index bdc680295..686c0c015 100644
--- a/public/pages/Repositories/components/CreateRepositoryFlyout/CreateRepositoryFlyout.tsx
+++ b/public/pages/Repositories/components/CreateRepositoryFlyout/CreateRepositoryFlyout.tsx
@@ -5,6 +5,7 @@
import {
EuiAccordion,
+ EuiCallOut,
EuiCodeEditor,
EuiComboBox,
EuiComboBoxOptionOption,
@@ -153,6 +154,16 @@ export default class CreateRepositoryFlyout extends Component
+
+ Define a repository by custom type and settings.{" "}
+
+ View sample configurations
+
+
+
+ );
let configuration;
if (selectedRepoTypeOption == "fs") {
configuration = (
@@ -197,14 +208,20 @@ export default class CreateRepositoryFlyout extends Component
-
-
- Define a repository by custom type and settings.{" "}
-
- View sample configurations
+
+
+ To use a custom repository, such as Amazon S3, Azure Blob Storage or similar, install and configure the respective repository
+ plugin on OpenSearch and then define the repository configuration below.{" "}
+
+ Learn more
-
+
+
+
+
+
+
{
- const showSymbol = _.truncate(name, { length: 20 });
+ const showSymbol = _.truncate(name, { length: 60 });
return (
this.props.history.push(`${ROUTES.SNAPSHOT_POLICY_DETAILS}?id=${name}`)}>
{showSymbol}
@@ -127,7 +126,7 @@ export default class SnapshotPolicies extends Component {
- return truncateSpan(value);
+ return truncateSpan(value, 60);
},
},
{
@@ -135,6 +134,7 @@ export default class SnapshotPolicies extends Component {
const expression = name;
const timezone = item.creation.schedule.cron.timezone;
@@ -146,6 +146,7 @@ export default class SnapshotPolicies extends Component {
return truncateSpan(value);
},
@@ -287,6 +289,7 @@ export default class SnapshotPolicies extends Component {
@@ -305,6 +308,7 @@ export default class SnapshotPolicies extends Component {
diff --git a/public/pages/SnapshotPolicyDetails/containers/SnapshotPolicyDetails/SnapshotPolicyDetails.tsx b/public/pages/SnapshotPolicyDetails/containers/SnapshotPolicyDetails/SnapshotPolicyDetails.tsx
index 53f667840..4c647f858 100644
--- a/public/pages/SnapshotPolicyDetails/containers/SnapshotPolicyDetails/SnapshotPolicyDetails.tsx
+++ b/public/pages/SnapshotPolicyDetails/containers/SnapshotPolicyDetails/SnapshotPolicyDetails.tsx
@@ -21,7 +21,7 @@ import {
EuiText,
EuiTitle,
} from "@elastic/eui";
-import { SnapshotManagementService } from "../../../../services";
+import { NotificationService, SnapshotManagementService } from "../../../../services";
import { SMMetadata, SMPolicy } from "../../../../../models/interfaces";
import { CoreServicesContext } from "../../../../components/core_services";
import { BREADCRUMBS, ROUTES } from "../../../../utils/constants";
@@ -35,9 +35,11 @@ import { ModalConsumer } from "../../../../components/Modal";
import InfoModal from "../../components/InfoModal";
import { getAllowPartial, getIgnoreUnavailabel, getIncludeGlobalState } from "../../../CreateSnapshotPolicy/containers/helper";
import { truncateSpan } from "../../../Snapshots/helper";
+import { NotificationConfig } from "../../../../../server/models/interfaces";
interface SnapshotPolicyDetailsProps extends RouteComponentProps {
snapshotManagementService: SnapshotManagementService;
+ notificationService: NotificationService;
}
interface SnapshotPolicyDetailsState {
@@ -47,6 +49,8 @@ interface SnapshotPolicyDetailsState {
metadata: SMMetadata | null;
isDeleteModalVisible: boolean;
+
+ channel: NotificationConfig | null;
}
export default class SnapshotPolicyDetails extends Component {
@@ -61,6 +65,7 @@ export default class SnapshotPolicyDetails extends Component => {
+ try {
+ const { notificationService } = this.props;
+ const response = await notificationService.getChannel(channelId);
+
+ if (response.ok) {
+ const configList = response.response.config_list;
+ let channel = null;
+ if (configList.length == 1) channel = configList[0];
+ this.setState({ channel });
+ } else {
+ this.context.notifications.toasts.addDanger(`Could not load notification channel: ${response.error}`);
+ }
+ } catch (err) {
+ this.context.notifications.toasts.addDanger(getErrorMessage(err, "Could not load the notification channel"));
+ }
+ };
+
onEdit = () => {
const { policyId } = this.state;
if (policyId) {
@@ -188,7 +216,7 @@ export default class SnapshotPolicyDetails extends Component notiConditions[key])
.join(", ");
}
- console.log(`sm dev notification ${notiActivities}`);
+
+ let channelDetail = None
;
+ if (!!channel?.config.name) {
+ channelDetail = (
+
+ {channel?.config.name} ({channel?.config.config_type})
+
+ );
+ }
const notificationItems = [
{ term: "Notify on snapshot activities", value: notiActivities },
- { term: "Channels", value: _.get(policy, "notification.channel.id") },
+ { term: "Channel", value: channelDetail },
];
let creationLatestActivity: LatestActivities = { activityType: "Creation" };
diff --git a/public/pages/Snapshots/components/CreateSnapshotFlyout/CreateSnapshotFlyout.tsx b/public/pages/Snapshots/components/CreateSnapshotFlyout/CreateSnapshotFlyout.tsx
index 54a1d12ba..2ab6397d9 100644
--- a/public/pages/Snapshots/components/CreateSnapshotFlyout/CreateSnapshotFlyout.tsx
+++ b/public/pages/Snapshots/components/CreateSnapshotFlyout/CreateSnapshotFlyout.tsx
@@ -87,7 +87,6 @@ export default class CreateSnapshotFlyout extends Component
sortable: true,
dataType: "string",
render: (name: string, item: SnapshotsWithRepoAndPolicy) => {
- const truncated = _.truncate(name, { length: 20 });
+ const truncated = _.truncate(name, { length: 80 });
return (
this.setState({ showFlyout: true, flyoutSnapshotId: name, flyoutSnapshotRepo: item.repository })}>
{truncated}
@@ -84,7 +84,7 @@ export default class Snapshots extends Component
name: "Status",
sortable: true,
dataType: "string",
- width: "150px",
+ width: "130px",
render: (value: string) => {
return snapshotStatusRender(value);
},
@@ -94,6 +94,7 @@ export default class Snapshots extends Component
name: "Policy",
sortable: false,
dataType: "string",
+ width: "150px",
render: (name: string, item: SnapshotsWithRepoAndPolicy) => {
const truncated = _.truncate(name, { length: 20 });
if (!!item.policy) {
@@ -106,6 +107,7 @@ export default class Snapshots extends Component
field: "repository",
name: "Repository",
sortable: false,
+ width: "120px",
dataType: "string",
},
{
@@ -113,6 +115,7 @@ export default class Snapshots extends Component
name: "Start time",
sortable: true,
dataType: "date",
+ width: "130px",
render: renderTimestampMillis,
},
{
@@ -120,6 +123,7 @@ export default class Snapshots extends Component
name: "End time",
sortable: true,
dataType: "date",
+ width: "130px",
render: renderTimestampMillis,
},
];
@@ -267,7 +271,11 @@ export default class Snapshots extends Component
const subTitleText = (
- Snapshots are taken automatically from snapshot policies, or you can initiate manual snapshots to save to a repository.
+ Snapshots are taken automatically from snapshot policies, or you can initiate manual snapshots to save to a repository.
+ To restore a snapshot, use the snapshot restore API.{" "}
+
+ Learn more
+
);
diff --git a/public/plugin.ts b/public/plugin.ts
index ea5d09a53..ce07e27e6 100644
--- a/public/plugin.ts
+++ b/public/plugin.ts
@@ -7,6 +7,7 @@ import { AppMountParameters, CoreSetup, CoreStart, Plugin, PluginInitializerCont
import { IndexManagementPluginSetup } from ".";
import { IndexManagementPluginStart } from ".";
import { actionRepoSingleton } from "./pages/VisualCreatePolicy/utils/helpers";
+import { ROUTES } from "./utils/constants";
export class IndexManagementPlugin implements Plugin {
constructor(private readonly initializerContext: PluginInitializerContext) {
@@ -26,9 +27,26 @@ export class IndexManagementPlugin implements Plugin {
const { renderApp } = await import("./index_management_app");
const [coreStart, depsStart] = await core.getStartServices();
- return renderApp(coreStart, params);
+ return renderApp(coreStart, params, ROUTES.INDEX_POLICIES);
},
});
+
+ core.application.register({
+ id: "opensearch_snapshot_management_dashboards",
+ title: "Snapshot Management",
+ order: 7000,
+ category: {
+ id: "opensearch",
+ label: "OpenSearch Plugins",
+ order: 2000,
+ },
+ mount: async (params: AppMountParameters) => {
+ const { renderApp } = await import("./index_management_app");
+ const [coreStart, depsStart] = await core.getStartServices();
+ return renderApp(coreStart, params, ROUTES.SNAPSHOT_POLICIES);
+ },
+ });
+
return {
registerAction: (actionType, uiActionCtor, defaultAction) => {
actionRepoSingleton.registerAction(actionType, uiActionCtor, defaultAction);
diff --git a/public/services/NotificationService.ts b/public/services/NotificationService.ts
index 64f453039..751f2af44 100644
--- a/public/services/NotificationService.ts
+++ b/public/services/NotificationService.ts
@@ -4,7 +4,7 @@
*/
import { HttpSetup } from "opensearch-dashboards/public";
-import { GetChannelsResponse } from "../../server/models/interfaces";
+import { GetChannelsResponse, GetNotificationConfigsResponse } from "../../server/models/interfaces";
import { ServerResponse } from "../../server/models/types";
import { NODE_API } from "../../utils/constants";
@@ -20,4 +20,10 @@ export default class NotificationService {
const response = (await this.httpClient.get(url)) as ServerResponse;
return response;
};
+
+ getChannel = async (channelId: string): Promise> => {
+ let url = `..${NODE_API.CHANNELS}/${channelId}`;
+ const response = (await this.httpClient.get(url)) as ServerResponse;
+ return response;
+ };
}
diff --git a/public/utils/constants.ts b/public/utils/constants.ts
index b697cd372..441de3385 100644
--- a/public/utils/constants.ts
+++ b/public/utils/constants.ts
@@ -13,11 +13,15 @@ export const ACTIONS_DOCUMENTATION_URL = "https://opensearch.org/docs/im-plugin/
export const STATES_DOCUMENTATION_URL = "https://opensearch.org/docs/im-plugin/ism/policies/#states";
export const ERROR_NOTIFICATION_DOCUMENTATION_URL = "https://opensearch.org/docs/im-plugin/ism/policies/#error-notifications";
export const TRANSITION_DOCUMENTATION_URL = "https://opensearch.org/docs/im-plugin/ism/policies/#transitions";
+
+export const SNAPSHOT_MANAGEMENT_DOCUMENTATION_URL = "https://opensearch.org//docs/latest/opensearch/snapshots/snapshot-management/";
export const CRON_EXPRESSION_DOCUMENTATION_URL = "https://opensearch.org/docs/latest/monitoring-plugins/alerting/cron/";
-export const SNAPSHOT_MANAGEMENT_DOCUMENTATION_URL = "https://opensearch.org/docs/im-plugin/ism/index";
-export const REPOSITORY_DOCUMENTATION_URL = "https://opensearch.org/docs/latest/opensearch/snapshot-restore/#register-repository";
-export const FS_REPOSITORY_DOCUMENTATION_URL = "https://opensearch.org/docs/latest/opensearch/snapshot-restore/#shared-file-system";
-export const S3_REPOSITORY_DOCUMENTATION_URL = "https://opensearch.org/docs/latest/opensearch/snapshot-restore/#amazon-s3";
+export const RESTORE_SNAPSHOT_DOCUMENTATION_URL =
+ "https://opensearch.org/docs/latest/opensearch/snapshots/snapshot-restore/#restore-snapshots";
+export const REPOSITORY_DOCUMENTATION_URL = "https://opensearch.org/docs/latest/opensearch/snapshots/snapshot-restore/#register-repository";
+export const FS_REPOSITORY_DOCUMENTATION_URL =
+ "https://opensearch.org/docs/latest/opensearch/snapshots/snapshot-restore/#shared-file-system";
+export const S3_REPOSITORY_DOCUMENTATION_URL = "https://opensearch.org/docs/latest/opensearch/snapshots/snapshot-restore/#amazon-s3";
export const ROUTES = Object.freeze({
CHANGE_POLICY: "/change-policy",
diff --git a/server/clusters/ism/ismPlugin.ts b/server/clusters/ism/ismPlugin.ts
index e79a6c7e1..231c7b5bd 100644
--- a/server/clusters/ism/ismPlugin.ts
+++ b/server/clusters/ism/ismPlugin.ts
@@ -376,6 +376,19 @@ export default function ismPlugin(Client: any, config: any, components: any) {
method: "GET",
});
+ ism.getChannel = ca({
+ url: {
+ fmt: `${API.NOTIFICATION_CONFIGS_BASE}/<%=id%>`,
+ req: {
+ id: {
+ type: "string",
+ required: true,
+ },
+ },
+ },
+ method: "GET",
+ });
+
ism.getSMPolicy = ca({
url: {
fmt: `${API.SM_POLICY_BASE}/<%=id%>`,
diff --git a/server/models/interfaces.ts b/server/models/interfaces.ts
index 4960d9967..f93626352 100644
--- a/server/models/interfaces.ts
+++ b/server/models/interfaces.ts
@@ -107,6 +107,25 @@ export interface FeatureChannelList {
is_enabled: boolean;
}
+export interface GetNotificationConfigsResponse {
+ start_index: number;
+ total_hits: number;
+ total_hit_relation: string;
+ config_list: NotificationConfig[];
+}
+
+export interface NotificationConfig {
+ config_id: string;
+ last_updated_time_ms: number;
+ created_time_ms: number;
+ config: {
+ name: string;
+ description: string;
+ config_type: string;
+ is_enabled: boolean;
+ };
+}
+
export interface GetFieldsResponse {
result: string;
}
@@ -282,6 +301,7 @@ export interface IndexManagementApi {
readonly ROLLUP_JOBS_BASE: string;
readonly TRANSFORM_BASE: string;
readonly CHANNELS_BASE: string;
+ readonly NOTIFICATION_CONFIGS_BASE: string;
readonly SM_POLICY_BASE: string;
}
diff --git a/server/routes/notifications.ts b/server/routes/notifications.ts
index 0e52e4519..90f56498f 100644
--- a/server/routes/notifications.ts
+++ b/server/routes/notifications.ts
@@ -6,6 +6,7 @@
import { NodeServices } from "../models/interfaces";
import { NODE_API } from "../../utils/constants";
import { IRouter } from "../../../../src/core/server";
+import { schema } from "@osd/config-schema";
export default function (services: NodeServices, router: IRouter) {
const { notificationService } = services;
@@ -17,4 +18,16 @@ export default function (services: NodeServices, router: IRouter) {
},
notificationService.getChannels
);
+
+ router.get(
+ {
+ path: `${NODE_API.CHANNELS}/{id}`,
+ validate: {
+ params: schema.object({
+ id: schema.string(),
+ }),
+ },
+ },
+ notificationService.getChannelById
+ );
}
diff --git a/server/services/NotificationService.ts b/server/services/NotificationService.ts
index 26c3d6fb8..b7d39a37a 100644
--- a/server/services/NotificationService.ts
+++ b/server/services/NotificationService.ts
@@ -12,7 +12,7 @@ import {
ResponseError,
} from "opensearch-dashboards/server";
import { ServerResponse } from "../models/types";
-import { GetChannelsResponse } from "../models/interfaces";
+import { GetChannelsResponse, GetNotificationConfigsResponse } from "../models/interfaces";
export default class NotificationService {
osDriver: ILegacyCustomClusterClient;
@@ -48,4 +48,38 @@ export default class NotificationService {
});
}
};
+
+ getChannelById = async (
+ context: RequestHandlerContext,
+ request: OpenSearchDashboardsRequest,
+ response: OpenSearchDashboardsResponseFactory
+ ): Promise | ResponseError>> => {
+ try {
+ const { id } = request.params as {
+ id: string;
+ };
+
+ const { callAsCurrentUser: callWithRequest } = this.osDriver.asScoped(request);
+ const getResponse: GetNotificationConfigsResponse = await callWithRequest("ism.getChannel", {
+ id,
+ });
+
+ return response.custom({
+ statusCode: 200,
+ body: {
+ ok: true,
+ response: getResponse,
+ },
+ });
+ } catch (err) {
+ console.error("Index Management - NotificationService - getChannel:", err);
+ return response.custom({
+ statusCode: 200,
+ body: {
+ ok: false,
+ error: err.message,
+ },
+ });
+ }
+ };
}
diff --git a/server/services/SnapshotManagementService.ts b/server/services/SnapshotManagementService.ts
index 3d4324f2a..84d405fca 100644
--- a/server/services/SnapshotManagementService.ts
+++ b/server/services/SnapshotManagementService.ts
@@ -75,10 +75,6 @@ export default class SnapshotManagementService {
repository: repositories[i],
policy: s.metadata?.sm_policy,
}));
- // TODO SM try catch the missing snapshot exception
- // const catSnapshotsRes: CatSnapshotWithRepoAndPolicy[] = await callWithRequest("snapshot.get", params);
- // const snapshotsWithRepo = catSnapshotsRes.map((item) => ({ ...item, repository: repositories[i] }));
- // console.log(`sm dev cat snapshot response: ${JSON.stringify(snapshotWithPolicy)}`);
snapshots = [...snapshots, ...snapshotWithPolicy];
}
@@ -93,7 +89,7 @@ export default class SnapshotManagementService {
},
});
} catch (err) {
- // TODO SM handle missing snapshot exception, return empty
+ // If getting a non-existing snapshot, need to handle the missing snapshot exception, and return empty
return this.errorResponse(response, err, "getAllSnapshotsWithPolicy");
}
};
@@ -176,7 +172,6 @@ export default class SnapshotManagementService {
snapshot: id,
body: JSON.stringify(request.body),
};
- // TODO SM body indices, ignore_unavailable, include_global_state, partial
const { callAsCurrentUser: callWithRequest } = this.osDriver.asScoped(request);
const resp: CreateSnapshotResponse = await callWithRequest("snapshot.create", params);
diff --git a/server/utils/constants.ts b/server/utils/constants.ts
index 8196ce0b2..2bef33314 100644
--- a/server/utils/constants.ts
+++ b/server/utils/constants.ts
@@ -10,6 +10,7 @@ export const API_ROUTE_PREFIX_ROLLUP = "/_plugins/_rollup";
export const TRANSFORM_ROUTE_PREFIX = "/_plugins/_transform";
export const NOTIFICATIONS_API_ROUTE_PREFIX = "/_plugins/_notifications";
export const CHANNELS_ROUTE = `${NOTIFICATIONS_API_ROUTE_PREFIX}/channels`;
+export const NOTIFICATION_CONFIGS_ROUTE = `${NOTIFICATIONS_API_ROUTE_PREFIX}/configs`;
export const SM_ROUTE_PREFIX = "/_plugins/_sm";
export const API: IndexManagementApi = {
@@ -22,6 +23,7 @@ export const API: IndexManagementApi = {
ROLLUP_JOBS_BASE: `${API_ROUTE_PREFIX_ROLLUP}/jobs`,
TRANSFORM_BASE: `${TRANSFORM_ROUTE_PREFIX}`,
CHANNELS_BASE: `${CHANNELS_ROUTE}`,
+ NOTIFICATION_CONFIGS_BASE: `${NOTIFICATION_CONFIGS_ROUTE}`,
SM_POLICY_BASE: `${SM_ROUTE_PREFIX}/policies`,
};