Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
b1d1bf2
Updated README with basic description
akbhatta Oct 5, 2020
dab3f75
Add docs to main branch for OpenSearch (#2)
joshuali925 Apr 19, 2021
900fc75
Update issue template with multiple labels
VachaShah May 7, 2021
3f28415
Merge pull request #14 from VachaShah/update_template
anirudha May 10, 2021
bd332ad
call smtp function in SPI from sendMessageAction handler (#236)
zhongnansu Jul 31, 2021
5cad6a6
Support HOST_DENY_LIST and TOOLTIP_SUPPORT in plugin settings (#250)
zhongnansu Aug 2, 2021
a8fa959
Fix custom webhook request body format (#248)
zhongnansu Aug 3, 2021
969222b
Refactor SPI for SES channel addition
akbhatta Aug 4, 2021
2f46c8c
Frontend: Add parsing logic for SNS channels (#249)
joshuali925 Aug 5, 2021
2395c67
Bump opensearch-notification version to 1.1 (#264)
zhongnansu Aug 6, 2021
29d86fa
add support for email credentials (#252)
zhongnansu Aug 9, 2021
b80bd1e
Update NotificationEventIndexTest.kt
kavithacm Aug 10, 2021
a6fc0b5
downgrade to 1.0 and align common-utils in CI to use `notifiation-dev…
zhongnansu Aug 10, 2021
e67201f
Add SNS support in notifications plugin (#266)
joshuali925 Aug 11, 2021
9a0458f
Added SES channel in SPI
akbhatta Aug 10, 2021
dce31c1
Disallow inconsistent config types in update requests (#280)
joshuali925 Aug 12, 2021
3cc9fa4
Refactor Feature from enum to string
akbhatta Aug 13, 2021
09e6e37
Adds PublishNotificationAction for legacy ISM implementation (#254)
dbbaughe Aug 13, 2021
b109cdb
Add support for sending email over SES in notification plugin
akbhatta Aug 16, 2021
6d306ff
Include back failed tests (#283)
dai-chen Aug 17, 2021
43046e2
SES channel is migrated to AWS SDK V1 to be same as SNS client
akbhatta Aug 17, 2021
816dd1d
Fix snapshot build. (#284)
dblock Aug 18, 2021
70264bb
Add Backend Metrics (#268)
davidcui1225 Aug 18, 2021
7e1e458
Add ses_account to feature api response (#290)
joshuali925 Aug 18, 2021
9dd5aa3
Merge remote-tracking branch 'upstream/develop' into main
zhongnansu Aug 18, 2021
3613158
Merge from develop to main (#291)
zhongnansu Aug 19, 2021
52714e2
Bump hosted-git-info from 2.8.8 to 2.8.9 in /dashboards-notifications…
dependabot[bot] Aug 19, 2021
62577de
Bump path-parse from 1.0.6 to 1.0.7 in /dashboards-notifications (#294)
dependabot[bot] Aug 19, 2021
84ca870
Bump ws from 7.4.4 to 7.5.3 in /dashboards-notifications (#293)
dependabot[bot] Aug 19, 2021
a0ba53b
Bump browserslist from 4.16.3 to 4.16.8 in /dashboards-notifications …
dependabot[bot] Aug 19, 2021
68bd46f
Remove unused mock data (#297)
joshuali925 Aug 20, 2021
d760a84
Delete NotificationEventIndexTest.kt
kavithacm Aug 23, 2021
303ebbd
Merge branch 'opensearch-project:main' into kavithacm-patch-1
kavithacm Aug 23, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 9 additions & 7 deletions .github/workflows/notifications-test-and-build-workflow.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,9 @@ name: Test and Build Notifications
on: [push, pull_request]

env:
OPENSEARCH_VERSION: '1.0'
COMMON_UTILS_VERSION: '1.0'
OPENSEARCH_VERSION: '1.1.0-SNAPSHOT'
OPENSEARCH_BRANCH: '1.x'
COMMON_UTILS_BRANCH: 'main'

jobs:
build:
Expand All @@ -45,30 +46,31 @@ jobs:
with:
repository: 'opensearch-project/OpenSearch'
path: OpenSearch
ref: ${{ env.OPENSEARCH_VERSION }}
ref: ${{ env.OPENSEARCH_BRANCH }}
- name: Build OpenSearch
working-directory: ./OpenSearch
run: ./gradlew publishToMavenLocal -Dbuild.snapshot=false
run: ./gradlew publishToMavenLocal

# dependencies: common-utils
- name: Checkout common-utils
uses: actions/checkout@v2
with:
repository: 'opensearch-project/common-utils'
ref: ${{ env.COMMON_UTILS_VERSION }}
ref: ${{ env.COMMON_UTILS_BRANCH }}
path: common-utils
- name: Build common-utils
working-directory: ./common-utils
run: ./gradlew publishToMavenLocal -Dopensearch.version=${{ env.OPENSEARCH_VERSION }}.0
run: ./gradlew publishToMavenLocal -Dopensearch.version=${{ env.OPENSEARCH_VERSION }}

# notifications
- name: Checkout Notifications
uses: actions/checkout@v2

# Temporarily exclude tests which causing CI to fail. Tracking in #251
- name: Build with Gradle
run: |
cd notifications
./gradlew build -PexcludeTests="**/SesChannelIT*" -Dopensearch.version=${{ env.OPENSEARCH_VERSION }}.0
./gradlew build -PexcludeTests="**/SesChannelIT*" -Dopensearch.version=${{ env.OPENSEARCH_VERSION }}

- name: Upload coverage
uses: codecov/codecov-action@v1
Expand Down
4 changes: 4 additions & 0 deletions dashboards-notifications/models/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,10 @@ export interface ChannelItemType extends ConfigType {
[id: string]: string;
};
};
sns?: {
topic_arn: string;
role_arn?: string;
}
}

interface ConfigType {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ exports[`<DetailsListModal /> spec renders the component 1`] = `
"notificationService": NotificationService {
"createConfig": [Function],
"deleteConfigs": [Function],
"getAvailableFeatures": [Function],
"getChannel": [Function],
"getChannels": [Function],
"getConfig": [Function],
Expand All @@ -38,6 +37,7 @@ exports[`<DetailsListModal /> spec renders the component 1`] = `
"getRecipientGroups": [Function],
"getSender": [Function],
"getSenders": [Function],
"getServerFeatures": [Function],
"httpClient": [MockFunction],
"updateConfig": [Function],
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ exports[`<DetailsTableModal /> spec renders headers 1`] = `
"notificationService": NotificationService {
"createConfig": [Function],
"deleteConfigs": [Function],
"getAvailableFeatures": [Function],
"getChannel": [Function],
"getChannels": [Function],
"getConfig": [Function],
Expand All @@ -39,6 +38,7 @@ exports[`<DetailsTableModal /> spec renders headers 1`] = `
"getRecipientGroups": [Function],
"getSender": [Function],
"getSenders": [Function],
"getServerFeatures": [Function],
"httpClient": [MockFunction],
"updateConfig": [Function],
},
Expand Down Expand Up @@ -1862,7 +1862,6 @@ exports[`<DetailsTableModal /> spec renders parameters 1`] = `
"notificationService": NotificationService {
"createConfig": [Function],
"deleteConfigs": [Function],
"getAvailableFeatures": [Function],
"getChannel": [Function],
"getChannels": [Function],
"getConfig": [Function],
Expand All @@ -1872,6 +1871,7 @@ exports[`<DetailsTableModal /> spec renders parameters 1`] = `
"getRecipientGroups": [Function],
"getSender": [Function],
"getSenders": [Function],
"getServerFeatures": [Function],
"httpClient": [MockFunction],
"updateConfig": [Function],
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -143,19 +143,6 @@ export function ChannelSettingsDetails(props: ChannelSettingsDetailsProps) {
title: 'Default recipients',
description: recipientsDescription,
},
// TODO remove when removing header/footer functionality
// {
// title: 'Email header',
// description: props.channel.destination.email.header
// ? 'Enabled'
// : 'Disabled',
// },
// {
// title: 'Email footer',
// description: props.channel.destination.email.footer
// ? 'Enabled'
// : 'Disabled',
// },
]
);
} else if (type === BACKEND_CHANNEL_TYPE.CUSTOM_WEBHOOK) {
Expand Down Expand Up @@ -203,22 +190,22 @@ export function ChannelSettingsDetails(props: ChannelSettingsDetailsProps) {
]
);
} else if (type === BACKEND_CHANNEL_TYPE.SNS) {
// settingsList.push(
// ...[
// {
// title: 'Channel type',
// description: CHANNEL_TYPE.SNS,
// },
// {
// title: 'SNS topic ARN',
// description: props.channel.destination.sns.topic_arn || '-',
// },
// {
// title: 'IAM role ARN',
// description: props.channel.destination.sns.role_arn || '-',
// },
// ]
// );
settingsList.push(
...[
{
title: 'Channel type',
description: CHANNEL_TYPE.sns,
},
{
title: 'SNS topic ARN',
description: props.channel.sns?.topic_arn || '-',
},
{
title: 'IAM role ARN',
description: props.channel.sns?.role_arn || '-',
},
]
);
} else if (type === BACKEND_CHANNEL_TYPE.SES) {
// TODO
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,6 @@ export const CreateChannelContext = createContext<{
} | null>(null);

export function CreateChannel(props: CreateChannelsProps) {
const isOdfe = true;

const coreContext = useContext(CoreServicesContext)!;
const servicesContext = useContext(ServicesContext)!;
const mainStateContext = useContext(MainContext)!;
Expand Down Expand Up @@ -226,7 +224,8 @@ export function CreateChannel(props: CreateChannelsProps) {
} else if (type === BACKEND_CHANNEL_TYPE.SES) {
// TODO
} else if (type === BACKEND_CHANNEL_TYPE.SNS) {
// TODO
setTopicArn(response.sns?.topic_arn || '');
setRoleArn(response.sns?.role_arn || '');
}
} catch (error) {
coreContext.notifications.toasts.addDanger(
Expand Down Expand Up @@ -265,7 +264,7 @@ export function CreateChannel(props: CreateChannelsProps) {
}
} else if (channelType === BACKEND_CHANNEL_TYPE.SNS) {
errors.topicArn = validateArn(topicArn);
if (!isOdfe) errors.roleArn = validateArn(roleArn);
if (!mainStateContext.tooltipSupport) errors.roleArn = validateArn(roleArn);
}
setInputErrors(errors);
return !Object.values(errors).reduce(
Expand Down Expand Up @@ -303,6 +302,13 @@ export function CreateChannel(props: CreateChannelsProps) {
selectedSenderOptions,
selectedRecipientGroupOptions
);
} else if (channelType === BACKEND_CHANNEL_TYPE.SES) {
// TODO
} else if (channelType === BACKEND_CHANNEL_TYPE.SNS) {
config.sns = {
topic_arn: topicArn,
...(roleArn && { role_arn: roleArn }),
};
}
return config;
};
Expand Down Expand Up @@ -450,7 +456,6 @@ export function CreateChannel(props: CreateChannelsProps) {
/>
) : channelType === BACKEND_CHANNEL_TYPE.SNS ? (
<SNSSettings
isOdfe={isOdfe}
topicArn={topicArn}
setTopicArn={setTopicArn}
roleArn={roleArn}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,11 @@ describe('test create channel validation helpers', () => {

it('validates webhook', () => {
const pass = validateWebhookURL('https://test-webhook');
const httpTest = validateWebhookURL('http://test-webhook');
const emptyInput = validateWebhookURL('');
const invalidURL = validateWebhookURL('hxxp://test-webhook');
expect(pass).toHaveLength(0);
expect(httpTest).toHaveLength(0);
expect(emptyInput).toHaveLength(1);
expect(invalidURL).toHaveLength(1);
});
Expand All @@ -69,11 +71,13 @@ describe('test create channel validation helpers', () => {

it('validates custom url host', () => {
const pass = validateCustomURLHost('test-webhook');
const httpTest = validateCustomURLHost('http://test-webhook');
const httpsTest = validateCustomURLHost('https://test-webhook');
const emptyInput = validateCustomURLHost('');
const invalidURL = validateCustomURLHost('http://test-webhook'); // only https is allowed
expect(pass).toHaveLength(0);
expect(httpTest).toHaveLength(0);
expect(httpsTest).toHaveLength(0);
expect(emptyInput).toHaveLength(1);
expect(invalidURL).toHaveLength(1);
});

it('validates custom url port', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,10 @@ export function EmailSettings(props: EmailSettingsProps) {
) => {
setSenderOptions([...senderOptions, newOption]);
props.setSelectedSenderOptions([newOption]);
context.setInputErrors({
...context.inputErrors,
sender: validateEmailSender([newOption]),
});
},
})
}
Expand Down Expand Up @@ -273,6 +277,10 @@ export function EmailSettings(props: EmailSettingsProps) {
...props.selectedRecipientGroupOptions,
newOption,
]);
context.setInputErrors({
...context.inputErrors,
recipients: validateRecipients([newOption]),
});
},
})
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,11 @@ import {
} from '@elastic/eui';
import React, { useContext } from 'react';
import { DOCUMENTATION_LINK } from '../../../utils/constants';
import { MainContext } from '../../Main/Main';
import { CreateChannelContext } from '../CreateChannel';
import { validateArn } from '../utils/validationHelper';

interface SNSSettingsProps {
isOdfe: boolean;
topicArn: string;
setTopicArn: (topicArn: string) => void;
roleArn: string;
Expand All @@ -47,6 +47,7 @@ interface SNSSettingsProps {

export function SNSSettings(props: SNSSettingsProps) {
const context = useContext(CreateChannelContext)!;
const mainStateContext = useContext(MainContext)!;
return (
<>
<EuiSpacer />
Expand All @@ -69,7 +70,7 @@ export function SNSSettings(props: SNSSettingsProps) {
/>
</EuiFormRow>

{props.isOdfe ? (
{mainStateContext.tooltipSupport ? (
<>
<EuiFormRow
label={
Expand Down Expand Up @@ -97,9 +98,8 @@ export function SNSSettings(props: SNSSettingsProps) {
style={{ maxWidth: 720 }}
>
<div>
If your cluster is not running on AWS, you must add your access
key, secret key, and optional session token to the OpenSearch
keystore.{' '}
If your cluster is not running on AWS, you must configure aws
credentials on your OpenSearch cluster.{' '}
<EuiLink href={DOCUMENTATION_LINK} target="_blank" external>
Learn more
</EuiLink>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ export const validateChannelName = (name: string) => {
export const validateWebhookURL = (url: string) => {
const errors = [];
if (url.length === 0) errors.push('Webhook URL cannot be empty.');
else if (!url.match(/^https:\/\/.+/)) errors.push('Invalid webhook URL.');
else if (!url.match(/^https?:\/\/.+/)) errors.push('Invalid webhook URL.');
return errors;
};

Expand All @@ -55,7 +55,6 @@ export const validateWebhookValue = (value: string) => {
export const validateCustomURLHost = (host: string) => {
const errors = [];
if (host.length === 0) errors.push('Host cannot be empty.');
else if (host.match(/^http:\/\//)) errors.push('Invalid webhook URL.');
return errors;
};

Expand Down
11 changes: 8 additions & 3 deletions dashboards-notifications/public/pages/Main/Main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ interface MainProps extends RouteComponentProps {}

export interface MainState {
availableFeatures: Partial<typeof CHANNEL_TYPE>;
tooltipSupport: boolean; // if true, IAM role for SNS is optional and helper text should be available
}

export const MainContext = createContext<MainState | null>(null);
Expand All @@ -68,13 +69,17 @@ export default class Main extends Component<MainProps, MainState> {
super(props);
this.state = {
availableFeatures: CHANNEL_TYPE,
tooltipSupport: false,
};
}

async componentDidMount() {
const availableFeatures =
await this.context.notificationService.getAvailableFeatures();
if (availableFeatures != null) this.setState({ availableFeatures });
const serverFeatures = await this.context.notificationService.getServerFeatures();
if (serverFeatures != null)
this.setState({
availableFeatures: serverFeatures.availableFeatures,
tooltipSupport: serverFeatures.tooltipSupport,
});
}

render() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -198,13 +198,13 @@ export default class Notifications extends Component<
const getNotificationsResponse = await services.eventService.getNotifications(
queryObject
);
const getHistogramResponse = await services.eventService.getHistogram(
queryObject
);
// const getHistogramResponse = await services.eventService.getHistogram(
// queryObject
// );
this.setState({
items: getNotificationsResponse.items,
total: getNotificationsResponse.total,
histogramData: getHistogramResponse,
// histogramData: getHistogramResponse,
});
} catch (err) {
this.context.notifications.toasts.addDanger(
Expand Down
4 changes: 2 additions & 2 deletions dashboards-notifications/public/services/EventService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@
import { HttpFetchQuery, HttpSetup } from '../../../../src/core/public';
import { NODE_API } from '../../common';
import { NOTIFICATION_SOURCE } from '../utils/constants';
import { MOCK_GET_HISTOGRAM } from './mockData';
import { eventListToNotifications, eventToNotification } from './utils/helper';

interface EventsResponse {
Expand All @@ -43,7 +42,8 @@ export default class EventService {
}

getHistogram = async (queryObject: object) => {
return MOCK_GET_HISTOGRAM();
// TODO needs backend support
// return MOCK_GET_HISTOGRAM();
};

getNotifications = async (queryObject: HttpFetchQuery) => {
Expand Down
Loading