From d27d52c23c9d66eb2b39dcb85ad22bd868737196 Mon Sep 17 00:00:00 2001 From: Aditya Jindal <13850971+aditjind@users.noreply.github.com> Date: Thu, 1 Jul 2021 17:47:57 -0700 Subject: [PATCH 001/140] Update Release Notes for GA (#36) * Update Release Notes for GA * Update Release Notes for GA include RC1 Changes as well. Signed-off-by: Aditya Jindal --- ...arch-common-utils.release-notes-1.0.0.0.md | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 release-notes/opensearch-common-utils.release-notes-1.0.0.0.md diff --git a/release-notes/opensearch-common-utils.release-notes-1.0.0.0.md b/release-notes/opensearch-common-utils.release-notes-1.0.0.0.md new file mode 100644 index 00000000..71d1a7db --- /dev/null +++ b/release-notes/opensearch-common-utils.release-notes-1.0.0.0.md @@ -0,0 +1,29 @@ +## Version 1.0.0.0 2021-07-01 + +Compatible with OpenSearch 1.0.0 + +### Enhancements + + * Notification plugin interface and models ([#31](https://github.com/opensearch-project/common-utils/pull/31)) + +### Infrastructure + + * Support for kotlin and JUnit5 with mockito ([#29](https://github.com/opensearch-project/common-utils/pull/29)) + * Removing Kotlin Runtime library bundled into library ([#30](https://github.com/opensearch-project/common-utils/pull/30)) + * Bump to version 1.0.0.0 #34 ([#34](https://github.com/opensearch-project/common-utils/pull/34)) + +### Documentation + + * Update OpenSearch branch to 1.0 ([#28](https://github.com/opensearch-project/common-utils/pull/28)) + * Cleanup READMEs. ([#32](https://github.com/opensearch-project/common-utils/pull/32)) + +### Maintainence + + * Update issue template with multiple labels ([#18](https://github.com/opensearch-project/common-utils/pull/18)) + * Rename namespaces from OpenDistro to OpenSearch ([#20](https://github.com/opensearch-project/common-utils/pull/20)) + * Rename classes, variables, methods to incorporate OpenSearch ([#21](https://github.com/opensearch-project/common-utils/pull/21)) + * Rename remaining identifiers to OpenSearch ([#23](https://github.com/opensearch-project/common-utils/pull/23)) + * Version changed to rc1 #24 ([#24](https://github.com/opensearch-project/common-utils/pull/24)) + * Rename consts as per changes in security plugin ([#25](https://github.com/opensearch-project/common-utils/pull/25)) + * Move workflow tags to rc1 ([#26](https://github.com/opensearch-project/common-utils/pull/26)) + * Add rc1 release notes ([#27](https://github.com/opensearch-project/common-utils/pull/27)) From 62de872df5a24b1e5e5617d7a84378b9fbf38444 Mon Sep 17 00:00:00 2001 From: Zhongnan Su Date: Fri, 16 Jul 2021 15:08:55 -0700 Subject: [PATCH 002/140] add method type in CustomWebhook data model (#39) Signed-off-by: Zhongnan Su --- .../notifications/model/HttpMethodType.kt | 36 +++++++++++++++++++ .../commons/notifications/model/Webhook.kt | 13 +++++-- .../notifications/model/WebhookTests.kt | 15 ++++++-- 3 files changed, 58 insertions(+), 6 deletions(-) create mode 100644 src/main/kotlin/org/opensearch/commons/notifications/model/HttpMethodType.kt diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/HttpMethodType.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/HttpMethodType.kt new file mode 100644 index 00000000..8485e4fd --- /dev/null +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/HttpMethodType.kt @@ -0,0 +1,36 @@ +package org.opensearch.commons.notifications.model + +import org.opensearch.commons.utils.EnumParser + +enum class HttpMethodType(val tag: String) { + POST("POST") { + override fun toString(): String { + return tag + } + }, + PUT("PUT") { + override fun toString(): String { + return tag + } + }, + PATCH("PATCH") { + override fun toString(): String { + return tag + } + }; + + companion object { + private val tagMap = values().associateBy { it.tag } + + val enumParser = EnumParser { fromTagOrDefault(it) } + + /** + * Get HttpMethodType from tag or POST if not found + * @param tag the tag + * @return MethodType corresponding to tag. POST if invalid tag. + */ + fun fromTagOrDefault(tag: String): HttpMethodType { + return tagMap[tag] ?: POST + } + } +} diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/Webhook.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/Webhook.kt index 55a4cb3e..09dbfe9d 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/Webhook.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/Webhook.kt @@ -35,6 +35,7 @@ import org.opensearch.common.xcontent.XContentBuilder import org.opensearch.common.xcontent.XContentParser import org.opensearch.common.xcontent.XContentParserUtils import org.opensearch.commons.notifications.NotificationConstants.HEADER_PARAMS_TAG +import org.opensearch.commons.notifications.NotificationConstants.METHOD_TAG import org.opensearch.commons.notifications.NotificationConstants.URL_TAG import org.opensearch.commons.utils.STRING_READER import org.opensearch.commons.utils.STRING_WRITER @@ -47,7 +48,8 @@ import java.io.IOException */ data class Webhook( val url: String, - val headerParams: Map = mapOf() + val headerParams: Map = mapOf(), + val method: HttpMethodType = HttpMethodType.POST ) : BaseConfigData { init { @@ -77,6 +79,7 @@ data class Webhook( fun parse(parser: XContentParser): Webhook { var url: String? = null var headerParams: Map = mapOf() + var method = HttpMethodType.POST XContentParserUtils.ensureExpectedToken( XContentParser.Token.START_OBJECT, @@ -89,6 +92,7 @@ data class Webhook( when (fieldName) { URL_TAG -> url = parser.text() HEADER_PARAMS_TAG -> headerParams = parser.mapStrings() + METHOD_TAG -> method = HttpMethodType.fromTagOrDefault(parser.text()) else -> { parser.skipChildren() log.info("Unexpected field: $fieldName, while parsing Webhook destination") @@ -96,7 +100,7 @@ data class Webhook( } } url ?: throw IllegalArgumentException("$URL_TAG field absent") - return Webhook(url, headerParams) + return Webhook(url, headerParams, method) } } @@ -108,6 +112,7 @@ data class Webhook( return builder.startObject() .field(URL_TAG, url) .field(HEADER_PARAMS_TAG, headerParams) + .field(METHOD_TAG, method.tag) .endObject() } @@ -117,7 +122,8 @@ data class Webhook( */ constructor(input: StreamInput) : this( url = input.readString(), - headerParams = input.readMap(STRING_READER, STRING_READER) + headerParams = input.readMap(STRING_READER, STRING_READER), + method = input.readEnum(HttpMethodType::class.java) ) /** @@ -126,5 +132,6 @@ data class Webhook( override fun writeTo(output: StreamOutput) { output.writeString(url) output.writeMap(headerParams, STRING_WRITER, STRING_WRITER) + output.writeEnum(method) } } diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/WebhookTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/WebhookTests.kt index 9ca39c7c..48dedf49 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/WebhookTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/WebhookTests.kt @@ -46,7 +46,11 @@ internal class WebhookTests { @Test fun `Webhook serialize and deserialize using json object should be equal`() { - val sampleWebhook = Webhook("https://domain.com/sample_url#1234567890", mapOf(Pair("key", "value"))) + val sampleWebhook = Webhook( + "https://domain.com/sample_url#1234567890", + mapOf(Pair("key", "value")), + HttpMethodType.PUT + ) val jsonString = getJsonString(sampleWebhook) val recreatedObject = createObjectFromJsonString(jsonString) { Webhook.parse(it) } assertEquals(sampleWebhook, recreatedObject) @@ -54,13 +58,18 @@ internal class WebhookTests { @Test fun `Webhook should deserialize json object using parser`() { - val sampleWebhook = Webhook("https://domain.com/sample_url#1234567890", mapOf(Pair("key", "value"))) + val sampleWebhook = Webhook( + "https://domain.com/sample_url#1234567890", + mapOf(Pair("key", "value")), + HttpMethodType.PATCH + ) val jsonString = """ { "url":"${sampleWebhook.url}", "header_params":{ "key":"value" - } + }, + "method":"PATCH" } """.trimIndent() val recreatedObject = createObjectFromJsonString(jsonString) { Webhook.parse(it) } From 4ef189df7708ace7bf91867bbe6b30fd3bf98a9c Mon Sep 17 00:00:00 2001 From: Chen Dai <46505291+dai-chen@users.noreply.github.com> Date: Tue, 20 Jul 2021 09:37:48 -0700 Subject: [PATCH 003/140] Fix class loader issue for notifications response (#40) * Fix class loader issue for notifications Signed-off-by: Joshua Li * Fix formatting Signed-off-by: Joshua Li * Refactor creation of action listener object Signed-off-by: Joshua Li * Fix indentation Signed-off-by: Joshua Li * Remove unused suppresses Signed-off-by: Joshua Li * Add UT for notification API Signed-off-by: Chen Dai * Add UT for notification API Signed-off-by: Chen Dai * Add UT for send notification API Signed-off-by: Chen Dai * Fix Github workflow failure Signed-off-by: Chen Dai * Fix Github workflow failure Signed-off-by: Chen Dai * Refactor UT code Signed-off-by: Chen Dai Co-authored-by: Joshua Li --- .../NotificationsPluginInterface.kt | 43 ++- .../NotificationsPluginInterfaceTests.kt | 268 ++++++++++++++++++ .../org.mockito.plugins.MockMaker | 1 + 3 files changed, 304 insertions(+), 8 deletions(-) create mode 100644 src/test/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterfaceTests.kt create mode 100644 src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker diff --git a/src/main/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterface.kt b/src/main/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterface.kt index e82aaba8..2f043351 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterface.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterface.kt @@ -27,8 +27,11 @@ package org.opensearch.commons.notifications import org.opensearch.action.ActionListener +import org.opensearch.action.ActionResponse import org.opensearch.client.node.NodeClient +import org.opensearch.common.io.stream.Writeable import org.opensearch.commons.ConfigConstants.OPENSEARCH_SECURITY_USER_INFO_THREAD_CONTEXT +import org.opensearch.commons.notifications.action.BaseResponse import org.opensearch.commons.notifications.action.CreateNotificationConfigRequest import org.opensearch.commons.notifications.action.CreateNotificationConfigResponse import org.opensearch.commons.notifications.action.DeleteNotificationConfigRequest @@ -56,6 +59,7 @@ import org.opensearch.commons.notifications.action.UpdateNotificationConfigRespo import org.opensearch.commons.notifications.model.ChannelMessage import org.opensearch.commons.notifications.model.EventSource import org.opensearch.commons.utils.SecureClientWrapper +import org.opensearch.commons.utils.recreateObject /** * All the transport action plugin interfaces for the Notification plugin @@ -76,7 +80,7 @@ object NotificationsPluginInterface { client.execute( CREATE_NOTIFICATION_CONFIG_ACTION_TYPE, request, - listener + wrapActionListener(listener) { response -> recreateObject(response) { CreateNotificationConfigResponse(it) } } ) } @@ -94,7 +98,7 @@ object NotificationsPluginInterface { client.execute( UPDATE_NOTIFICATION_CONFIG_ACTION_TYPE, request, - listener + wrapActionListener(listener) { response -> recreateObject(response) { UpdateNotificationConfigResponse(it) } } ) } @@ -112,7 +116,7 @@ object NotificationsPluginInterface { client.execute( DELETE_NOTIFICATION_CONFIG_ACTION_TYPE, request, - listener + wrapActionListener(listener) { response -> recreateObject(response) { DeleteNotificationConfigResponse(it) } } ) } @@ -130,7 +134,7 @@ object NotificationsPluginInterface { client.execute( GET_NOTIFICATION_CONFIG_ACTION_TYPE, request, - listener + wrapActionListener(listener) { response -> recreateObject(response) { GetNotificationConfigResponse(it) } } ) } @@ -148,7 +152,7 @@ object NotificationsPluginInterface { client.execute( GET_NOTIFICATION_EVENT_ACTION_TYPE, request, - listener + wrapActionListener(listener) { response -> recreateObject(response) { GetNotificationEventResponse(it) } } ) } @@ -166,7 +170,7 @@ object NotificationsPluginInterface { client.execute( GET_PLUGIN_FEATURES_ACTION_TYPE, request, - listener + wrapActionListener(listener) { response -> recreateObject(response) { GetPluginFeaturesResponse(it) } } ) } @@ -184,7 +188,7 @@ object NotificationsPluginInterface { client.execute( GET_FEATURE_CHANNEL_LIST_ACTION_TYPE, request, - listener + wrapActionListener(listener) { response -> recreateObject(response) { GetFeatureChannelListResponse(it) } } ) } @@ -209,7 +213,30 @@ object NotificationsPluginInterface { wrapper.execute( SEND_NOTIFICATION_ACTION_TYPE, SendNotificationRequest(eventSource, channelMessage, channelIds, threadContext), - listener + wrapActionListener(listener) { response -> recreateObject(response) { SendNotificationResponse(it) } } ) } + + /** + * Wrap action listener on concrete response class by a new created one on ActionResponse. + * This is required because the response may be loaded by different classloader across plugins. + * The onResponse(ActionResponse) avoids type cast exception and give a chance to recreate + * the response object. + */ + @Suppress("UNCHECKED_CAST") + private fun wrapActionListener( + listener: ActionListener, + recreate: (Writeable) -> Response + ): ActionListener { + return object : ActionListener { + override fun onResponse(response: ActionResponse) { + val recreated = response as? Response ?: recreate(response) + listener.onResponse(recreated) + } + + override fun onFailure(exception: java.lang.Exception) { + listener.onFailure(exception) + } + } as ActionListener + } } diff --git a/src/test/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterfaceTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterfaceTests.kt new file mode 100644 index 00000000..99f558f4 --- /dev/null +++ b/src/test/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterfaceTests.kt @@ -0,0 +1,268 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + * + * Modifications Copyright OpenSearch Contributors. See + * GitHub history for details. + */ +package org.opensearch.commons.notifications + +import com.nhaarman.mockitokotlin2.whenever +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.extension.ExtendWith +import org.mockito.Answers +import org.mockito.ArgumentMatchers.eq +import org.mockito.Mock +import org.mockito.Mockito.any +import org.mockito.Mockito.doAnswer +import org.mockito.Mockito.mock +import org.mockito.Mockito.times +import org.mockito.Mockito.verify +import org.mockito.junit.jupiter.MockitoExtension +import org.opensearch.action.ActionListener +import org.opensearch.action.ActionType +import org.opensearch.client.node.NodeClient +import org.opensearch.commons.notifications.action.CreateNotificationConfigRequest +import org.opensearch.commons.notifications.action.CreateNotificationConfigResponse +import org.opensearch.commons.notifications.action.DeleteNotificationConfigRequest +import org.opensearch.commons.notifications.action.DeleteNotificationConfigResponse +import org.opensearch.commons.notifications.action.GetFeatureChannelListRequest +import org.opensearch.commons.notifications.action.GetFeatureChannelListResponse +import org.opensearch.commons.notifications.action.GetNotificationConfigRequest +import org.opensearch.commons.notifications.action.GetNotificationConfigResponse +import org.opensearch.commons.notifications.action.GetNotificationEventRequest +import org.opensearch.commons.notifications.action.GetNotificationEventResponse +import org.opensearch.commons.notifications.action.GetPluginFeaturesRequest +import org.opensearch.commons.notifications.action.GetPluginFeaturesResponse +import org.opensearch.commons.notifications.action.SendNotificationResponse +import org.opensearch.commons.notifications.action.UpdateNotificationConfigRequest +import org.opensearch.commons.notifications.action.UpdateNotificationConfigResponse +import org.opensearch.commons.notifications.model.ChannelMessage +import org.opensearch.commons.notifications.model.ConfigType +import org.opensearch.commons.notifications.model.DeliveryStatus +import org.opensearch.commons.notifications.model.EventSource +import org.opensearch.commons.notifications.model.EventStatus +import org.opensearch.commons.notifications.model.Feature +import org.opensearch.commons.notifications.model.FeatureChannel +import org.opensearch.commons.notifications.model.FeatureChannelList +import org.opensearch.commons.notifications.model.NotificationConfig +import org.opensearch.commons.notifications.model.NotificationConfigInfo +import org.opensearch.commons.notifications.model.NotificationConfigSearchResult +import org.opensearch.commons.notifications.model.NotificationEvent +import org.opensearch.commons.notifications.model.NotificationEventInfo +import org.opensearch.commons.notifications.model.NotificationEventSearchResult +import org.opensearch.commons.notifications.model.SeverityType +import org.opensearch.commons.notifications.model.Slack +import org.opensearch.rest.RestStatus +import java.time.Instant +import java.util.EnumSet + +@Suppress("UNCHECKED_CAST") +@ExtendWith(MockitoExtension::class) +internal class NotificationsPluginInterfaceTests { + + @Mock(answer = Answers.RETURNS_DEEP_STUBS) + private lateinit var client: NodeClient + + @Test + fun createNotificationConfig() { + val request = mock(CreateNotificationConfigRequest::class.java) + val response = CreateNotificationConfigResponse("configId") + val listener: ActionListener = + mock(ActionListener::class.java) as ActionListener + + doAnswer { + (it.getArgument(2) as ActionListener) + .onResponse(response) + }.whenever(client).execute(any(ActionType::class.java), any(), any()) + + NotificationsPluginInterface.createNotificationConfig(client, request, listener) + verify(listener, times(1)).onResponse(eq(response)) + } + + @Test + fun updateNotificationConfig() { + val request = mock(UpdateNotificationConfigRequest::class.java) + val response = UpdateNotificationConfigResponse("configId") + val listener: ActionListener = + mock(ActionListener::class.java) as ActionListener + + doAnswer { + (it.getArgument(2) as ActionListener) + .onResponse(response) + }.whenever(client).execute(any(ActionType::class.java), any(), any()) + + NotificationsPluginInterface.updateNotificationConfig(client, request, listener) + verify(listener, times(1)).onResponse(eq(response)) + } + + @Test + fun deleteNotificationConfig() { + val request = mock(DeleteNotificationConfigRequest::class.java) + val response = DeleteNotificationConfigResponse(mapOf(Pair("sample_config_id", RestStatus.OK))) + val listener: ActionListener = + mock(ActionListener::class.java) as ActionListener + + doAnswer { + (it.getArgument(2) as ActionListener) + .onResponse(response) + }.whenever(client).execute(any(ActionType::class.java), any(), any()) + + NotificationsPluginInterface.deleteNotificationConfig(client, request, listener) + verify(listener, times(1)).onResponse(eq(response)) + } + + @Test + fun getNotificationConfig() { + val request = mock(GetNotificationConfigRequest::class.java) + val response = mockGetNotificationConfigResponse() + val listener: ActionListener = + mock(ActionListener::class.java) as ActionListener + + doAnswer { + (it.getArgument(2) as ActionListener) + .onResponse(response) + }.whenever(client).execute(any(ActionType::class.java), any(), any()) + + NotificationsPluginInterface.getNotificationConfig(client, request, listener) + verify(listener, times(1)).onResponse(eq(response)) + } + + @Test + fun getNotificationEvent() { + val request = mock(GetNotificationEventRequest::class.java) + val response = mockGetNotificationEventResponse() + val listener: ActionListener = + mock(ActionListener::class.java) as ActionListener + + doAnswer { + (it.getArgument(2) as ActionListener) + .onResponse(response) + }.whenever(client).execute(any(ActionType::class.java), any(), any()) + + NotificationsPluginInterface.getNotificationEvent(client, request, listener) + verify(listener, times(1)).onResponse(eq(response)) + } + + @Test + fun getPluginFeatures() { + val request = mock(GetPluginFeaturesRequest::class.java) + val response = GetPluginFeaturesResponse( + listOf("config_type_1", "config_type_2", "config_type_3"), + mapOf( + Pair("FeatureKey1", "FeatureValue1"), + Pair("FeatureKey2", "FeatureValue2"), + Pair("FeatureKey3", "FeatureValue3") + ) + ) + val listener: ActionListener = + mock(ActionListener::class.java) as ActionListener + + doAnswer { + (it.getArgument(2) as ActionListener) + .onResponse(response) + }.whenever(client).execute(any(ActionType::class.java), any(), any()) + + NotificationsPluginInterface.getPluginFeatures(client, request, listener) + verify(listener, times(1)).onResponse(eq(response)) + } + + @Test + fun getFeatureChannelList() { + val sampleConfig = FeatureChannel( + "config_id", + "name", + "description", + ConfigType.SLACK + ) + + val request = mock(GetFeatureChannelListRequest::class.java) + val response = GetFeatureChannelListResponse(FeatureChannelList(sampleConfig)) + val listener: ActionListener = + mock(ActionListener::class.java) as ActionListener + + doAnswer { + (it.getArgument(2) as ActionListener) + .onResponse(response) + }.whenever(client).execute(any(ActionType::class.java), any(), any()) + + NotificationsPluginInterface.getFeatureChannelList(client, request, listener) + verify(listener, times(1)).onResponse(eq(response)) + } + + @Test + fun sendNotification() { + val notificationInfo = EventSource( + "title", + "reference_id", + Feature.REPORTS, + SeverityType.HIGH, + listOf("tag1", "tag2") + ) + val channelMessage = ChannelMessage( + "text_description", + "htmlDescription", + null + ) + + val response = SendNotificationResponse("configId") + val listener: ActionListener = + mock(ActionListener::class.java) as ActionListener + + doAnswer { + (it.getArgument(2) as ActionListener) + .onResponse(response) + }.whenever(client).execute(any(ActionType::class.java), any(), any()) + + NotificationsPluginInterface.sendNotification( + client, notificationInfo, channelMessage, listOf("channelId1", "channelId2"), listener + ) + verify(listener, times(1)).onResponse(eq(response)) + } + + private fun mockGetNotificationConfigResponse(): GetNotificationConfigResponse { + val sampleSlack = Slack("https://domain.com/sample_url#1234567890") + val sampleConfig = NotificationConfig( + "name", + "description", + ConfigType.SLACK, + EnumSet.of(Feature.REPORTS), + configData = sampleSlack + ) + val configInfo = NotificationConfigInfo( + "config_id", + Instant.now(), + Instant.now(), + "tenant", + sampleConfig + ) + return GetNotificationConfigResponse(NotificationConfigSearchResult(configInfo)) + } + + private fun mockGetNotificationEventResponse(): GetNotificationEventResponse { + val sampleEventSource = EventSource( + "title", + "reference_id", + Feature.ALERTING, + severity = SeverityType.INFO + ) + val sampleStatus = EventStatus( + "config_id", + "name", + ConfigType.SLACK, + deliveryStatus = DeliveryStatus("404", "invalid recipient") + ) + val sampleEvent = NotificationEvent(sampleEventSource, listOf(sampleStatus)) + val eventInfo = NotificationEventInfo( + "event_id", + Instant.now(), + Instant.now(), + "tenant", + sampleEvent + ) + return GetNotificationEventResponse(NotificationEventSearchResult(eventInfo)) + } +} diff --git a/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker b/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker new file mode 100644 index 00000000..ca6ee9ce --- /dev/null +++ b/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker @@ -0,0 +1 @@ +mock-maker-inline \ No newline at end of file From 0af72bffc3b4ff17d8acd588dbfe298602c7448e Mon Sep 17 00:00:00 2001 From: Zhongnan Su Date: Mon, 2 Aug 2021 10:34:23 -0700 Subject: [PATCH 004/140] remove restrictions on webhook url protocols to also include http (#43) --- .../org/opensearch/commons/utils/ValidationHelpers.kt | 6 +----- .../opensearch/commons/notifications/model/ChimeTests.kt | 6 +++--- .../opensearch/commons/notifications/model/SlackTests.kt | 6 +++--- .../commons/notifications/model/WebhookTests.kt | 8 ++++---- 4 files changed, 11 insertions(+), 15 deletions(-) diff --git a/src/main/kotlin/org/opensearch/commons/utils/ValidationHelpers.kt b/src/main/kotlin/org/opensearch/commons/utils/ValidationHelpers.kt index 93bcdc77..0124179f 100644 --- a/src/main/kotlin/org/opensearch/commons/utils/ValidationHelpers.kt +++ b/src/main/kotlin/org/opensearch/commons/utils/ValidationHelpers.kt @@ -34,9 +34,6 @@ private val VALID_ID_CHARS: Set = (('a'..'z') + ('A'..'Z') + ('0'..'9') + fun validateUrl(urlString: String) { require(isValidUrl(urlString)) { "Invalid URL or unsupported" } - val url = URL(urlString) - require("https" == url.protocol) // Support only HTTPS. HTTP and other protocols not supported - // TODO : Add hosts deny list } fun validateEmail(email: String) { @@ -49,8 +46,7 @@ fun validateId(idString: String) { fun isValidUrl(urlString: String): Boolean { val url = URL(urlString) // throws MalformedURLException if URL is invalid - // TODO : Add hosts deny list - return ("https" == url.protocol) // Support only HTTPS. HTTP and other protocols not supported + return ("https" == url.protocol || "http" == url.protocol) // Support only http/https, other protocols not supported } /** diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/ChimeTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/ChimeTests.kt index f70dc097..da404b28 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/ChimeTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/ChimeTests.kt @@ -89,11 +89,11 @@ internal class ChimeTests { } @Test - fun `Chime should throw exception when url protocol is not https`() { + fun `Chime should throw exception when url protocol is not https or http`() { assertThrows { - Chime("http://domain.com/sample_url#1234567890") + Chime("ftp://domain.com/sample_url#1234567890") } - val jsonString = "{\"url\":\"http://domain.com/sample_url\"}" + val jsonString = "{\"url\":\"ftp://domain.com/sample_url\"}" assertThrows { createObjectFromJsonString(jsonString) { Chime.parse(it) } } diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/SlackTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/SlackTests.kt index b5bf7783..98fbc0cd 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/SlackTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/SlackTests.kt @@ -89,11 +89,11 @@ internal class SlackTests { } @Test - fun `Slack should throw exception when url protocol is not https`() { + fun `Slack should throw exception when url protocol is not https or http`() { assertThrows { - Slack("http://domain.com/sample_url#1234567890") + Slack("ftp://domain.com/sample_url#1234567890") } - val jsonString = "{\"url\":\"http://domain.com/sample_url\"}" + val jsonString = "{\"url\":\"ftp://domain.com/sample_url\"}" assertThrows { createObjectFromJsonString(jsonString) { Slack.parse(it) } } diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/WebhookTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/WebhookTests.kt index 48dedf49..5a717669 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/WebhookTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/WebhookTests.kt @@ -47,7 +47,7 @@ internal class WebhookTests { @Test fun `Webhook serialize and deserialize using json object should be equal`() { val sampleWebhook = Webhook( - "https://domain.com/sample_url#1234567890", + "http://domain.com/sample_url#1234567890", mapOf(Pair("key", "value")), HttpMethodType.PUT ) @@ -105,11 +105,11 @@ internal class WebhookTests { } @Test - fun `Webhook should throw exception when url protocol is not https`() { + fun `Webhook should throw exception when url protocol is not https or http`() { assertThrows { - Webhook("http://domain.com/sample_url#1234567890") + Webhook("ftp://domain.com/sample_url#1234567890") } - val jsonString = "{\"url\":\"http://domain.com/sample_url\"}" + val jsonString = "{\"url\":\"ftp://domain.com/sample_url\"}" assertThrows { createObjectFromJsonString(jsonString) { Webhook.parse(it) } } From bf2bfb312776b840acc4d3c9f92922441d996f31 Mon Sep 17 00:00:00 2001 From: Sarat Vemulapalli Date: Fri, 6 Aug 2021 09:43:06 -0700 Subject: [PATCH 005/140] Bumping common-utils to build with OpenSearch(main) 1.1.0 (#48) Signed-off-by: Sarat Vemulapalli --- .github/workflows/ci.yml | 6 +++--- build.gradle | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f49c13b9..4f0adf94 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -31,7 +31,7 @@ jobs: with: repository: 'opensearch-project/OpenSearch' path: OpenSearch - ref: '1.0' + ref: 'main' - name: Build OpenSearch working-directory: ./OpenSearch run: ./gradlew publishToMavenLocal -Dbuild.snapshot=false @@ -39,11 +39,11 @@ jobs: # common-utils - name: Build and Test run: | - ./gradlew build -Dopensearch.version=1.0.0 + ./gradlew build -Dopensearch.version=1.1.0 - name: Publish to Maven Local run: | - ./gradlew publishToMavenLocal -Dopensearch.version=1.0.0 + ./gradlew publishToMavenLocal -Dopensearch.version=1.1.0 - name: Upload Coverage Report uses: codecov/codecov-action@v1 diff --git a/build.gradle b/build.gradle index 2d955951..0f2b241a 100644 --- a/build.gradle +++ b/build.gradle @@ -12,7 +12,7 @@ buildscript { ext { opensearch_group = "org.opensearch" - opensearch_version = System.getProperty("opensearch.version", "1.0.0") + opensearch_version = System.getProperty("opensearch.version", "1.1.0") kotlin_version = System.getProperty("kotlin.version", "1.4.32") } @@ -146,7 +146,7 @@ task javadocJar(type: Jar) { from javadoc.destinationDir } -version '1.0.0.0' +version '1.1.0.0' publishing { publications { From 28e688b76e4a4bf99312ae051576c405e3f4ce4f Mon Sep 17 00:00:00 2001 From: Ravi <6005951+thalurur@users.noreply.github.com> Date: Fri, 6 Aug 2021 09:47:39 -0700 Subject: [PATCH 006/140] Adding an utility method that allows consumers to set custom thread context property in InjectSecurity class (#47) Signed-off-by: Ravi Thaluru --- .../opensearch/commons/InjectSecurity.java | 17 ++++++ .../commons/InjectSecurityTest.java | 54 +++++++++++++++++++ 2 files changed, 71 insertions(+) diff --git a/src/main/java/org/opensearch/commons/InjectSecurity.java b/src/main/java/org/opensearch/commons/InjectSecurity.java index ab4f0323..2240ab60 100644 --- a/src/main/java/org/opensearch/commons/InjectSecurity.java +++ b/src/main/java/org/opensearch/commons/InjectSecurity.java @@ -160,6 +160,23 @@ public void injectRoles(final List roles) { } } + /** + * Allows one to set the property in threadContext if possible to the value provided. If not possible returns false. + * @param property + * @param value + * @return boolean + */ + public boolean injectProperty(final String property, final Object value) { + if (Strings.isNullOrEmpty(property) || value == null || threadContext.getTransient(property) != null) { + log.debug("{}, InjectSecurity - cannot inject property: {}", Thread.currentThread().getName(), id); + return false; + } else { + threadContext.putTransient(property, value); + log.debug("{}, InjectSecurity - inject property: {}", Thread.currentThread().getName(), id); + return true; + } + } + @Override public void close() { if (ctx != null) { diff --git a/src/test/java/org/opensearch/commons/InjectSecurityTest.java b/src/test/java/org/opensearch/commons/InjectSecurityTest.java index 0f6e0c83..a9073d93 100644 --- a/src/test/java/org/opensearch/commons/InjectSecurityTest.java +++ b/src/test/java/org/opensearch/commons/InjectSecurityTest.java @@ -27,13 +27,16 @@ package org.opensearch.commons; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; import static org.opensearch.commons.ConfigConstants.INJECTED_USER; import static org.opensearch.commons.ConfigConstants.OPENSEARCH_SECURITY_INJECTED_ROLES; import static org.opensearch.commons.ConfigConstants.OPENSEARCH_SECURITY_USE_INJECTED_USER_FOR_PLUGINS; import java.util.Arrays; +import java.util.Map; import org.junit.jupiter.api.Test; import org.opensearch.common.settings.Settings; @@ -102,4 +105,55 @@ public void testInjectUser() { assertEquals("plugin", threadContext.getTransient("ctx.name")); assertNull(threadContext.getTransient(INJECTED_USER)); } + + @Test + public void testInjectProperty() { + Settings settings = Settings.builder().put(OPENSEARCH_SECURITY_USE_INJECTED_USER_FOR_PLUGINS, false).build(); + Settings headerSettings = Settings.builder().put("request.headers.default", "1").build(); + ThreadContext threadContext = new ThreadContext(headerSettings); + threadContext.putHeader("name", "opendistro"); + threadContext.putTransient("ctx.name", "plugin"); + + assertEquals("1", threadContext.getHeader("default")); + assertEquals("opendistro", threadContext.getHeader("name")); + assertEquals("plugin", threadContext.getTransient("ctx.name")); + + try (InjectSecurity helper = new InjectSecurity("test-name", settings, threadContext)) { + helper.inject("joe", Arrays.asList("ops-role", "logs-role")); + assertEquals("1", threadContext.getHeader("default")); + assertEquals("opendistro", threadContext.getHeader("name")); + assertEquals("plugin", threadContext.getTransient("ctx.name")); + assertNotNull(threadContext.getTransient(OPENSEARCH_SECURITY_INJECTED_ROLES)); + // cannot inject property that is already set + assertFalse(helper.injectProperty(OPENSEARCH_SECURITY_INJECTED_ROLES, "new value")); + assertEquals("plugin|ops-role,logs-role", threadContext.getTransient(OPENSEARCH_SECURITY_INJECTED_ROLES)); + // cannot inject invalid property/value + assertFalse(helper.injectProperty("", "new value")); + assertFalse(helper.injectProperty(null, "new value")); + assertFalse(helper.injectProperty("property", null)); + // can inject non-set valid properties + assertTrue(helper.injectProperty("property1", true)); + assertTrue(helper.injectProperty("property2", "some value")); + assertTrue(helper.injectProperty("property3", "")); + assertTrue(helper.injectProperty("property4", Map.of("key", "value"))); + // verify the set properties are not null and equal to what was set + assertNull(threadContext.getTransient("property")); + assertNotNull(threadContext.getTransient("property1")); + assertEquals(true, threadContext.getTransient("property1")); + assertNotNull(threadContext.getTransient("property2")); + assertEquals("some value", threadContext.getTransient("property2")); + assertNotNull(threadContext.getTransient("property3")); + assertEquals("", threadContext.getTransient("property3")); + assertNotNull(threadContext.getTransient("property4")); + assertEquals(Map.of("key", "value"), threadContext.getTransient("property4")); + } + assertEquals("1", threadContext.getHeader("default")); + assertEquals("opendistro", threadContext.getHeader("name")); + assertEquals("plugin", threadContext.getTransient("ctx.name")); + assertNull(threadContext.getTransient(OPENSEARCH_SECURITY_INJECTED_ROLES)); + assertNull(threadContext.getTransient("property1")); + assertNull(threadContext.getTransient("property2")); + assertNull(threadContext.getTransient("property3")); + assertNull(threadContext.getTransient("property4")); + } } From b18a489dc7c61f1e3ce6de3eef8d0b9b9482b363 Mon Sep 17 00:00:00 2001 From: Joshua Date: Mon, 9 Aug 2021 15:00:19 -0700 Subject: [PATCH 007/140] Add Notifications SNS model (#50) --- .../notifications/NotificationConstants.kt | 2 + .../commons/notifications/model/ConfigType.kt | 5 + .../notifications/model/EventStatus.kt | 1 + .../commons/notifications/model/SNS.kt | 112 ++++++++++++++++++ .../model/config/ConfigDataProperties.kt | 3 + .../commons/utils/ValidationHelpers.kt | 6 + .../commons/notifications/model/SNSTests.kt | 105 ++++++++++++++++ 7 files changed, 234 insertions(+) create mode 100644 src/main/kotlin/org/opensearch/commons/notifications/model/SNS.kt create mode 100644 src/test/kotlin/org/opensearch/commons/notifications/model/SNSTests.kt diff --git a/src/main/kotlin/org/opensearch/commons/notifications/NotificationConstants.kt b/src/main/kotlin/org/opensearch/commons/notifications/NotificationConstants.kt index 344cf0b8..04f3affe 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/NotificationConstants.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/NotificationConstants.kt @@ -42,6 +42,8 @@ object NotificationConstants { const val TAGS_TAG = "tags" const val URL_TAG = "url" const val HEADER_PARAMS_TAG = "header_params" + const val TOPIC_ARN_FIELD = "topic_arn" + const val ROLE_ARN_FIELD = "role_arn" const val HOST_TAG = "host" const val PORT_TAG = "port" const val METHOD_TAG = "method" diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/ConfigType.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/ConfigType.kt index 0dbe70a6..d5400a75 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/ConfigType.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/ConfigType.kt @@ -57,6 +57,11 @@ enum class ConfigType(val tag: String) { return tag } }, + SNS("sns") { + override fun toString(): String { + return tag + } + }, SMTP_ACCOUNT("smtp_account") { override fun toString(): String { return tag diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/EventStatus.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/EventStatus.kt index 1233a997..bf72836d 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/EventStatus.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/EventStatus.kt @@ -64,6 +64,7 @@ data class EventStatus( ConfigType.WEBHOOK -> requireNotNull(deliveryStatus) ConfigType.SLACK -> requireNotNull(deliveryStatus) ConfigType.EMAIL -> require(emailRecipientStatus.isNotEmpty()) + ConfigType.SNS -> requireNotNull(deliveryStatus) ConfigType.NONE -> log.info("Some config field not recognized") else -> { log.info("non-allowed config type for Status") diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/SNS.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/SNS.kt new file mode 100644 index 00000000..12cdba4f --- /dev/null +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/SNS.kt @@ -0,0 +1,112 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + * + * Modifications Copyright OpenSearch Contributors. See + * GitHub history for details. + */ +package org.opensearch.commons.notifications.model + +import org.opensearch.common.io.stream.StreamInput +import org.opensearch.common.io.stream.StreamOutput +import org.opensearch.common.io.stream.Writeable +import org.opensearch.common.xcontent.ToXContent +import org.opensearch.common.xcontent.XContentBuilder +import org.opensearch.common.xcontent.XContentParser +import org.opensearch.common.xcontent.XContentParserUtils +import org.opensearch.commons.notifications.NotificationConstants.ROLE_ARN_FIELD +import org.opensearch.commons.notifications.NotificationConstants.TOPIC_ARN_FIELD +import org.opensearch.commons.utils.fieldIfNotNull +import org.opensearch.commons.utils.logger +import org.opensearch.commons.utils.validateIAMRoleArn +import java.io.IOException +import java.util.regex.Pattern + +/** + * SNS notification data model + */ +data class SNS(val topicARN: String, val roleARN: String?) : BaseConfigData { + + init { + require(SNS_ARN_REGEX.matcher(topicARN).find()) { "Invalid AWS SNS topic ARN: $topicARN" } + if (roleARN != null) { + validateIAMRoleArn(roleARN) + } + } + + override fun toXContent(builder: XContentBuilder, params: ToXContent.Params): XContentBuilder { + return builder.startObject() + .field(TOPIC_ARN_FIELD, topicARN) + .fieldIfNotNull(ROLE_ARN_FIELD, roleARN) + .endObject() + } + + /** + * Constructor used in transport action communication. + * @param input StreamInput stream to deserialize data from. + */ + constructor(input: StreamInput) : this( + topicARN = input.readString(), + roleARN = input.readOptionalString() + ) + + @Throws(IOException::class) + override fun writeTo(out: StreamOutput) { + out.writeString(topicARN) + out.writeOptionalString(roleARN) + } + + companion object { + private val log by logger(SNS::class.java) + + private val SNS_ARN_REGEX = + Pattern.compile("^arn:aws(-[^:]+)?:sns:([a-zA-Z0-9-]+):([0-9]{12}):([a-zA-Z0-9-_]+)$") + + /** + * reader to create instance of class from writable. + */ + val reader = Writeable.Reader { SNS(it) } + + /** + * Parser to parse xContent + */ + val xParser = XParser { parse(it) } + + @JvmStatic + @Throws(IOException::class) + fun parse(xcp: XContentParser): SNS { + var topicARN: String? = null + var roleARN: String? = null + + XContentParserUtils.ensureExpectedToken(XContentParser.Token.START_OBJECT, xcp.currentToken(), xcp) + while (xcp.nextToken() != XContentParser.Token.END_OBJECT) { + val fieldName = xcp.currentName() + xcp.nextToken() + when (fieldName) { + TOPIC_ARN_FIELD -> topicARN = xcp.textOrNull() + ROLE_ARN_FIELD -> roleARN = xcp.textOrNull() + else -> { + xcp.skipChildren() + log.info("Unexpected field: $fieldName, while parsing SNS destination") + } + } + } + topicARN ?: throw IllegalArgumentException("$TOPIC_ARN_FIELD field absent") + return SNS(topicARN, roleARN) + } + + @JvmStatic + @Throws(IOException::class) + fun readFrom(sin: StreamInput): SNS? { + return if (sin.readBoolean()) { + SNS( + topicARN = sin.readString(), + roleARN = sin.readOptionalString() + ) + } else null + } + } +} diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/config/ConfigDataProperties.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/config/ConfigDataProperties.kt index 1500879c..34bd2edc 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/config/ConfigDataProperties.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/config/ConfigDataProperties.kt @@ -33,6 +33,7 @@ import org.opensearch.commons.notifications.model.Chime import org.opensearch.commons.notifications.model.ConfigType import org.opensearch.commons.notifications.model.Email import org.opensearch.commons.notifications.model.EmailGroup +import org.opensearch.commons.notifications.model.SNS import org.opensearch.commons.notifications.model.Slack import org.opensearch.commons.notifications.model.SmtpAccount import org.opensearch.commons.notifications.model.Webhook @@ -53,6 +54,7 @@ internal object ConfigDataProperties { Pair(ConfigType.CHIME, ConfigProperty(Chime.reader, Chime.xParser)), Pair(ConfigType.WEBHOOK, ConfigProperty(Webhook.reader, Webhook.xParser)), Pair(ConfigType.EMAIL, ConfigProperty(Email.reader, Email.xParser)), + Pair(ConfigType.SNS, ConfigProperty(SNS.reader, SNS.xParser)), Pair(ConfigType.EMAIL_GROUP, ConfigProperty(EmailGroup.reader, EmailGroup.xParser)), Pair(ConfigType.SMTP_ACCOUNT, ConfigProperty(SmtpAccount.reader, SmtpAccount.xParser)) ) @@ -78,6 +80,7 @@ internal object ConfigDataProperties { ConfigType.EMAIL_GROUP -> configData is EmailGroup ConfigType.SMTP_ACCOUNT -> configData is SmtpAccount ConfigType.CHIME -> configData is Chime + ConfigType.SNS -> configData is SNS ConfigType.NONE -> true } } diff --git a/src/main/kotlin/org/opensearch/commons/utils/ValidationHelpers.kt b/src/main/kotlin/org/opensearch/commons/utils/ValidationHelpers.kt index 0124179f..fc117923 100644 --- a/src/main/kotlin/org/opensearch/commons/utils/ValidationHelpers.kt +++ b/src/main/kotlin/org/opensearch/commons/utils/ValidationHelpers.kt @@ -28,6 +28,7 @@ package org.opensearch.commons.utils import java.net.URL +import java.util.regex.Pattern // Valid ID characters = (All Base64 chars + "_-") to support UUID format and Base64 encoded IDs private val VALID_ID_CHARS: Set = (('a'..'z') + ('A'..'Z') + ('0'..'9') + '+' + '/' + '_' + '-').toSet() @@ -69,3 +70,8 @@ fun isValidEmail(email: String): Boolean { fun isValidId(idString: String): Boolean { return idString.isNotBlank() && idString.all { VALID_ID_CHARS.contains(it) } } + +fun validateIAMRoleArn(roleARN: String) { + val roleArnRegex = Pattern.compile("^arn:aws(-[^:]+)?:iam::([0-9]{12}):([a-zA-Z_0-9+=,.@\\-_/]+)$") + require(roleArnRegex.matcher(roleARN).find()) { "Invalid AWS role ARN: $roleARN " } +} diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/SNSTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/SNSTests.kt new file mode 100644 index 00000000..46d7cfc8 --- /dev/null +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/SNSTests.kt @@ -0,0 +1,105 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + * + * Modifications Copyright OpenSearch Contributors. See + * GitHub history for details. + */ + +package org.opensearch.commons.notifications.model + +import com.fasterxml.jackson.core.JsonParseException +import org.junit.jupiter.api.Assertions +import org.junit.jupiter.api.Assertions.assertThrows +import org.junit.jupiter.api.Test +import org.opensearch.commons.utils.createObjectFromJsonString +import org.opensearch.commons.utils.getJsonString +import org.opensearch.commons.utils.recreateObject + +internal class SNSTests { + + @Test + fun `SNS should throw exception if empty topic`() { + assertThrows(IllegalArgumentException::class.java) { + SNS("", null) + } + val jsonString = "{\"topic_arn\":\"\"}" + assertThrows(IllegalArgumentException::class.java) { + createObjectFromJsonString(jsonString) { SNS.parse(it) } + } + } + + @Test + fun `SNS should throw exception if invalid topic ARN`() { + assertThrows(IllegalArgumentException::class.java) { + SNS("arn:aws:es:us-east-1:012345678989:test", null) + } + val jsonString = "{\"topic_arn\":\"arn:aws:es:us-east-1:012345678989:test\"}" + assertThrows(IllegalArgumentException::class.java) { + createObjectFromJsonString(jsonString) { SNS.parse(it) } + } + } + + @Test + fun `SNS should throw exception if invalid role ARN`() { + assertThrows(IllegalArgumentException::class.java) { + SNS("arn:aws:sns:us-east-1:012345678912:topic-test", "arn:aws:iam:us-east-1:0123456789:role-test") + } + val jsonString = + "{\"topic_arn\":\"arn:aws:sns:us-east-1:012345678912:topic-test\",\"role_arn\":\"arn:aws:iam:us-east-1:0123456789:role-test\"}" + assertThrows(IllegalArgumentException::class.java) { + createObjectFromJsonString(jsonString) { SNS.parse(it) } + } + } + + @Test + fun `SNS serialize and deserialize transport object should be equal`() { + val sampleSNS = SNS("arn:aws:sns:us-east-1:012345678912:topic-test", "arn:aws:iam::012345678912:role/iam-test") + val recreatedObject = recreateObject(sampleSNS) { SNS(it) } + Assertions.assertEquals(sampleSNS, recreatedObject) + } + + @Test + fun `SNS serialize and deserialize using json object should be equal`() { + val sampleSNS = SNS("arn:aws:sns:us-east-1:012345678912:topic-test", "arn:aws:iam::012345678912:role/iam-test") + val jsonString = getJsonString(sampleSNS) + val recreatedObject = createObjectFromJsonString(jsonString) { SNS.parse(it) } + Assertions.assertEquals(sampleSNS, recreatedObject) + } + + @Test + fun `SNS should deserialize json object using parser`() { + val sampleSNS = SNS("arn:aws:sns:us-east-1:012345678912:topic-test", "arn:aws:iam::012345678912:role/iam-test") + val jsonString = "{\"topic_arn\":\"${sampleSNS.topicARN}\",\"role_arn\":\"${sampleSNS.roleARN}\"}" + val recreatedObject = createObjectFromJsonString(jsonString) { SNS.parse(it) } + Assertions.assertEquals(sampleSNS, recreatedObject) + } + + @Test + fun `SNS should throw exception when invalid json object is passed`() { + val jsonString = "sample message" + assertThrows(JsonParseException::class.java) { + createObjectFromJsonString(jsonString) { SNS.parse(it) } + } + } + + @Test + fun `SNS should throw exception when arn is replace with arn2 in json object`() { + val sampleSNS = SNS("arn:aws:sns:us-east-1:012345678912:topic-test", "arn:aws:iam::012345678912:role/iam-test") + val jsonString = "{\"topic_arn2\":\"${sampleSNS.topicARN}\",\"role_arn\":\"${sampleSNS.roleARN}\"}" + assertThrows(IllegalArgumentException::class.java) { + createObjectFromJsonString(jsonString) { SNS.parse(it) } + } + } + + @Test + fun `SNS should safely ignore extra field in json object`() { + val sampleSNS = SNS("arn:aws:sns:us-east-1:012345678912:topic-test", null) + val jsonString = "{\"topic_arn\":\"${sampleSNS.topicARN}\", \"another\":\"field\"}" + val recreatedObject = createObjectFromJsonString(jsonString) { SNS.parse(it) } + Assertions.assertEquals(sampleSNS, recreatedObject) + } +} From d79c53dbf4a49a83dc5e36e4d4653dd66c250118 Mon Sep 17 00:00:00 2001 From: Anantha Krishna Bhatta <31894175+akbhatta@users.noreply.github.com> Date: Thu, 12 Aug 2021 17:00:19 -0700 Subject: [PATCH 008/140] Added support for SesAccount (#54) Also updated Feature to be simple string for future plugin easy addition [Tests] Added unit tests for SesAccount Updated Unit tests for changes Signed-off-by: @akbhatta --- .../notifications/NotificationConstants.kt | 9 +- .../action/GetFeatureChannelListRequest.kt | 13 +- .../commons/notifications/model/ConfigType.kt | 5 + .../notifications/model/EventSource.kt | 12 +- .../commons/notifications/model/Feature.kt | 71 -------- .../notifications/model/NotificationConfig.kt | 15 +- .../commons/notifications/model/SesAccount.kt | 124 ++++++++++++++ .../notifications/model/{SNS.kt => Sns.kt} | 55 +++---- .../model/config/ConfigDataProperties.kt | 9 +- .../commons/utils/ValidationHelpers.kt | 4 +- .../NotificationsPluginInterfaceTests.kt | 10 +- .../CreateNotificationConfigRequestTests.kt | 29 ++-- .../GetFeatureChannelListRequestTests.kt | 10 +- .../GetNotificationConfigResponseTests.kt | 20 +-- .../GetNotificationEventResponseTests.kt | 19 +-- .../action/SendNotificationRequestTests.kt | 12 +- .../UpdateNotificationConfigRequestTests.kt | 29 ++-- .../notifications/model/EventSourceTests.kt | 13 +- .../notifications/model/FeatureTests.kt | 56 ------- .../model/NotificationConfigInfoTests.kt | 13 +- .../NotificationConfigSearchResultsTests.kt | 23 +-- .../model/NotificationConfigTests.kt | 34 ++-- .../model/NotificationEventInfoTests.kt | 11 +- .../NotificationEventSearchResultTests.kt | 22 +-- .../model/NotificationEventTests.kt | 8 +- .../notifications/model/SesAccountTests.kt | 151 ++++++++++++++++++ .../model/{SNSTests.kt => SnsTests.kt} | 52 +++--- 27 files changed, 496 insertions(+), 333 deletions(-) delete mode 100644 src/main/kotlin/org/opensearch/commons/notifications/model/Feature.kt create mode 100644 src/main/kotlin/org/opensearch/commons/notifications/model/SesAccount.kt rename src/main/kotlin/org/opensearch/commons/notifications/model/{SNS.kt => Sns.kt} (63%) delete mode 100644 src/test/kotlin/org/opensearch/commons/notifications/model/FeatureTests.kt create mode 100644 src/test/kotlin/org/opensearch/commons/notifications/model/SesAccountTests.kt rename src/test/kotlin/org/opensearch/commons/notifications/model/{SNSTests.kt => SnsTests.kt} (65%) diff --git a/src/main/kotlin/org/opensearch/commons/notifications/NotificationConstants.kt b/src/main/kotlin/org/opensearch/commons/notifications/NotificationConstants.kt index 04f3affe..55dc9a44 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/NotificationConstants.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/NotificationConstants.kt @@ -42,8 +42,9 @@ object NotificationConstants { const val TAGS_TAG = "tags" const val URL_TAG = "url" const val HEADER_PARAMS_TAG = "header_params" - const val TOPIC_ARN_FIELD = "topic_arn" - const val ROLE_ARN_FIELD = "role_arn" + const val TOPIC_ARN_TAG = "topic_arn" + const val ROLE_ARN_TAG = "role_arn" + const val REGION_TAG = "region" const val HOST_TAG = "host" const val PORT_TAG = "port" const val METHOD_TAG = "method" @@ -69,5 +70,9 @@ object NotificationConstants { const val CONFIG_TYPE_LIST_TAG = "config_type_list" const val PLUGIN_FEATURES_TAG = "plugin_features" + const val FEATURE_ALERTING = "alerting" + const val FEATURE_INDEX_MANAGEMENT = "index_management" + const val FEATURE_REPORTS = "reports" + const val DEFAULT_MAX_ITEMS = 1000 } diff --git a/src/main/kotlin/org/opensearch/commons/notifications/action/GetFeatureChannelListRequest.kt b/src/main/kotlin/org/opensearch/commons/notifications/action/GetFeatureChannelListRequest.kt index 17e4f6fb..309a31bc 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/action/GetFeatureChannelListRequest.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/action/GetFeatureChannelListRequest.kt @@ -37,7 +37,6 @@ import org.opensearch.common.xcontent.XContentBuilder import org.opensearch.common.xcontent.XContentParser import org.opensearch.common.xcontent.XContentParserUtils import org.opensearch.commons.notifications.NotificationConstants.FEATURE_TAG -import org.opensearch.commons.notifications.model.Feature import org.opensearch.commons.utils.logger import java.io.IOException @@ -48,7 +47,7 @@ import java.io.IOException * Hence the request also contains tenant info for space isolation. */ class GetFeatureChannelListRequest : ActionRequest, ToXContentObject { - val feature: Feature + val feature: String companion object { private val log by logger(GetFeatureChannelListRequest::class.java) @@ -65,7 +64,7 @@ class GetFeatureChannelListRequest : ActionRequest, ToXContentObject { @JvmStatic @Throws(IOException::class) fun parse(parser: XContentParser): GetFeatureChannelListRequest { - var feature: Feature? = null + var feature: String? = null XContentParserUtils.ensureExpectedToken( XContentParser.Token.START_OBJECT, @@ -76,7 +75,7 @@ class GetFeatureChannelListRequest : ActionRequest, ToXContentObject { val fieldName = parser.currentName() parser.nextToken() when (fieldName) { - FEATURE_TAG -> feature = Feature.fromTagOrDefault(parser.text()) + FEATURE_TAG -> feature = parser.text() else -> { parser.skipChildren() log.info("Unexpected field: $fieldName, while parsing GetFeatureChannelListRequest") @@ -92,7 +91,7 @@ class GetFeatureChannelListRequest : ActionRequest, ToXContentObject { * constructor for creating the class * @param feature the caller plugin feature */ - constructor(feature: Feature) { + constructor(feature: String) { this.feature = feature } @@ -101,7 +100,7 @@ class GetFeatureChannelListRequest : ActionRequest, ToXContentObject { */ @Throws(IOException::class) constructor(input: StreamInput) : super(input) { - feature = input.readEnum(Feature::class.java) + feature = input.readString() } /** @@ -110,7 +109,7 @@ class GetFeatureChannelListRequest : ActionRequest, ToXContentObject { @Throws(IOException::class) override fun writeTo(output: StreamOutput) { super.writeTo(output) - output.writeEnum(feature) + output.writeString(feature) } /** diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/ConfigType.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/ConfigType.kt index d5400a75..85c10e35 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/ConfigType.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/ConfigType.kt @@ -62,6 +62,11 @@ enum class ConfigType(val tag: String) { return tag } }, + SES_ACCOUNT("ses_account") { + override fun toString(): String { + return tag + } + }, SMTP_ACCOUNT("smtp_account") { override fun toString(): String { return tag diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/EventSource.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/EventSource.kt index caf86dcd..98c46d2a 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/EventSource.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/EventSource.kt @@ -49,7 +49,7 @@ import java.io.IOException data class EventSource( val title: String, val referenceId: String, - val feature: Feature, + val feature: String, val severity: SeverityType = SeverityType.INFO, val tags: List = listOf() ) : BaseModel { @@ -75,7 +75,7 @@ data class EventSource( fun parse(parser: XContentParser): EventSource { var title: String? = null var referenceId: String? = null - var feature: Feature? = null + var feature: String? = null var severity: SeverityType = SeverityType.INFO var tags: List = emptyList() @@ -90,7 +90,7 @@ data class EventSource( when (fieldName) { TITLE_TAG -> title = parser.text() REFERENCE_ID_TAG -> referenceId = parser.text() - FEATURE_TAG -> feature = Feature.fromTagOrDefault(parser.text()) + FEATURE_TAG -> feature = parser.text() SEVERITY_TAG -> severity = SeverityType.fromTagOrDefault(parser.text()) TAGS_TAG -> tags = parser.stringList() else -> { @@ -121,7 +121,7 @@ data class EventSource( return builder.startObject() .field(TITLE_TAG, title) .field(REFERENCE_ID_TAG, referenceId) - .field(FEATURE_TAG, feature.tag) + .field(FEATURE_TAG, feature) .field(SEVERITY_TAG, severity.tag) .field(TAGS_TAG, tags) .endObject() @@ -134,7 +134,7 @@ data class EventSource( constructor(input: StreamInput) : this( title = input.readString(), referenceId = input.readString(), - feature = input.readEnum(Feature::class.java), + feature = input.readString(), severity = input.readEnum(SeverityType::class.java), tags = input.readStringList() ) @@ -145,7 +145,7 @@ data class EventSource( override fun writeTo(output: StreamOutput) { output.writeString(title) output.writeString(referenceId) - output.writeEnum(feature) + output.writeString(feature) output.writeEnum(severity) output.writeStringCollection(tags) } diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/Feature.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/Feature.kt deleted file mode 100644 index 84b37139..00000000 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/Feature.kt +++ /dev/null @@ -1,71 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * - */ - -package org.opensearch.commons.notifications.model - -import org.opensearch.commons.utils.EnumParser - -/** - * Features using notification plugin - */ -enum class Feature(val tag: String) { - NONE("none") { - override fun toString(): String { - return tag - } - }, - ALERTING("alerting") { - override fun toString(): String { - return tag - } - }, - INDEX_MANAGEMENT("index_management") { - override fun toString(): String { - return tag - } - }, - REPORTS("reports") { - override fun toString(): String { - return tag - } - }; - - companion object { - private val tagMap = values().associateBy { it.tag } - - val enumParser = EnumParser { fromTagOrDefault(it) } - - /** - * Get Feature from tag or NONE if not found - * @param tag the tag - * @return Feature corresponding to tag. NONE if invalid tag. - */ - fun fromTagOrDefault(tag: String): Feature { - return tagMap[tag] ?: NONE - } - } -} diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationConfig.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationConfig.kt index 30d72147..a0f7f5ad 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationConfig.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationConfig.kt @@ -42,11 +42,12 @@ import org.opensearch.commons.notifications.NotificationConstants.NAME_TAG import org.opensearch.commons.notifications.model.config.ConfigDataProperties.createConfigData import org.opensearch.commons.notifications.model.config.ConfigDataProperties.getReaderForConfigType import org.opensearch.commons.notifications.model.config.ConfigDataProperties.validateConfigData -import org.opensearch.commons.utils.enumSet +import org.opensearch.commons.utils.STRING_READER +import org.opensearch.commons.utils.STRING_WRITER import org.opensearch.commons.utils.fieldIfNotNull import org.opensearch.commons.utils.logger +import org.opensearch.commons.utils.stringList import java.io.IOException -import java.util.EnumSet /** * Data class representing Notification config. @@ -55,7 +56,7 @@ data class NotificationConfig( val name: String, val description: String, val configType: ConfigType, - val features: EnumSet, + val features: Set, val configData: BaseConfigData?, val isEnabled: Boolean = true ) : BaseModel { @@ -89,7 +90,7 @@ data class NotificationConfig( var name: String? = null var description = "" var configType: ConfigType? = null - var features: EnumSet? = null + var features: Set? = null var isEnabled = true var configData: BaseConfigData? = null XContentParserUtils.ensureExpectedToken( @@ -104,7 +105,7 @@ data class NotificationConfig( NAME_TAG -> name = parser.text() DESCRIPTION_TAG -> description = parser.text() CONFIG_TYPE_TAG -> configType = ConfigType.fromTagOrDefault(parser.text()) - FEATURE_LIST_TAG -> features = parser.enumSet(Feature.enumParser) + FEATURE_LIST_TAG -> features = parser.stringList().toSet() IS_ENABLED_TAG -> isEnabled = parser.booleanValue() else -> { val configTypeForTag = ConfigType.fromTagOrDefault(fieldName) @@ -154,7 +155,7 @@ data class NotificationConfig( name = input.readString(), description = input.readString(), configType = input.readEnum(ConfigType::class.java), - features = input.readEnumSet(Feature::class.java), + features = input.readSet(STRING_READER), isEnabled = input.readBoolean(), configData = input.readOptionalWriteable(getReaderForConfigType(input.readEnum(ConfigType::class.java))) ) @@ -166,7 +167,7 @@ data class NotificationConfig( output.writeString(name) output.writeString(description) output.writeEnum(configType) - output.writeEnumSet(features) + output.writeCollection(features, STRING_WRITER) output.writeBoolean(isEnabled) // Reading config types multiple times in constructor output.writeEnum(configType) diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/SesAccount.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/SesAccount.kt new file mode 100644 index 00000000..d529b407 --- /dev/null +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/SesAccount.kt @@ -0,0 +1,124 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + * + * Modifications Copyright OpenSearch Contributors. See + * GitHub history for details. + */ + +package org.opensearch.commons.notifications.model + +import org.opensearch.common.Strings +import org.opensearch.common.io.stream.StreamInput +import org.opensearch.common.io.stream.StreamOutput +import org.opensearch.common.io.stream.Writeable +import org.opensearch.common.xcontent.ToXContent +import org.opensearch.common.xcontent.XContentBuilder +import org.opensearch.common.xcontent.XContentParser +import org.opensearch.common.xcontent.XContentParserUtils +import org.opensearch.commons.notifications.NotificationConstants.FROM_ADDRESS_TAG +import org.opensearch.commons.notifications.NotificationConstants.REGION_TAG +import org.opensearch.commons.notifications.NotificationConstants.ROLE_ARN_TAG +import org.opensearch.commons.utils.logger +import org.opensearch.commons.utils.validateEmail +import org.opensearch.commons.utils.validateIamRoleArn +import java.io.IOException + +/** + * Data class representing SES account channel. + */ +data class SesAccount( + val awsRegion: String, + val roleArn: String?, + val fromAddress: String +) : BaseConfigData { + + init { + require(!Strings.isNullOrEmpty(awsRegion)) { "awsRegion is null or empty" } + validateEmail(fromAddress) + if (roleArn != null) { + validateIamRoleArn(roleArn) + } + } + + companion object { + private val log by logger(SesAccount::class.java) + + /** + * reader to create instance of class from writable. + */ + val reader = Writeable.Reader { SesAccount(it) } + + /** + * Parser to parse xContent + */ + val xParser = XParser { parse(it) } + + @JvmStatic + @Throws(IOException::class) + fun parse(parser: XContentParser): SesAccount { + var awsRegion: String? = null + var roleArn: String? = null + var fromAddress: String? = null + + XContentParserUtils.ensureExpectedToken( + XContentParser.Token.START_OBJECT, + parser.currentToken(), + parser + ) + while (parser.nextToken() != XContentParser.Token.END_OBJECT) { + val fieldName = parser.currentName() + parser.nextToken() + when (fieldName) { + REGION_TAG -> awsRegion = parser.text() + ROLE_ARN_TAG -> roleArn = parser.text() + FROM_ADDRESS_TAG -> fromAddress = parser.text() + else -> { + parser.skipChildren() + log.info("Unexpected field: $fieldName, while parsing SesAccount") + } + } + } + awsRegion ?: throw IllegalArgumentException("$REGION_TAG field absent") + fromAddress ?: throw IllegalArgumentException("$FROM_ADDRESS_TAG field absent") + return SesAccount( + awsRegion, + roleArn, + fromAddress + ) + } + } + + /** + * {@inheritDoc} + */ + override fun toXContent(builder: XContentBuilder?, params: ToXContent.Params?): XContentBuilder { + return builder!!.startObject() + .field(REGION_TAG, awsRegion) + .field(ROLE_ARN_TAG, roleArn) + .field(FROM_ADDRESS_TAG, fromAddress) + .endObject() + } + + /** + * Constructor used in transport action communication. + * @param input StreamInput stream to deserialize data from. + */ + constructor(input: StreamInput) : this( + awsRegion = input.readString(), + roleArn = input.readOptionalString(), + fromAddress = input.readString() + ) + + /** + * {@inheritDoc} + */ + override fun writeTo(out: StreamOutput) { + out.writeString(awsRegion) + out.writeOptionalString(roleArn) + out.writeString(fromAddress) + } +} diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/SNS.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/Sns.kt similarity index 63% rename from src/main/kotlin/org/opensearch/commons/notifications/model/SNS.kt rename to src/main/kotlin/org/opensearch/commons/notifications/model/Sns.kt index 12cdba4f..5e723926 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/SNS.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/Sns.kt @@ -17,30 +17,30 @@ import org.opensearch.common.xcontent.ToXContent import org.opensearch.common.xcontent.XContentBuilder import org.opensearch.common.xcontent.XContentParser import org.opensearch.common.xcontent.XContentParserUtils -import org.opensearch.commons.notifications.NotificationConstants.ROLE_ARN_FIELD -import org.opensearch.commons.notifications.NotificationConstants.TOPIC_ARN_FIELD +import org.opensearch.commons.notifications.NotificationConstants.ROLE_ARN_TAG +import org.opensearch.commons.notifications.NotificationConstants.TOPIC_ARN_TAG import org.opensearch.commons.utils.fieldIfNotNull import org.opensearch.commons.utils.logger -import org.opensearch.commons.utils.validateIAMRoleArn +import org.opensearch.commons.utils.validateIamRoleArn import java.io.IOException import java.util.regex.Pattern /** * SNS notification data model */ -data class SNS(val topicARN: String, val roleARN: String?) : BaseConfigData { +data class Sns(val topicArn: String, val roleArn: String?) : BaseConfigData { init { - require(SNS_ARN_REGEX.matcher(topicARN).find()) { "Invalid AWS SNS topic ARN: $topicARN" } - if (roleARN != null) { - validateIAMRoleArn(roleARN) + require(SNS_ARN_REGEX.matcher(topicArn).find()) { "Invalid AWS SNS topic ARN: $topicArn" } + if (roleArn != null) { + validateIamRoleArn(roleArn) } } override fun toXContent(builder: XContentBuilder, params: ToXContent.Params): XContentBuilder { return builder.startObject() - .field(TOPIC_ARN_FIELD, topicARN) - .fieldIfNotNull(ROLE_ARN_FIELD, roleARN) + .field(TOPIC_ARN_TAG, topicArn) + .fieldIfNotNull(ROLE_ARN_TAG, roleArn) .endObject() } @@ -49,18 +49,18 @@ data class SNS(val topicARN: String, val roleARN: String?) : BaseConfigData { * @param input StreamInput stream to deserialize data from. */ constructor(input: StreamInput) : this( - topicARN = input.readString(), - roleARN = input.readOptionalString() + topicArn = input.readString(), + roleArn = input.readOptionalString() ) @Throws(IOException::class) override fun writeTo(out: StreamOutput) { - out.writeString(topicARN) - out.writeOptionalString(roleARN) + out.writeString(topicArn) + out.writeOptionalString(roleArn) } companion object { - private val log by logger(SNS::class.java) + private val log by logger(Sns::class.java) private val SNS_ARN_REGEX = Pattern.compile("^arn:aws(-[^:]+)?:sns:([a-zA-Z0-9-]+):([0-9]{12}):([a-zA-Z0-9-_]+)$") @@ -68,7 +68,7 @@ data class SNS(val topicARN: String, val roleARN: String?) : BaseConfigData { /** * reader to create instance of class from writable. */ - val reader = Writeable.Reader { SNS(it) } + val reader = Writeable.Reader { Sns(it) } /** * Parser to parse xContent @@ -77,36 +77,25 @@ data class SNS(val topicARN: String, val roleARN: String?) : BaseConfigData { @JvmStatic @Throws(IOException::class) - fun parse(xcp: XContentParser): SNS { - var topicARN: String? = null - var roleARN: String? = null + fun parse(xcp: XContentParser): Sns { + var topicArn: String? = null + var roleArn: String? = null XContentParserUtils.ensureExpectedToken(XContentParser.Token.START_OBJECT, xcp.currentToken(), xcp) while (xcp.nextToken() != XContentParser.Token.END_OBJECT) { val fieldName = xcp.currentName() xcp.nextToken() when (fieldName) { - TOPIC_ARN_FIELD -> topicARN = xcp.textOrNull() - ROLE_ARN_FIELD -> roleARN = xcp.textOrNull() + TOPIC_ARN_TAG -> topicArn = xcp.textOrNull() + ROLE_ARN_TAG -> roleArn = xcp.textOrNull() else -> { xcp.skipChildren() log.info("Unexpected field: $fieldName, while parsing SNS destination") } } } - topicARN ?: throw IllegalArgumentException("$TOPIC_ARN_FIELD field absent") - return SNS(topicARN, roleARN) - } - - @JvmStatic - @Throws(IOException::class) - fun readFrom(sin: StreamInput): SNS? { - return if (sin.readBoolean()) { - SNS( - topicARN = sin.readString(), - roleARN = sin.readOptionalString() - ) - } else null + topicArn ?: throw IllegalArgumentException("$TOPIC_ARN_TAG field absent") + return Sns(topicArn, roleArn) } } } diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/config/ConfigDataProperties.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/config/ConfigDataProperties.kt index 34bd2edc..e6844934 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/config/ConfigDataProperties.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/config/ConfigDataProperties.kt @@ -33,9 +33,10 @@ import org.opensearch.commons.notifications.model.Chime import org.opensearch.commons.notifications.model.ConfigType import org.opensearch.commons.notifications.model.Email import org.opensearch.commons.notifications.model.EmailGroup -import org.opensearch.commons.notifications.model.SNS +import org.opensearch.commons.notifications.model.SesAccount import org.opensearch.commons.notifications.model.Slack import org.opensearch.commons.notifications.model.SmtpAccount +import org.opensearch.commons.notifications.model.Sns import org.opensearch.commons.notifications.model.Webhook import org.opensearch.commons.notifications.model.XParser @@ -54,7 +55,8 @@ internal object ConfigDataProperties { Pair(ConfigType.CHIME, ConfigProperty(Chime.reader, Chime.xParser)), Pair(ConfigType.WEBHOOK, ConfigProperty(Webhook.reader, Webhook.xParser)), Pair(ConfigType.EMAIL, ConfigProperty(Email.reader, Email.xParser)), - Pair(ConfigType.SNS, ConfigProperty(SNS.reader, SNS.xParser)), + Pair(ConfigType.SNS, ConfigProperty(Sns.reader, Sns.xParser)), + Pair(ConfigType.SES_ACCOUNT, ConfigProperty(SesAccount.reader, SesAccount.xParser)), Pair(ConfigType.EMAIL_GROUP, ConfigProperty(EmailGroup.reader, EmailGroup.xParser)), Pair(ConfigType.SMTP_ACCOUNT, ConfigProperty(SmtpAccount.reader, SmtpAccount.xParser)) ) @@ -80,7 +82,8 @@ internal object ConfigDataProperties { ConfigType.EMAIL_GROUP -> configData is EmailGroup ConfigType.SMTP_ACCOUNT -> configData is SmtpAccount ConfigType.CHIME -> configData is Chime - ConfigType.SNS -> configData is SNS + ConfigType.SNS -> configData is Sns + ConfigType.SES_ACCOUNT -> configData is SesAccount ConfigType.NONE -> true } } diff --git a/src/main/kotlin/org/opensearch/commons/utils/ValidationHelpers.kt b/src/main/kotlin/org/opensearch/commons/utils/ValidationHelpers.kt index fc117923..9f9082c4 100644 --- a/src/main/kotlin/org/opensearch/commons/utils/ValidationHelpers.kt +++ b/src/main/kotlin/org/opensearch/commons/utils/ValidationHelpers.kt @@ -71,7 +71,7 @@ fun isValidId(idString: String): Boolean { return idString.isNotBlank() && idString.all { VALID_ID_CHARS.contains(it) } } -fun validateIAMRoleArn(roleARN: String) { +fun validateIamRoleArn(roleArn: String) { val roleArnRegex = Pattern.compile("^arn:aws(-[^:]+)?:iam::([0-9]{12}):([a-zA-Z_0-9+=,.@\\-_/]+)$") - require(roleArnRegex.matcher(roleARN).find()) { "Invalid AWS role ARN: $roleARN " } + require(roleArnRegex.matcher(roleArn).find()) { "Invalid AWS role ARN: $roleArn " } } diff --git a/src/test/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterfaceTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterfaceTests.kt index 99f558f4..cf4f8420 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterfaceTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterfaceTests.kt @@ -25,6 +25,8 @@ import org.mockito.junit.jupiter.MockitoExtension import org.opensearch.action.ActionListener import org.opensearch.action.ActionType import org.opensearch.client.node.NodeClient +import org.opensearch.commons.notifications.NotificationConstants.FEATURE_ALERTING +import org.opensearch.commons.notifications.NotificationConstants.FEATURE_REPORTS import org.opensearch.commons.notifications.action.CreateNotificationConfigRequest import org.opensearch.commons.notifications.action.CreateNotificationConfigResponse import org.opensearch.commons.notifications.action.DeleteNotificationConfigRequest @@ -45,7 +47,6 @@ import org.opensearch.commons.notifications.model.ConfigType import org.opensearch.commons.notifications.model.DeliveryStatus import org.opensearch.commons.notifications.model.EventSource import org.opensearch.commons.notifications.model.EventStatus -import org.opensearch.commons.notifications.model.Feature import org.opensearch.commons.notifications.model.FeatureChannel import org.opensearch.commons.notifications.model.FeatureChannelList import org.opensearch.commons.notifications.model.NotificationConfig @@ -58,7 +59,6 @@ import org.opensearch.commons.notifications.model.SeverityType import org.opensearch.commons.notifications.model.Slack import org.opensearch.rest.RestStatus import java.time.Instant -import java.util.EnumSet @Suppress("UNCHECKED_CAST") @ExtendWith(MockitoExtension::class) @@ -198,7 +198,7 @@ internal class NotificationsPluginInterfaceTests { val notificationInfo = EventSource( "title", "reference_id", - Feature.REPORTS, + FEATURE_REPORTS, SeverityType.HIGH, listOf("tag1", "tag2") ) @@ -229,7 +229,7 @@ internal class NotificationsPluginInterfaceTests { "name", "description", ConfigType.SLACK, - EnumSet.of(Feature.REPORTS), + setOf(FEATURE_REPORTS), configData = sampleSlack ) val configInfo = NotificationConfigInfo( @@ -246,7 +246,7 @@ internal class NotificationsPluginInterfaceTests { val sampleEventSource = EventSource( "title", "reference_id", - Feature.ALERTING, + FEATURE_ALERTING, severity = SeverityType.INFO ) val sampleStatus = EventStatus( diff --git a/src/test/kotlin/org/opensearch/commons/notifications/action/CreateNotificationConfigRequestTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/action/CreateNotificationConfigRequestTests.kt index 679ded46..f190e7f6 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/action/CreateNotificationConfigRequestTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/action/CreateNotificationConfigRequestTests.kt @@ -31,11 +31,11 @@ import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Assertions.assertNull import org.junit.jupiter.api.Test import org.junit.jupiter.api.assertThrows +import org.opensearch.commons.notifications.NotificationConstants.FEATURE_INDEX_MANAGEMENT import org.opensearch.commons.notifications.model.Chime import org.opensearch.commons.notifications.model.ConfigType import org.opensearch.commons.notifications.model.Email import org.opensearch.commons.notifications.model.EmailGroup -import org.opensearch.commons.notifications.model.Feature import org.opensearch.commons.notifications.model.MethodType import org.opensearch.commons.notifications.model.NotificationConfig import org.opensearch.commons.notifications.model.Slack @@ -44,7 +44,6 @@ import org.opensearch.commons.notifications.model.Webhook import org.opensearch.commons.utils.createObjectFromJsonString import org.opensearch.commons.utils.getJsonString import org.opensearch.commons.utils.recreateObject -import java.util.EnumSet internal class CreateNotificationConfigRequestTests { @@ -54,7 +53,7 @@ internal class CreateNotificationConfigRequestTests { "name", "description", ConfigType.WEBHOOK, - EnumSet.of(Feature.INDEX_MANAGEMENT), + setOf(FEATURE_INDEX_MANAGEMENT), isEnabled = true, configData = sampleWebhook ) @@ -66,7 +65,7 @@ internal class CreateNotificationConfigRequestTests { "name", "description", ConfigType.SLACK, - EnumSet.of(Feature.INDEX_MANAGEMENT), + setOf(FEATURE_INDEX_MANAGEMENT), isEnabled = true, configData = sampleSlack ) @@ -78,7 +77,7 @@ internal class CreateNotificationConfigRequestTests { "name", "description", ConfigType.CHIME, - EnumSet.of(Feature.INDEX_MANAGEMENT), + setOf(FEATURE_INDEX_MANAGEMENT), isEnabled = true, configData = sampleChime ) @@ -90,7 +89,7 @@ internal class CreateNotificationConfigRequestTests { "name", "description", ConfigType.EMAIL_GROUP, - EnumSet.of(Feature.INDEX_MANAGEMENT), + setOf(FEATURE_INDEX_MANAGEMENT), isEnabled = true, configData = sampleEmailGroup ) @@ -106,7 +105,7 @@ internal class CreateNotificationConfigRequestTests { "name", "description", ConfigType.EMAIL, - EnumSet.of(Feature.INDEX_MANAGEMENT), + setOf(FEATURE_INDEX_MANAGEMENT), isEnabled = true, configData = sampleEmail ) @@ -123,7 +122,7 @@ internal class CreateNotificationConfigRequestTests { "name", "description", ConfigType.SMTP_ACCOUNT, - EnumSet.of(Feature.INDEX_MANAGEMENT), + setOf(FEATURE_INDEX_MANAGEMENT), isEnabled = true, configData = sampleSmtpAccount ) @@ -286,7 +285,7 @@ internal class CreateNotificationConfigRequestTests { "name", "description", ConfigType.SLACK, - EnumSet.of(Feature.INDEX_MANAGEMENT), + setOf(FEATURE_INDEX_MANAGEMENT), isEnabled = true, configData = sampleSlack ) @@ -314,7 +313,7 @@ internal class CreateNotificationConfigRequestTests { "name", "description", ConfigType.WEBHOOK, - EnumSet.of(Feature.INDEX_MANAGEMENT), + setOf(FEATURE_INDEX_MANAGEMENT), isEnabled = true, configData = sampleWebhook ) @@ -342,7 +341,7 @@ internal class CreateNotificationConfigRequestTests { "name", "description", ConfigType.CHIME, - EnumSet.of(Feature.INDEX_MANAGEMENT), + setOf(FEATURE_INDEX_MANAGEMENT), isEnabled = true, configData = sampleChime ) @@ -371,7 +370,7 @@ internal class CreateNotificationConfigRequestTests { "name", "description", ConfigType.EMAIL_GROUP, - EnumSet.of(Feature.INDEX_MANAGEMENT), + setOf(FEATURE_INDEX_MANAGEMENT), isEnabled = true, configData = sampleEmailGroup ) @@ -404,7 +403,7 @@ internal class CreateNotificationConfigRequestTests { "name", "description", ConfigType.EMAIL, - EnumSet.of(Feature.INDEX_MANAGEMENT), + setOf(FEATURE_INDEX_MANAGEMENT), isEnabled = true, configData = sampleEmail ) @@ -439,7 +438,7 @@ internal class CreateNotificationConfigRequestTests { "name", "description", ConfigType.SMTP_ACCOUNT, - EnumSet.of(Feature.INDEX_MANAGEMENT), + setOf(FEATURE_INDEX_MANAGEMENT), isEnabled = true, configData = sampleSmtpAccount ) @@ -507,7 +506,7 @@ internal class CreateNotificationConfigRequestTests { "name", "description", ConfigType.SLACK, - EnumSet.of(Feature.INDEX_MANAGEMENT), + setOf(FEATURE_INDEX_MANAGEMENT), isEnabled = true, configData = sampleSlack ) diff --git a/src/test/kotlin/org/opensearch/commons/notifications/action/GetFeatureChannelListRequestTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/action/GetFeatureChannelListRequestTests.kt index c9788a80..8c5c770f 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/action/GetFeatureChannelListRequestTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/action/GetFeatureChannelListRequestTests.kt @@ -30,7 +30,9 @@ import com.fasterxml.jackson.core.JsonParseException import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Test import org.junit.jupiter.api.assertThrows -import org.opensearch.commons.notifications.model.Feature +import org.opensearch.commons.notifications.NotificationConstants.FEATURE_ALERTING +import org.opensearch.commons.notifications.NotificationConstants.FEATURE_INDEX_MANAGEMENT +import org.opensearch.commons.notifications.NotificationConstants.FEATURE_REPORTS import org.opensearch.commons.utils.createObjectFromJsonString import org.opensearch.commons.utils.getJsonString import org.opensearch.commons.utils.recreateObject @@ -46,14 +48,14 @@ internal class GetFeatureChannelListRequestTests { @Test fun `Get request serialize and deserialize transport object should be equal`() { - val configRequest = GetFeatureChannelListRequest(Feature.REPORTS) + val configRequest = GetFeatureChannelListRequest(FEATURE_REPORTS) val recreatedObject = recreateObject(configRequest) { GetFeatureChannelListRequest(it) } assertGetRequestEquals(configRequest, recreatedObject) } @Test fun `Get request serialize and deserialize using json object should be equal`() { - val configRequest = GetFeatureChannelListRequest(Feature.INDEX_MANAGEMENT) + val configRequest = GetFeatureChannelListRequest(FEATURE_INDEX_MANAGEMENT) val jsonString = getJsonString(configRequest) val recreatedObject = createObjectFromJsonString(jsonString) { GetFeatureChannelListRequest.parse(it) } assertGetRequestEquals(configRequest, recreatedObject) @@ -69,7 +71,7 @@ internal class GetFeatureChannelListRequestTests { @Test fun `Get request should safely ignore extra field in json object`() { - val configRequest = GetFeatureChannelListRequest(Feature.ALERTING) + val configRequest = GetFeatureChannelListRequest(FEATURE_ALERTING) val jsonString = """ { "feature":"${configRequest.feature}", diff --git a/src/test/kotlin/org/opensearch/commons/notifications/action/GetNotificationConfigResponseTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/action/GetNotificationConfigResponseTests.kt index a2e14b40..2ec08913 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/action/GetNotificationConfigResponseTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/action/GetNotificationConfigResponseTests.kt @@ -30,9 +30,10 @@ import org.apache.lucene.search.TotalHits import org.junit.jupiter.api.Assertions import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Test +import org.opensearch.commons.notifications.NotificationConstants.FEATURE_INDEX_MANAGEMENT +import org.opensearch.commons.notifications.NotificationConstants.FEATURE_REPORTS import org.opensearch.commons.notifications.model.Chime import org.opensearch.commons.notifications.model.ConfigType -import org.opensearch.commons.notifications.model.Feature import org.opensearch.commons.notifications.model.NotificationConfig import org.opensearch.commons.notifications.model.NotificationConfigInfo import org.opensearch.commons.notifications.model.NotificationConfigSearchResult @@ -41,7 +42,6 @@ import org.opensearch.commons.utils.createObjectFromJsonString import org.opensearch.commons.utils.getJsonString import org.opensearch.commons.utils.recreateObject import java.time.Instant -import java.util.EnumSet internal class GetNotificationConfigResponseTests { @@ -63,7 +63,7 @@ internal class GetNotificationConfigResponseTests { "name", "description", ConfigType.SLACK, - EnumSet.of(Feature.REPORTS), + setOf(FEATURE_REPORTS), configData = sampleSlack ) val configInfo = NotificationConfigInfo( @@ -85,7 +85,7 @@ internal class GetNotificationConfigResponseTests { "name", "description", ConfigType.SLACK, - EnumSet.of(Feature.REPORTS), + setOf(FEATURE_REPORTS), configData = Slack("https://domain.com/sample_url#1234567890") ) val configInfo1 = NotificationConfigInfo( @@ -99,7 +99,7 @@ internal class GetNotificationConfigResponseTests { "name", "description", ConfigType.CHIME, - EnumSet.of(Feature.INDEX_MANAGEMENT), + setOf(FEATURE_INDEX_MANAGEMENT), configData = Chime("https://domain.com/sample_url#1234567890") ) val configInfo2 = NotificationConfigInfo( @@ -129,7 +129,7 @@ internal class GetNotificationConfigResponseTests { "name", "description", ConfigType.SLACK, - EnumSet.of(Feature.REPORTS), + setOf(FEATURE_REPORTS), configData = sampleSlack ) val configInfo = NotificationConfigInfo( @@ -154,7 +154,7 @@ internal class GetNotificationConfigResponseTests { "name", "description", ConfigType.SLACK, - EnumSet.of(Feature.REPORTS), + setOf(FEATURE_REPORTS), configData = Slack("https://domain.com/sample_url#1234567890") ) val configInfo1 = NotificationConfigInfo( @@ -168,7 +168,7 @@ internal class GetNotificationConfigResponseTests { "name", "description", ConfigType.CHIME, - EnumSet.of(Feature.INDEX_MANAGEMENT), + setOf(FEATURE_INDEX_MANAGEMENT), configData = Chime("https://domain.com/sample_url#1234567890") ) val configInfo2 = NotificationConfigInfo( @@ -199,7 +199,7 @@ internal class GetNotificationConfigResponseTests { "name", "description", ConfigType.SLACK, - EnumSet.of(Feature.INDEX_MANAGEMENT), + setOf(FEATURE_INDEX_MANAGEMENT), isEnabled = true, configData = sampleSlack ) @@ -250,7 +250,7 @@ internal class GetNotificationConfigResponseTests { "name", "description", ConfigType.SLACK, - EnumSet.of(Feature.INDEX_MANAGEMENT), + setOf(FEATURE_INDEX_MANAGEMENT), isEnabled = true, configData = sampleSlack ) diff --git a/src/test/kotlin/org/opensearch/commons/notifications/action/GetNotificationEventResponseTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/action/GetNotificationEventResponseTests.kt index 4f7d72d1..1895d1d3 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/action/GetNotificationEventResponseTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/action/GetNotificationEventResponseTests.kt @@ -30,11 +30,12 @@ import org.apache.lucene.search.TotalHits import org.junit.jupiter.api.Assertions import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Test +import org.opensearch.commons.notifications.NotificationConstants.FEATURE_ALERTING +import org.opensearch.commons.notifications.NotificationConstants.FEATURE_REPORTS import org.opensearch.commons.notifications.model.ConfigType import org.opensearch.commons.notifications.model.DeliveryStatus import org.opensearch.commons.notifications.model.EventSource import org.opensearch.commons.notifications.model.EventStatus -import org.opensearch.commons.notifications.model.Feature import org.opensearch.commons.notifications.model.NotificationEvent import org.opensearch.commons.notifications.model.NotificationEventInfo import org.opensearch.commons.notifications.model.NotificationEventSearchResult @@ -62,7 +63,7 @@ internal class GetNotificationEventResponseTests { val sampleEventSource = EventSource( "title", "reference_id", - Feature.ALERTING, + FEATURE_ALERTING, severity = SeverityType.INFO ) val sampleStatus = EventStatus( @@ -90,13 +91,13 @@ internal class GetNotificationEventResponseTests { val eventSource1 = EventSource( "title 1", "reference_id_1", - Feature.ALERTING, + FEATURE_ALERTING, severity = SeverityType.INFO ) val eventSource2 = EventSource( "title 2", "reference_id_2", - Feature.REPORTS, + FEATURE_REPORTS, severity = SeverityType.HIGH ) val status1 = EventStatus( @@ -157,7 +158,7 @@ internal class GetNotificationEventResponseTests { val sampleEventSource = EventSource( "title", "reference_id", - Feature.ALERTING, + FEATURE_ALERTING, severity = SeverityType.INFO ) val sampleStatus = EventStatus( @@ -188,13 +189,13 @@ internal class GetNotificationEventResponseTests { val eventSource1 = EventSource( "title 1", "reference_id_1", - Feature.ALERTING, + FEATURE_ALERTING, severity = SeverityType.INFO ) val eventSource2 = EventSource( "title 2", "reference_id_2", - Feature.REPORTS, + FEATURE_REPORTS, severity = SeverityType.HIGH ) val status1 = EventStatus( @@ -242,7 +243,7 @@ internal class GetNotificationEventResponseTests { val sampleEventSource = EventSource( "title", "reference_id", - Feature.ALERTING, + FEATURE_ALERTING, severity = SeverityType.INFO ) val sampleStatus = EventStatus( @@ -310,7 +311,7 @@ internal class GetNotificationEventResponseTests { val sampleEventSource = EventSource( "title", "reference_id", - Feature.ALERTING, + FEATURE_ALERTING, severity = SeverityType.INFO ) val sampleStatus = EventStatus( diff --git a/src/test/kotlin/org/opensearch/commons/notifications/action/SendNotificationRequestTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/action/SendNotificationRequestTests.kt index 9c8bd2b4..31f6f549 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/action/SendNotificationRequestTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/action/SendNotificationRequestTests.kt @@ -32,9 +32,11 @@ import org.junit.jupiter.api.Assertions.assertNotNull import org.junit.jupiter.api.Assertions.assertNull import org.junit.jupiter.api.Test import org.junit.jupiter.api.assertThrows +import org.opensearch.commons.notifications.NotificationConstants.FEATURE_ALERTING +import org.opensearch.commons.notifications.NotificationConstants.FEATURE_INDEX_MANAGEMENT +import org.opensearch.commons.notifications.NotificationConstants.FEATURE_REPORTS import org.opensearch.commons.notifications.model.ChannelMessage import org.opensearch.commons.notifications.model.EventSource -import org.opensearch.commons.notifications.model.Feature import org.opensearch.commons.notifications.model.SeverityType import org.opensearch.commons.utils.createObjectFromJsonString import org.opensearch.commons.utils.getJsonString @@ -58,7 +60,7 @@ internal class SendNotificationRequestTests { val notificationInfo = EventSource( "title", "reference_id", - Feature.REPORTS, + FEATURE_REPORTS, SeverityType.HIGH, listOf("tag1", "tag2") ) @@ -82,7 +84,7 @@ internal class SendNotificationRequestTests { val notificationInfo = EventSource( "title", "reference_id", - Feature.INDEX_MANAGEMENT, + FEATURE_INDEX_MANAGEMENT, SeverityType.CRITICAL, listOf("tag1", "tag2") ) @@ -115,7 +117,7 @@ internal class SendNotificationRequestTests { val notificationInfo = EventSource( "title", "reference_id", - Feature.ALERTING, + FEATURE_ALERTING, SeverityType.HIGH, listOf("tag1", "tag2") ) @@ -159,7 +161,7 @@ internal class SendNotificationRequestTests { val notificationInfo = EventSource( "title", "reference_id", - Feature.REPORTS, + FEATURE_REPORTS, SeverityType.INFO, listOf("tag1", "tag2") ) diff --git a/src/test/kotlin/org/opensearch/commons/notifications/action/UpdateNotificationConfigRequestTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/action/UpdateNotificationConfigRequestTests.kt index 607e8077..2dfcff69 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/action/UpdateNotificationConfigRequestTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/action/UpdateNotificationConfigRequestTests.kt @@ -31,11 +31,11 @@ import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Assertions.assertNull import org.junit.jupiter.api.Test import org.junit.jupiter.api.assertThrows +import org.opensearch.commons.notifications.NotificationConstants.FEATURE_INDEX_MANAGEMENT import org.opensearch.commons.notifications.model.Chime import org.opensearch.commons.notifications.model.ConfigType import org.opensearch.commons.notifications.model.Email import org.opensearch.commons.notifications.model.EmailGroup -import org.opensearch.commons.notifications.model.Feature import org.opensearch.commons.notifications.model.MethodType import org.opensearch.commons.notifications.model.NotificationConfig import org.opensearch.commons.notifications.model.Slack @@ -44,7 +44,6 @@ import org.opensearch.commons.notifications.model.Webhook import org.opensearch.commons.utils.createObjectFromJsonString import org.opensearch.commons.utils.getJsonString import org.opensearch.commons.utils.recreateObject -import java.util.EnumSet internal class UpdateNotificationConfigRequestTests { @@ -54,7 +53,7 @@ internal class UpdateNotificationConfigRequestTests { "name", "description", ConfigType.WEBHOOK, - EnumSet.of(Feature.INDEX_MANAGEMENT), + setOf(FEATURE_INDEX_MANAGEMENT), isEnabled = true, configData = sampleWebhook ) @@ -66,7 +65,7 @@ internal class UpdateNotificationConfigRequestTests { "name", "description", ConfigType.SLACK, - EnumSet.of(Feature.INDEX_MANAGEMENT), + setOf(FEATURE_INDEX_MANAGEMENT), isEnabled = true, configData = sampleSlack ) @@ -78,7 +77,7 @@ internal class UpdateNotificationConfigRequestTests { "name", "description", ConfigType.CHIME, - EnumSet.of(Feature.INDEX_MANAGEMENT), + setOf(FEATURE_INDEX_MANAGEMENT), isEnabled = true, configData = sampleChime ) @@ -90,7 +89,7 @@ internal class UpdateNotificationConfigRequestTests { "name", "description", ConfigType.EMAIL_GROUP, - EnumSet.of(Feature.INDEX_MANAGEMENT), + setOf(FEATURE_INDEX_MANAGEMENT), isEnabled = true, configData = sampleEmailGroup ) @@ -106,7 +105,7 @@ internal class UpdateNotificationConfigRequestTests { "name", "description", ConfigType.EMAIL, - EnumSet.of(Feature.INDEX_MANAGEMENT), + setOf(FEATURE_INDEX_MANAGEMENT), isEnabled = true, configData = sampleEmail ) @@ -123,7 +122,7 @@ internal class UpdateNotificationConfigRequestTests { "name", "description", ConfigType.SMTP_ACCOUNT, - EnumSet.of(Feature.INDEX_MANAGEMENT), + setOf(FEATURE_INDEX_MANAGEMENT), isEnabled = true, configData = sampleSmtpAccount ) @@ -250,7 +249,7 @@ internal class UpdateNotificationConfigRequestTests { "name", "description", ConfigType.SLACK, - EnumSet.of(Feature.INDEX_MANAGEMENT), + setOf(FEATURE_INDEX_MANAGEMENT), isEnabled = true, configData = sampleSlack ) @@ -280,7 +279,7 @@ internal class UpdateNotificationConfigRequestTests { "name", "description", ConfigType.WEBHOOK, - EnumSet.of(Feature.INDEX_MANAGEMENT), + setOf(FEATURE_INDEX_MANAGEMENT), isEnabled = true, configData = sampleWebhook ) @@ -310,7 +309,7 @@ internal class UpdateNotificationConfigRequestTests { "name", "description", ConfigType.CHIME, - EnumSet.of(Feature.INDEX_MANAGEMENT), + setOf(FEATURE_INDEX_MANAGEMENT), isEnabled = true, configData = sampleChime ) @@ -340,7 +339,7 @@ internal class UpdateNotificationConfigRequestTests { "name", "description", ConfigType.EMAIL_GROUP, - EnumSet.of(Feature.INDEX_MANAGEMENT), + setOf(FEATURE_INDEX_MANAGEMENT), isEnabled = true, configData = sampleEmailGroup ) @@ -374,7 +373,7 @@ internal class UpdateNotificationConfigRequestTests { "name", "description", ConfigType.EMAIL, - EnumSet.of(Feature.INDEX_MANAGEMENT), + setOf(FEATURE_INDEX_MANAGEMENT), isEnabled = true, configData = sampleEmail ) @@ -410,7 +409,7 @@ internal class UpdateNotificationConfigRequestTests { "name", "description", ConfigType.SMTP_ACCOUNT, - EnumSet.of(Feature.INDEX_MANAGEMENT), + setOf(FEATURE_INDEX_MANAGEMENT), isEnabled = true, configData = sampleSmtpAccount ) @@ -448,7 +447,7 @@ internal class UpdateNotificationConfigRequestTests { "name", "description", ConfigType.SLACK, - EnumSet.of(Feature.INDEX_MANAGEMENT), + setOf(FEATURE_INDEX_MANAGEMENT), isEnabled = true, configData = sampleSlack ) diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/EventSourceTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/EventSourceTests.kt index 883c5047..6a87ed3f 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/EventSourceTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/EventSourceTests.kt @@ -29,6 +29,7 @@ package org.opensearch.commons.notifications.model import org.junit.jupiter.api.Assertions import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Test +import org.opensearch.commons.notifications.NotificationConstants.FEATURE_ALERTING import org.opensearch.commons.utils.createObjectFromJsonString import org.opensearch.commons.utils.getJsonString import org.opensearch.commons.utils.recreateObject @@ -40,7 +41,7 @@ internal class EventSourceTests { val sampleEventSource = EventSource( "title", "reference_id", - Feature.ALERTING, + FEATURE_ALERTING, severity = SeverityType.INFO ) val recreatedObject = recreateObject(sampleEventSource) { EventSource(it) } @@ -52,7 +53,7 @@ internal class EventSourceTests { val sampleEventSource = EventSource( "title", "reference_id", - Feature.ALERTING, + FEATURE_ALERTING, severity = SeverityType.INFO ) @@ -66,7 +67,7 @@ internal class EventSourceTests { val sampleEventSource = EventSource( "title", "reference_id", - Feature.ALERTING, + FEATURE_ALERTING, tags = listOf("tag1", "tag2"), severity = SeverityType.INFO ) @@ -87,11 +88,11 @@ internal class EventSourceTests { } @Test - fun `Event source should safely ignore unknown feature type in json object`() { + fun `Event source should safely accepts unknown feature type in json object`() { val sampleEventSource = EventSource( "title", "reference_id", - Feature.NONE, + "NewFeature", tags = listOf("tag1", "tag2"), severity = SeverityType.INFO ) @@ -114,7 +115,7 @@ internal class EventSourceTests { EventSource( "", "reference_id", - Feature.ALERTING, + FEATURE_ALERTING, tags = listOf("tag1", "tag2"), severity = SeverityType.INFO ) diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/FeatureTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/FeatureTests.kt deleted file mode 100644 index 215c2c2c..00000000 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/FeatureTests.kt +++ /dev/null @@ -1,56 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * - */ -package org.opensearch.commons.notifications.model - -import org.junit.jupiter.api.Assertions.assertEquals -import org.junit.jupiter.api.Test -import org.opensearch.commons.notifications.model.Feature.Companion.enumParser -import org.opensearch.commons.notifications.model.Feature.Companion.fromTagOrDefault - -internal class FeatureTests { - - @Test - fun `toString should return tag`() { - Feature.values().forEach { - assertEquals(it.tag, it.toString()) - } - } - - @Test - fun `fromTagOrDefault should return corresponding enum`() { - Feature.values().forEach { - assertEquals(it, fromTagOrDefault(it.tag)) - } - } - - @Test - fun `EnumParser fromTagOrDefault should return corresponding enum`() { - Feature.values().forEach { - assertEquals(it, enumParser.fromTagOrDefault(it.tag)) - } - } -} diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationConfigInfoTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationConfigInfoTests.kt index 79c1035d..409decd7 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationConfigInfoTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationConfigInfoTests.kt @@ -29,11 +29,12 @@ package org.opensearch.commons.notifications.model import org.junit.jupiter.api.Assertions import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Test +import org.opensearch.commons.notifications.NotificationConstants.FEATURE_INDEX_MANAGEMENT +import org.opensearch.commons.notifications.NotificationConstants.FEATURE_REPORTS import org.opensearch.commons.utils.createObjectFromJsonString import org.opensearch.commons.utils.getJsonString import org.opensearch.commons.utils.recreateObject import java.time.Instant -import java.util.EnumSet internal class NotificationConfigInfoTests { @@ -44,7 +45,7 @@ internal class NotificationConfigInfoTests { "name", "description", ConfigType.SLACK, - EnumSet.of(Feature.REPORTS), + setOf(FEATURE_REPORTS), configData = sampleSlack ) val configInfo = NotificationConfigInfo( @@ -67,7 +68,7 @@ internal class NotificationConfigInfoTests { "name", "description", ConfigType.SLACK, - EnumSet.of(Feature.REPORTS), + setOf(FEATURE_REPORTS), configData = sampleSlack ) val configInfo = NotificationConfigInfo( @@ -91,7 +92,7 @@ internal class NotificationConfigInfoTests { "name", "description", ConfigType.SLACK, - EnumSet.of(Feature.INDEX_MANAGEMENT), + setOf(FEATURE_INDEX_MANAGEMENT), isEnabled = true, configData = sampleSlack ) @@ -130,7 +131,7 @@ internal class NotificationConfigInfoTests { "name", "description", ConfigType.SLACK, - EnumSet.of(Feature.INDEX_MANAGEMENT), + setOf(FEATURE_INDEX_MANAGEMENT), isEnabled = true, configData = sampleSlack ) @@ -171,7 +172,7 @@ internal class NotificationConfigInfoTests { "name", "description", ConfigType.SLACK, - EnumSet.of(Feature.REPORTS), + setOf(FEATURE_REPORTS), configData = sampleSlack ) Assertions.assertThrows(IllegalArgumentException::class.java) { diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationConfigSearchResultsTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationConfigSearchResultsTests.kt index a9543533..6a10935f 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationConfigSearchResultsTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationConfigSearchResultsTests.kt @@ -30,11 +30,12 @@ import org.apache.lucene.search.TotalHits import org.junit.jupiter.api.Assertions import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Test +import org.opensearch.commons.notifications.NotificationConstants.FEATURE_INDEX_MANAGEMENT +import org.opensearch.commons.notifications.NotificationConstants.FEATURE_REPORTS import org.opensearch.commons.utils.createObjectFromJsonString import org.opensearch.commons.utils.getJsonString import org.opensearch.commons.utils.recreateObject import java.time.Instant -import java.util.EnumSet internal class NotificationConfigSearchResultsTests { @@ -56,7 +57,7 @@ internal class NotificationConfigSearchResultsTests { "name", "description", ConfigType.SLACK, - EnumSet.of(Feature.REPORTS), + setOf(FEATURE_REPORTS), configData = sampleSlack ) val configInfo = NotificationConfigInfo( @@ -77,7 +78,7 @@ internal class NotificationConfigSearchResultsTests { "name", "description", ConfigType.SLACK, - EnumSet.of(Feature.REPORTS), + setOf(FEATURE_REPORTS), configData = Slack("https://domain.com/sample_url#1234567890") ) val configInfo1 = NotificationConfigInfo( @@ -91,7 +92,7 @@ internal class NotificationConfigSearchResultsTests { "name", "description", ConfigType.CHIME, - EnumSet.of(Feature.INDEX_MANAGEMENT), + setOf(FEATURE_INDEX_MANAGEMENT), configData = Chime("https://domain.com/sample_url#1234567890") ) val configInfo2 = NotificationConfigInfo( @@ -118,7 +119,7 @@ internal class NotificationConfigSearchResultsTests { "name", "description", ConfigType.SLACK, - EnumSet.of(Feature.REPORTS), + setOf(FEATURE_REPORTS), configData = Slack("https://domain.com/sample_url#1234567890") ) val configInfo1 = NotificationConfigInfo( @@ -132,7 +133,7 @@ internal class NotificationConfigSearchResultsTests { "name", "description", ConfigType.CHIME, - EnumSet.of(Feature.INDEX_MANAGEMENT), + setOf(FEATURE_INDEX_MANAGEMENT), configData = Chime("https://domain.com/sample_url#1234567890") ) val configInfo2 = NotificationConfigInfo( @@ -161,7 +162,7 @@ internal class NotificationConfigSearchResultsTests { "name", "description", ConfigType.SLACK, - EnumSet.of(Feature.REPORTS), + setOf(FEATURE_REPORTS), configData = sampleSlack ) val configInfo = NotificationConfigInfo( @@ -185,7 +186,7 @@ internal class NotificationConfigSearchResultsTests { "name", "description", ConfigType.SLACK, - EnumSet.of(Feature.REPORTS), + setOf(FEATURE_REPORTS), configData = Slack("https://domain.com/sample_url#1234567890") ) val configInfo1 = NotificationConfigInfo( @@ -199,7 +200,7 @@ internal class NotificationConfigSearchResultsTests { "name", "description", ConfigType.CHIME, - EnumSet.of(Feature.INDEX_MANAGEMENT), + setOf(FEATURE_INDEX_MANAGEMENT), configData = Chime("https://domain.com/sample_url#1234567890") ) val configInfo2 = NotificationConfigInfo( @@ -229,7 +230,7 @@ internal class NotificationConfigSearchResultsTests { "name", "description", ConfigType.SLACK, - EnumSet.of(Feature.INDEX_MANAGEMENT), + setOf(FEATURE_INDEX_MANAGEMENT), isEnabled = true, configData = sampleSlack ) @@ -280,7 +281,7 @@ internal class NotificationConfigSearchResultsTests { "name", "description", ConfigType.SLACK, - EnumSet.of(Feature.INDEX_MANAGEMENT), + setOf(FEATURE_INDEX_MANAGEMENT), isEnabled = true, configData = sampleSlack ) diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationConfigTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationConfigTests.kt index ab45e2fc..c7126ab0 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationConfigTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationConfigTests.kt @@ -28,10 +28,12 @@ package org.opensearch.commons.notifications.model import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Test +import org.opensearch.commons.notifications.NotificationConstants.FEATURE_ALERTING +import org.opensearch.commons.notifications.NotificationConstants.FEATURE_INDEX_MANAGEMENT +import org.opensearch.commons.notifications.NotificationConstants.FEATURE_REPORTS import org.opensearch.commons.utils.createObjectFromJsonString import org.opensearch.commons.utils.getJsonString import org.opensearch.commons.utils.recreateObject -import java.util.EnumSet internal class NotificationConfigTests { @@ -42,7 +44,7 @@ internal class NotificationConfigTests { "name", "description", ConfigType.SLACK, - EnumSet.of(Feature.REPORTS), + setOf(FEATURE_REPORTS), configData = sampleSlack ) val recreatedObject = recreateObject(sampleConfig) { NotificationConfig(it) } @@ -56,7 +58,7 @@ internal class NotificationConfigTests { "name", "description", ConfigType.SLACK, - EnumSet.of(Feature.REPORTS), + setOf(FEATURE_REPORTS), configData = sampleSlack ) val jsonString = getJsonString(sampleConfig) @@ -71,7 +73,7 @@ internal class NotificationConfigTests { "name", "description", ConfigType.CHIME, - EnumSet.of(Feature.ALERTING), + setOf(FEATURE_ALERTING), configData = sampleChime ) val recreatedObject = recreateObject(sampleConfig) { NotificationConfig(it) } @@ -85,7 +87,7 @@ internal class NotificationConfigTests { "name", "description", ConfigType.CHIME, - EnumSet.of(Feature.ALERTING), + setOf(FEATURE_ALERTING), configData = sampleChime ) val jsonString = getJsonString(sampleConfig) @@ -100,7 +102,7 @@ internal class NotificationConfigTests { "name", "description", ConfigType.WEBHOOK, - EnumSet.of(Feature.INDEX_MANAGEMENT), + setOf(FEATURE_INDEX_MANAGEMENT), configData = sampleWebhook ) val recreatedObject = recreateObject(sampleConfig) { NotificationConfig(it) } @@ -114,7 +116,7 @@ internal class NotificationConfigTests { "name", "description", ConfigType.WEBHOOK, - EnumSet.of(Feature.INDEX_MANAGEMENT), + setOf(FEATURE_INDEX_MANAGEMENT), configData = sampleWebhook ) val jsonString = getJsonString(sampleConfig) @@ -129,7 +131,7 @@ internal class NotificationConfigTests { "name", "description", ConfigType.EMAIL, - EnumSet.of(Feature.INDEX_MANAGEMENT), + setOf(FEATURE_INDEX_MANAGEMENT), configData = sampleEmail ) val recreatedObject = recreateObject(sampleConfig) { NotificationConfig(it) } @@ -143,7 +145,7 @@ internal class NotificationConfigTests { "name", "description", ConfigType.EMAIL, - EnumSet.of(Feature.INDEX_MANAGEMENT), + setOf(FEATURE_INDEX_MANAGEMENT), configData = sampleEmail ) val jsonString = getJsonString(sampleConfig) @@ -158,7 +160,7 @@ internal class NotificationConfigTests { "name", "description", ConfigType.SMTP_ACCOUNT, - EnumSet.of(Feature.INDEX_MANAGEMENT), + setOf(FEATURE_INDEX_MANAGEMENT), configData = smtpAccount ) val jsonString = getJsonString(sampleConfig) @@ -173,7 +175,7 @@ internal class NotificationConfigTests { "name", "description", ConfigType.SMTP_ACCOUNT, - EnumSet.of(Feature.INDEX_MANAGEMENT), + setOf(FEATURE_INDEX_MANAGEMENT), configData = sampleSmtpAccount ) val recreatedObject = recreateObject(sampleConfig) { NotificationConfig(it) } @@ -187,7 +189,7 @@ internal class NotificationConfigTests { "name", "description", ConfigType.EMAIL_GROUP, - EnumSet.of(Feature.INDEX_MANAGEMENT), + setOf(FEATURE_INDEX_MANAGEMENT), configData = sampleEmailGroup ) val jsonString = getJsonString(sampleConfig) @@ -202,7 +204,7 @@ internal class NotificationConfigTests { "name", "description", ConfigType.EMAIL_GROUP, - EnumSet.of(Feature.INDEX_MANAGEMENT), + setOf(FEATURE_INDEX_MANAGEMENT), configData = sampleEmailGroup ) val recreatedObject = recreateObject(sampleConfig) { NotificationConfig(it) } @@ -217,7 +219,7 @@ internal class NotificationConfigTests { "name", "description", ConfigType.NONE, - EnumSet.of(Feature.INDEX_MANAGEMENT), + setOf(FEATURE_INDEX_MANAGEMENT), isEnabled = true, configData = sampleSlack ) @@ -240,13 +242,13 @@ internal class NotificationConfigTests { } @Test - fun `Config should safely ignore unknown feature type in json object`() { + fun `Config should safely accepts unknown feature type in json object`() { val sampleWebhook = Webhook("https://domain.com/sample_webhook_url#1234567890") val sampleConfig = NotificationConfig( "name", "description", ConfigType.WEBHOOK, - EnumSet.of(Feature.INDEX_MANAGEMENT, Feature.NONE), + setOf(FEATURE_INDEX_MANAGEMENT, "NewFeature1", "NewFeature2"), isEnabled = true, configData = sampleWebhook ) diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationEventInfoTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationEventInfoTests.kt index e23ca1e0..9f45fbb0 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationEventInfoTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationEventInfoTests.kt @@ -29,6 +29,7 @@ package org.opensearch.commons.notifications.model import org.junit.jupiter.api.Assertions import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Test +import org.opensearch.commons.notifications.NotificationConstants.FEATURE_ALERTING import org.opensearch.commons.utils.createObjectFromJsonString import org.opensearch.commons.utils.getJsonString import org.opensearch.commons.utils.recreateObject @@ -41,7 +42,7 @@ internal class NotificationEventInfoTests { val sampleEventSource = EventSource( "title", "reference_id", - Feature.ALERTING, + FEATURE_ALERTING, severity = SeverityType.INFO ) val sampleStatus = EventStatus( @@ -69,7 +70,7 @@ internal class NotificationEventInfoTests { val sampleEventSource = EventSource( "title", "reference_id", - Feature.ALERTING, + FEATURE_ALERTING, severity = SeverityType.INFO ) val sampleStatus = EventStatus( @@ -98,7 +99,7 @@ internal class NotificationEventInfoTests { val sampleEventSource = EventSource( "title", "reference_id", - Feature.ALERTING, + FEATURE_ALERTING, severity = SeverityType.INFO ) val sampleStatus = EventStatus( @@ -155,7 +156,7 @@ internal class NotificationEventInfoTests { val sampleEventSource = EventSource( "title", "reference_id", - Feature.ALERTING, + FEATURE_ALERTING, severity = SeverityType.INFO ) val sampleStatus = EventStatus( @@ -215,7 +216,7 @@ internal class NotificationEventInfoTests { val sampleEventSource = EventSource( "title", "reference_id", - Feature.ALERTING, + FEATURE_ALERTING, severity = SeverityType.INFO ) val sampleStatus = EventStatus( diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationEventSearchResultTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationEventSearchResultTests.kt index d09fe9d2..078d4910 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationEventSearchResultTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationEventSearchResultTests.kt @@ -30,6 +30,8 @@ import org.apache.lucene.search.TotalHits import org.junit.jupiter.api.Assertions import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Test +import org.opensearch.commons.notifications.NotificationConstants.FEATURE_ALERTING +import org.opensearch.commons.notifications.NotificationConstants.FEATURE_REPORTS import org.opensearch.commons.utils.createObjectFromJsonString import org.opensearch.commons.utils.getJsonString import org.opensearch.commons.utils.recreateObject @@ -53,7 +55,7 @@ internal class NotificationEventSearchResultTests { val sampleEventSource = EventSource( "title", "reference_id", - Feature.ALERTING, + FEATURE_ALERTING, severity = SeverityType.INFO ) val sampleStatus = EventStatus( @@ -80,13 +82,13 @@ internal class NotificationEventSearchResultTests { val eventSource1 = EventSource( "title 1", "reference_id_1", - Feature.ALERTING, + FEATURE_ALERTING, severity = SeverityType.INFO ) val eventSource2 = EventSource( "title 2", "reference_id_2", - Feature.REPORTS, + FEATURE_REPORTS, severity = SeverityType.HIGH ) val status1 = EventStatus( @@ -147,13 +149,13 @@ internal class NotificationEventSearchResultTests { val eventSource1 = EventSource( "title 1", "reference_id_1", - Feature.ALERTING, + FEATURE_ALERTING, severity = SeverityType.INFO ) val eventSource2 = EventSource( "title 2", "reference_id_2", - Feature.REPORTS, + FEATURE_REPORTS, severity = SeverityType.HIGH ) val status1 = EventStatus( @@ -213,7 +215,7 @@ internal class NotificationEventSearchResultTests { val sampleEventSource = EventSource( "title", "reference_id", - Feature.ALERTING, + FEATURE_ALERTING, severity = SeverityType.INFO ) val sampleStatus = EventStatus( @@ -243,13 +245,13 @@ internal class NotificationEventSearchResultTests { val eventSource1 = EventSource( "title 1", "reference_id_1", - Feature.ALERTING, + FEATURE_ALERTING, severity = SeverityType.INFO ) val eventSource2 = EventSource( "title 2", "reference_id_2", - Feature.REPORTS, + FEATURE_REPORTS, severity = SeverityType.HIGH ) val status1 = EventStatus( @@ -296,7 +298,7 @@ internal class NotificationEventSearchResultTests { val sampleEventSource = EventSource( "title", "reference_id", - Feature.ALERTING, + FEATURE_ALERTING, severity = SeverityType.INFO ) val sampleStatus = EventStatus( @@ -364,7 +366,7 @@ internal class NotificationEventSearchResultTests { val sampleEventSource = EventSource( "title", "reference_id", - Feature.ALERTING, + FEATURE_ALERTING, severity = SeverityType.INFO ) val sampleStatus = EventStatus( diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationEventTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationEventTests.kt index 4a135d0c..92c53fd8 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationEventTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationEventTests.kt @@ -29,6 +29,8 @@ package org.opensearch.commons.notifications.model import org.junit.jupiter.api.Assertions import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Test +import org.opensearch.commons.notifications.NotificationConstants.FEATURE_ALERTING +import org.opensearch.commons.notifications.NotificationConstants.FEATURE_REPORTS import org.opensearch.commons.utils.createObjectFromJsonString import org.opensearch.commons.utils.getJsonString import org.opensearch.commons.utils.recreateObject @@ -40,7 +42,7 @@ internal class NotificationEventTests { val sampleEventSource = EventSource( "title", "reference_id", - Feature.ALERTING, + FEATURE_ALERTING, severity = SeverityType.INFO ) val sampleStatus = EventStatus( @@ -59,7 +61,7 @@ internal class NotificationEventTests { val sampleEventSource = EventSource( "title", "reference_id", - Feature.REPORTS, + FEATURE_REPORTS, severity = SeverityType.INFO ) val sampleStatus = EventStatus( @@ -79,7 +81,7 @@ internal class NotificationEventTests { val sampleEventSource = EventSource( "title", "reference_id", - Feature.ALERTING, + FEATURE_ALERTING, tags = listOf("tag1", "tag2"), severity = SeverityType.INFO ) diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/SesAccountTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/SesAccountTests.kt new file mode 100644 index 00000000..c99506fd --- /dev/null +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/SesAccountTests.kt @@ -0,0 +1,151 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + * + * Modifications Copyright OpenSearch Contributors. See + * GitHub history for details. + */ + +package org.opensearch.commons.notifications.model + +import com.fasterxml.jackson.core.JsonParseException +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.assertThrows +import org.opensearch.commons.utils.createObjectFromJsonString +import org.opensearch.commons.utils.getJsonString +import org.opensearch.commons.utils.recreateObject + +internal class SesAccountTests { + + @Test + fun `SES should throw exception if empty region`() { + assertThrows { + SesAccount("", null, "from@domain.com") + } + val jsonString = """ + { + "region":"", + "from_address":"from@domain.com" + } + """.trimIndent() + assertThrows { + createObjectFromJsonString(jsonString) { SesAccount.parse(it) } + } + } + + @Test + fun `SES should throw exception if invalid role ARN`() { + assertThrows { + SesAccount("us-east-1", "arn:aws:iam:us-east-1:0123456789:role-test", "from@domain.com") + } + val jsonString = """ + { + "region":"us-east-1", + "role_arn":"arn:aws:iam:us-east-1:0123456789:role-test", + "from_address":"from@domain.com" + } + """.trimIndent() + assertThrows { + createObjectFromJsonString(jsonString) { SesAccount.parse(it) } + } + } + + @Test + fun `SES should throw exception when email id is invalid`() { + val jsonString = """ + { + "region":"us-east-1", + "from_address":".from@domain.com" + } + """.trimIndent() + assertThrows { + createObjectFromJsonString(jsonString) { SesAccount.parse(it) } + } + } + + @Test + fun `SES serialize and deserialize transport object should be equal`() { + val sesAccount = SesAccount("us-east-1", "arn:aws:iam::012345678912:role/iam-test", "from@domain.com") + val recreatedObject = recreateObject(sesAccount) { SesAccount(it) } + assertEquals(sesAccount, recreatedObject) + } + + @Test + fun `SES serialize and deserialize using json object should be equal`() { + val sesAccount = SesAccount("us-east-1", "arn:aws:iam::012345678912:role/iam-test", "from@domain.com") + val jsonString = getJsonString(sesAccount) + val recreatedObject = createObjectFromJsonString(jsonString) { SesAccount.parse(it) } + assertEquals(sesAccount, recreatedObject) + } + + @Test + fun `SES should deserialize json object using parser`() { + val sesAccount = SesAccount("us-east-1", "arn:aws:iam::012345678912:role/iam-test", "from@domain.com") + val jsonString = """ + { + "region":"${sesAccount.awsRegion}", + "role_arn":"${sesAccount.roleArn}", + "from_address":"${sesAccount.fromAddress}" + } + """.trimIndent() + val recreatedObject = createObjectFromJsonString(jsonString) { SesAccount.parse(it) } + assertEquals(sesAccount, recreatedObject) + } + + @Test + fun `SES should throw exception when invalid json object is passed`() { + val jsonString = "sample message" + assertThrows { + createObjectFromJsonString(jsonString) { SesAccount.parse(it) } + } + } + + @Test + fun `SES should throw exception when region is replace with region2 in json object`() { + val jsonString = """ + { + "region2":"us-east-1", + "role_arn":"arn:aws:iam::012345678912:role/iam-test", + "from_address":"from@domain.com" + } + """.trimIndent() + assertThrows { + createObjectFromJsonString(jsonString) { SesAccount.parse(it) } + } + } + + @Test + fun `SES should throw exception when from_address is replace with from_address2 in json object`() { + val jsonString = """ + { + "region":"us-east-1", + "role_arn":"arn:aws:iam::012345678912:role/iam-test", + "from_address2":"from@domain.com" + } + """.trimIndent() + assertThrows { + createObjectFromJsonString(jsonString) { SesAccount.parse(it) } + } + } + + @Test + fun `SES should safely ignore extra field in json object`() { + val sesAccount = SesAccount("us-east-1", "arn:aws:iam::012345678912:role/iam-test", "from@domain.com") + val jsonString = """ + { + "region":"${sesAccount.awsRegion}", + "role_arn":"${sesAccount.roleArn}", + "from_address":"${sesAccount.fromAddress}", + "extra_field_1":["extra", "value"], + "extra_field_2":{"extra":"value"}, + "extra_field_3":"extra value 3" + } + """.trimIndent() + val recreatedObject = createObjectFromJsonString(jsonString) { SesAccount.parse(it) } + assertEquals(sesAccount, recreatedObject) + } +} diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/SNSTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/SnsTests.kt similarity index 65% rename from src/test/kotlin/org/opensearch/commons/notifications/model/SNSTests.kt rename to src/test/kotlin/org/opensearch/commons/notifications/model/SnsTests.kt index 46d7cfc8..03d494d2 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/SNSTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/SnsTests.kt @@ -19,87 +19,87 @@ import org.opensearch.commons.utils.createObjectFromJsonString import org.opensearch.commons.utils.getJsonString import org.opensearch.commons.utils.recreateObject -internal class SNSTests { +internal class SnsTests { @Test fun `SNS should throw exception if empty topic`() { assertThrows(IllegalArgumentException::class.java) { - SNS("", null) + Sns("", null) } val jsonString = "{\"topic_arn\":\"\"}" assertThrows(IllegalArgumentException::class.java) { - createObjectFromJsonString(jsonString) { SNS.parse(it) } + createObjectFromJsonString(jsonString) { Sns.parse(it) } } } @Test fun `SNS should throw exception if invalid topic ARN`() { assertThrows(IllegalArgumentException::class.java) { - SNS("arn:aws:es:us-east-1:012345678989:test", null) + Sns("arn:aws:es:us-east-1:012345678989:test", null) } val jsonString = "{\"topic_arn\":\"arn:aws:es:us-east-1:012345678989:test\"}" assertThrows(IllegalArgumentException::class.java) { - createObjectFromJsonString(jsonString) { SNS.parse(it) } + createObjectFromJsonString(jsonString) { Sns.parse(it) } } } @Test fun `SNS should throw exception if invalid role ARN`() { assertThrows(IllegalArgumentException::class.java) { - SNS("arn:aws:sns:us-east-1:012345678912:topic-test", "arn:aws:iam:us-east-1:0123456789:role-test") + Sns("arn:aws:sns:us-east-1:012345678912:topic-test", "arn:aws:iam:us-east-1:0123456789:role-test") } val jsonString = "{\"topic_arn\":\"arn:aws:sns:us-east-1:012345678912:topic-test\",\"role_arn\":\"arn:aws:iam:us-east-1:0123456789:role-test\"}" assertThrows(IllegalArgumentException::class.java) { - createObjectFromJsonString(jsonString) { SNS.parse(it) } + createObjectFromJsonString(jsonString) { Sns.parse(it) } } } @Test fun `SNS serialize and deserialize transport object should be equal`() { - val sampleSNS = SNS("arn:aws:sns:us-east-1:012345678912:topic-test", "arn:aws:iam::012345678912:role/iam-test") - val recreatedObject = recreateObject(sampleSNS) { SNS(it) } - Assertions.assertEquals(sampleSNS, recreatedObject) + val sampleSns = Sns("arn:aws:sns:us-east-1:012345678912:topic-test", "arn:aws:iam::012345678912:role/iam-test") + val recreatedObject = recreateObject(sampleSns) { Sns(it) } + Assertions.assertEquals(sampleSns, recreatedObject) } @Test fun `SNS serialize and deserialize using json object should be equal`() { - val sampleSNS = SNS("arn:aws:sns:us-east-1:012345678912:topic-test", "arn:aws:iam::012345678912:role/iam-test") - val jsonString = getJsonString(sampleSNS) - val recreatedObject = createObjectFromJsonString(jsonString) { SNS.parse(it) } - Assertions.assertEquals(sampleSNS, recreatedObject) + val sampleSns = Sns("arn:aws:sns:us-east-1:012345678912:topic-test", "arn:aws:iam::012345678912:role/iam-test") + val jsonString = getJsonString(sampleSns) + val recreatedObject = createObjectFromJsonString(jsonString) { Sns.parse(it) } + Assertions.assertEquals(sampleSns, recreatedObject) } @Test fun `SNS should deserialize json object using parser`() { - val sampleSNS = SNS("arn:aws:sns:us-east-1:012345678912:topic-test", "arn:aws:iam::012345678912:role/iam-test") - val jsonString = "{\"topic_arn\":\"${sampleSNS.topicARN}\",\"role_arn\":\"${sampleSNS.roleARN}\"}" - val recreatedObject = createObjectFromJsonString(jsonString) { SNS.parse(it) } - Assertions.assertEquals(sampleSNS, recreatedObject) + val sampleSns = Sns("arn:aws:sns:us-east-1:012345678912:topic-test", "arn:aws:iam::012345678912:role/iam-test") + val jsonString = "{\"topic_arn\":\"${sampleSns.topicArn}\",\"role_arn\":\"${sampleSns.roleArn}\"}" + val recreatedObject = createObjectFromJsonString(jsonString) { Sns.parse(it) } + Assertions.assertEquals(sampleSns, recreatedObject) } @Test fun `SNS should throw exception when invalid json object is passed`() { val jsonString = "sample message" assertThrows(JsonParseException::class.java) { - createObjectFromJsonString(jsonString) { SNS.parse(it) } + createObjectFromJsonString(jsonString) { Sns.parse(it) } } } @Test fun `SNS should throw exception when arn is replace with arn2 in json object`() { - val sampleSNS = SNS("arn:aws:sns:us-east-1:012345678912:topic-test", "arn:aws:iam::012345678912:role/iam-test") - val jsonString = "{\"topic_arn2\":\"${sampleSNS.topicARN}\",\"role_arn\":\"${sampleSNS.roleARN}\"}" + val sampleSns = Sns("arn:aws:sns:us-east-1:012345678912:topic-test", "arn:aws:iam::012345678912:role/iam-test") + val jsonString = "{\"topic_arn2\":\"${sampleSns.topicArn}\",\"role_arn\":\"${sampleSns.roleArn}\"}" assertThrows(IllegalArgumentException::class.java) { - createObjectFromJsonString(jsonString) { SNS.parse(it) } + createObjectFromJsonString(jsonString) { Sns.parse(it) } } } @Test fun `SNS should safely ignore extra field in json object`() { - val sampleSNS = SNS("arn:aws:sns:us-east-1:012345678912:topic-test", null) - val jsonString = "{\"topic_arn\":\"${sampleSNS.topicARN}\", \"another\":\"field\"}" - val recreatedObject = createObjectFromJsonString(jsonString) { SNS.parse(it) } - Assertions.assertEquals(sampleSNS, recreatedObject) + val sampleSns = Sns("arn:aws:sns:us-east-1:012345678912:topic-test", null) + val jsonString = "{\"topic_arn\":\"${sampleSns.topicArn}\", \"another\":\"field\"}" + val recreatedObject = createObjectFromJsonString(jsonString) { Sns.parse(it) } + Assertions.assertEquals(sampleSns, recreatedObject) } } From 4b1c21c325967852709376142aa71cd187ae0126 Mon Sep 17 00:00:00 2001 From: Drew Baugher <46505179+dbbaughe@users.noreply.github.com> Date: Thu, 12 Aug 2021 17:47:12 -0700 Subject: [PATCH 009/140] Adds legacy chime, slack, custom webhook messages, request/response f (#53) * Adds legacy chime, slack, custom webhook messages, request/response for publishing legacy notifications, and method for executing transport action Signed-off-by: Drew Baugher <46505179+dbbaughe@users.noreply.github.com> * Fixes import and removes username/password that is not used by ISM Signed-off-by: Drew Baugher <46505179+dbbaughe@users.noreply.github.com> * Throws error for toXContent for legacy notification response Signed-off-by: Drew Baugher <46505179+dbbaughe@users.noreply.github.com> * Renames legacy destination types to have legacy prefix Signed-off-by: Drew Baugher <46505179+dbbaughe@users.noreply.github.com> * Obfuscates message to remove from logs in toString method Signed-off-by: Drew Baugher <46505179+dbbaughe@users.noreply.github.com> * Makes destinationt type private and updates places to use getter Signed-off-by: Drew Baugher <46505179+dbbaughe@users.noreply.github.com> * Inlines destination type Signed-off-by: Drew Baugher <46505179+dbbaughe@users.noreply.github.com> * Makes base message content final Signed-off-by: Drew Baugher <46505179+dbbaughe@users.noreply.github.com> * Requires url to be defined in LegacyCustomWebhookMessage for use across transport wire and only writes the full url instead of each individual part Signed-off-by: Drew Baugher <46505179+dbbaughe@users.noreply.github.com> --- .../message/LegacyBaseMessage.java | 128 ++++++++ .../message/LegacyChimeMessage.java | 91 ++++++ .../message/LegacyCustomWebhookMessage.java | 274 ++++++++++++++++++ .../message/LegacyDestinationType.java | 36 +++ .../message/LegacySlackMessage.java | 95 ++++++ .../response/LegacyBaseResponse.java | 60 ++++ .../response/LegacyDestinationResponse.java | 82 ++++++ .../NotificationsPluginInterface.kt | 28 ++ .../LegacyPublishNotificationRequest.kt | 82 ++++++ .../LegacyPublishNotificationResponse.kt | 63 ++++ .../action/NotificationsActions.kt | 13 + .../message/LegacyChimeMessageTest.java | 100 +++++++ .../LegacyCustomWebhookMessageTest.java | 177 +++++++++++ .../message/LegacySlackMessageTest.java | 110 +++++++ .../LegacyDestinationResponseTest.java | 82 ++++++ .../NotificationsPluginInterfaceTests.kt | 24 ++ .../LegacyPublishNotificationRequestTests.kt | 42 +++ .../LegacyPublishNotificationResponseTests.kt | 29 ++ 18 files changed, 1516 insertions(+) create mode 100644 src/main/java/org/opensearch/commons/destination/message/LegacyBaseMessage.java create mode 100644 src/main/java/org/opensearch/commons/destination/message/LegacyChimeMessage.java create mode 100644 src/main/java/org/opensearch/commons/destination/message/LegacyCustomWebhookMessage.java create mode 100644 src/main/java/org/opensearch/commons/destination/message/LegacyDestinationType.java create mode 100644 src/main/java/org/opensearch/commons/destination/message/LegacySlackMessage.java create mode 100644 src/main/java/org/opensearch/commons/destination/response/LegacyBaseResponse.java create mode 100644 src/main/java/org/opensearch/commons/destination/response/LegacyDestinationResponse.java create mode 100644 src/main/kotlin/org/opensearch/commons/notifications/action/LegacyPublishNotificationRequest.kt create mode 100644 src/main/kotlin/org/opensearch/commons/notifications/action/LegacyPublishNotificationResponse.kt create mode 100644 src/test/java/org/opensearch/commons/destination/message/LegacyChimeMessageTest.java create mode 100644 src/test/java/org/opensearch/commons/destination/message/LegacyCustomWebhookMessageTest.java create mode 100644 src/test/java/org/opensearch/commons/destination/message/LegacySlackMessageTest.java create mode 100644 src/test/java/org/opensearch/commons/destination/response/LegacyDestinationResponseTest.java create mode 100644 src/test/kotlin/org/opensearch/commons/notifications/action/LegacyPublishNotificationRequestTests.kt create mode 100644 src/test/kotlin/org/opensearch/commons/notifications/action/LegacyPublishNotificationResponseTests.kt diff --git a/src/main/java/org/opensearch/commons/destination/message/LegacyBaseMessage.java b/src/main/java/org/opensearch/commons/destination/message/LegacyBaseMessage.java new file mode 100644 index 00000000..b5122f31 --- /dev/null +++ b/src/main/java/org/opensearch/commons/destination/message/LegacyBaseMessage.java @@ -0,0 +1,128 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + * + * Modifications Copyright OpenSearch Contributors. See + * GitHub history for details. + */ + +/* + * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package org.opensearch.commons.destination.message; + +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.Map; + +import org.apache.http.client.utils.URIBuilder; +import org.opensearch.common.Strings; +import org.opensearch.common.io.stream.StreamInput; +import org.opensearch.common.io.stream.StreamOutput; +import org.opensearch.common.io.stream.Writeable; + +/** + * This class holds the generic parameters required for a + * message. + */ +public abstract class LegacyBaseMessage implements Writeable { + + private final LegacyDestinationType destinationType; + protected String destinationName; + protected String url; + private final String content; + + LegacyBaseMessage(final LegacyDestinationType destinationType, final String destinationName, final String content) { + if (destinationType == null) { + throw new IllegalArgumentException("Channel type must be defined"); + } + if (!Strings.hasLength(destinationName)) { + throw new IllegalArgumentException("Channel name must be defined"); + } + this.destinationType = destinationType; + this.destinationName = destinationName; + this.content = content; + } + + LegacyBaseMessage(final LegacyDestinationType destinationType, final String destinationName, final String content, final String url) { + this(destinationType, destinationName, content); + if (url == null) { + throw new IllegalArgumentException("url is invalid or empty"); + } + this.url = url; + } + + LegacyBaseMessage(StreamInput streamInput) throws IOException { + this.destinationType = streamInput.readEnum(LegacyDestinationType.class); + this.destinationName = streamInput.readString(); + this.url = streamInput.readOptionalString(); + this.content = streamInput.readString(); + } + + public void setUrl(String url) { + this.url = url; + } + + public LegacyDestinationType getChannelType() { + return destinationType; + } + + public String getChannelName() { + return destinationName; + } + + public String getMessageContent() { + return content; + } + + public String getUrl() { + return url; + } + + public URI getUri() { + return buildUri(getUrl().trim(), null, null, -1, null, null); + } + + protected URI buildUri(String endpoint, String scheme, String host, int port, String path, Map queryParams) { + try { + if (Strings.isNullOrEmpty(endpoint)) { + if (Strings.isNullOrEmpty(scheme)) { + scheme = "https"; + } + URIBuilder uriBuilder = new URIBuilder(); + if (queryParams != null) { + for (Map.Entry e : queryParams.entrySet()) + uriBuilder.addParameter(e.getKey(), e.getValue()); + } + return uriBuilder.setScheme(scheme).setHost(host).setPort(port).setPath(path).build(); + } + return new URIBuilder(endpoint).build(); + } catch (URISyntaxException exception) { + throw new IllegalStateException("Error creating URI"); + } + } + + @Override + public void writeTo(StreamOutput streamOutput) throws IOException { + streamOutput.writeEnum(destinationType); + streamOutput.writeString(destinationName); + streamOutput.writeOptionalString(url); + streamOutput.writeString(content); + } +} diff --git a/src/main/java/org/opensearch/commons/destination/message/LegacyChimeMessage.java b/src/main/java/org/opensearch/commons/destination/message/LegacyChimeMessage.java new file mode 100644 index 00000000..b457d9aa --- /dev/null +++ b/src/main/java/org/opensearch/commons/destination/message/LegacyChimeMessage.java @@ -0,0 +1,91 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + * + * Modifications Copyright OpenSearch Contributors. See + * GitHub history for details. + */ + +/* + * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package org.opensearch.commons.destination.message; + +import java.io.IOException; + +import org.opensearch.common.Strings; +import org.opensearch.common.io.stream.StreamInput; + +/** + * This class holds the contents of an Chime message + */ +public class LegacyChimeMessage extends LegacyBaseMessage { + private final String message; + + private LegacyChimeMessage(final String destinationName, final String url, final String message) { + super(LegacyDestinationType.LEGACY_CHIME, destinationName, message, url); + + if (Strings.isNullOrEmpty(message)) { + throw new IllegalArgumentException("Message content is missing"); + } + + this.message = message; + } + + public LegacyChimeMessage(StreamInput streamInput) throws IOException { + super(streamInput); + this.message = super.getMessageContent(); + } + + @Override + public String toString() { + return "DestinationType: " + getChannelType() + ", DestinationName:" + destinationName + ", Url: " + url + ", Message: <...>"; + } + + public static class Builder { + private String message; + private final String destinationName; + private String url; + + public Builder(String destinationName) { + this.destinationName = destinationName; + } + + public LegacyChimeMessage.Builder withMessage(String message) { + this.message = message; + return this; + } + + public LegacyChimeMessage.Builder withUrl(String url) { + this.url = url; + return this; + } + + public LegacyChimeMessage build() { + return new LegacyChimeMessage(this.destinationName, this.url, this.message); + } + } + + public String getMessage() { + return message; + } + + public String getUrl() { + return url; + } +} diff --git a/src/main/java/org/opensearch/commons/destination/message/LegacyCustomWebhookMessage.java b/src/main/java/org/opensearch/commons/destination/message/LegacyCustomWebhookMessage.java new file mode 100644 index 00000000..9645b327 --- /dev/null +++ b/src/main/java/org/opensearch/commons/destination/message/LegacyCustomWebhookMessage.java @@ -0,0 +1,274 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + * + * Modifications Copyright OpenSearch Contributors. See + * GitHub history for details. + */ + +/* + * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package org.opensearch.commons.destination.message; + +import java.io.IOException; +import java.net.URI; +import java.util.Map; + +import org.apache.http.client.methods.HttpPatch; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.client.methods.HttpPut; +import org.opensearch.common.Strings; +import org.opensearch.common.io.stream.StreamInput; +import org.opensearch.common.io.stream.StreamOutput; + +/** + * This class holds the content of an CustomWebhook message + */ +public class LegacyCustomWebhookMessage extends LegacyBaseMessage { + + private final String message; + private final String url; + private final String scheme; + private final String host; + private final String method; + private final int port; + private String path; + private final Map queryParams; + private Map headerParams; + + private LegacyCustomWebhookMessage( + final String destinationName, + final String url, + final String scheme, + final String host, + final Integer port, + final String path, + final String method, + final Map queryParams, + final Map headerParams, + final String message + ) { + super(LegacyDestinationType.LEGACY_CUSTOM_WEBHOOK, destinationName, message); + + if (!Strings.isNullOrEmpty(url)) { + setUrl(url.trim()); + } + + if (Strings.isNullOrEmpty(message)) { + throw new IllegalArgumentException("Message content is missing"); + } + + this.scheme = Strings.isNullOrEmpty(scheme) ? "https" : scheme; + this.port = port == null ? -1 : port; + + if (!Strings.isNullOrEmpty(path)) { + if (!path.startsWith("/")) { + this.path = "/" + path; + } + } + + if (Strings.isNullOrEmpty(url) && Strings.isNullOrEmpty(host)) { + throw new IllegalArgumentException("Either fully qualified URL or host name should be provided"); + } + + if (Strings.isNullOrEmpty(method)) { + // Default to POST for backwards compatibility + this.method = "POST"; + } else if (!HttpPost.METHOD_NAME.equals(method) && !HttpPut.METHOD_NAME.equals(method) && !HttpPatch.METHOD_NAME.equals(method)) { + throw new IllegalArgumentException("Invalid method supplied. Only POST, PUT and PATCH are allowed"); + } else { + this.method = method; + } + + this.message = message; + this.url = url; + this.host = host; + this.queryParams = queryParams; + this.headerParams = headerParams; + } + + public LegacyCustomWebhookMessage(StreamInput streamInput) throws IOException { + super(streamInput); + this.message = super.getMessageContent(); + this.url = streamInput.readOptionalString(); + this.scheme = null; + this.host = null; + this.method = streamInput.readOptionalString(); + this.port = -1; + this.path = null; + this.queryParams = null; + if (streamInput.readBoolean()) { + @SuppressWarnings("unchecked") + Map headerParams = (Map) (Map) streamInput.readMap(); + this.headerParams = headerParams; + } + } + + @Override + public String toString() { + return "DestinationType: " + + getChannelType() + + ", DestinationName:" + + destinationName + + ", Url: " + + url + + ", scheme: " + + scheme + + ", Host: " + + host + + ", Port: " + + port + + ", Path: " + + path + + ", Method: " + + method + + ", Message: <...>"; + } + + public static class Builder { + private String message; + private final String destinationName; + private String url; + private String scheme; + private String host; + private Integer port; + private String path; + private String method; + private Map queryParams; + private Map headerParams; + + public Builder(String destinationName) { + this.destinationName = destinationName; + } + + public LegacyCustomWebhookMessage.Builder withScheme(String scheme) { + this.scheme = scheme; + return this; + } + + public LegacyCustomWebhookMessage.Builder withHost(String host) { + this.host = host; + return this; + } + + public LegacyCustomWebhookMessage.Builder withPort(Integer port) { + this.port = port; + return this; + } + + public LegacyCustomWebhookMessage.Builder withPath(String path) { + this.path = path; + return this; + } + + public LegacyCustomWebhookMessage.Builder withMethod(String method) { + this.method = method; + return this; + } + + public LegacyCustomWebhookMessage.Builder withQueryParams(Map queryParams) { + this.queryParams = queryParams; + return this; + } + + public LegacyCustomWebhookMessage.Builder withHeaderParams(Map headerParams) { + this.headerParams = headerParams; + return this; + } + + public LegacyCustomWebhookMessage.Builder withMessage(String message) { + this.message = message; + return this; + } + + public LegacyCustomWebhookMessage.Builder withUrl(String url) { + this.url = url; + return this; + } + + public LegacyCustomWebhookMessage build() { + return new LegacyCustomWebhookMessage( + this.destinationName, + this.url, + this.scheme, + this.host, + this.port, + this.path, + this.method, + this.queryParams, + this.headerParams, + this.message + ); + } + } + + public String getScheme() { + return scheme; + } + + public String getHost() { + return host; + } + + public int getPort() { + return port; + } + + public String getPath() { + return path; + } + + public String getMethod() { + return method; + } + + public Map getQueryParams() { + return queryParams; + } + + public Map getHeaderParams() { + return headerParams; + } + + public URI getUri() { + return buildUri(getUrl(), getScheme(), getHost(), getPort(), getPath(), getQueryParams()); + } + + public String getMessage() { + return message; + } + + @Override + public void writeTo(StreamOutput streamOutput) throws IOException { + super.writeTo(streamOutput); + // Making LegacyCustomWebhookMessage streamable is purely to support the new pass through API from ISM -> Notification plugin + // and it only supports LegacyCustomWebhookMessage when the url is already constructed by ISM. + if (Strings.isNullOrEmpty(getUrl())) { + throw new IllegalStateException("Cannot use LegacyCustomWebhookMessage across transport wire without defining full url."); + } + streamOutput.writeOptionalString(url); + streamOutput.writeOptionalString(method); + streamOutput.writeBoolean(headerParams != null); + if (headerParams != null) { + @SuppressWarnings("unchecked") + Map headerParams = (Map) (Map) this.headerParams; + streamOutput.writeMap(headerParams); + } + } +} diff --git a/src/main/java/org/opensearch/commons/destination/message/LegacyDestinationType.java b/src/main/java/org/opensearch/commons/destination/message/LegacyDestinationType.java new file mode 100644 index 00000000..85689510 --- /dev/null +++ b/src/main/java/org/opensearch/commons/destination/message/LegacyDestinationType.java @@ -0,0 +1,36 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + * + * Modifications Copyright OpenSearch Contributors. See + * GitHub history for details. + */ + +/* + * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package org.opensearch.commons.destination.message; + +/** + * Supported legacy notification destinations for Index Management + */ +public enum LegacyDestinationType { + LEGACY_CHIME, + LEGACY_SLACK, + LEGACY_CUSTOM_WEBHOOK +} diff --git a/src/main/java/org/opensearch/commons/destination/message/LegacySlackMessage.java b/src/main/java/org/opensearch/commons/destination/message/LegacySlackMessage.java new file mode 100644 index 00000000..f426894a --- /dev/null +++ b/src/main/java/org/opensearch/commons/destination/message/LegacySlackMessage.java @@ -0,0 +1,95 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + * + * Modifications Copyright OpenSearch Contributors. See + * GitHub history for details. + */ + +/* + * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package org.opensearch.commons.destination.message; + +import java.io.IOException; + +import org.opensearch.common.Strings; +import org.opensearch.common.io.stream.StreamInput; + +/** + * This class holds the content of an Slack message + */ +public class LegacySlackMessage extends LegacyBaseMessage { + private final String message; + + private LegacySlackMessage(final String destinationName, final String url, final String message) { + super(LegacyDestinationType.LEGACY_SLACK, destinationName, message, url); + + if (Strings.isNullOrEmpty(url)) { // add URL validation + throw new IllegalArgumentException("Fully qualified URL is missing/invalid: " + url); + } + + if (Strings.isNullOrEmpty(message)) { + throw new IllegalArgumentException("Message content is missing"); + } + + this.message = message; + } + + public LegacySlackMessage(StreamInput streamInput) throws IOException { + super(streamInput); + this.message = super.getMessageContent(); + } + + @Override + public String toString() { + return "DestinationType: " + getChannelType() + ", DestinationName:" + destinationName + ", Url: " + url + ", Message: <...>"; + } + + public static class Builder { + private String message; + private String destinationName; + private String url; + + public Builder(String channelName) { + this.destinationName = channelName; + } + + public LegacySlackMessage.Builder withMessage(String message) { + this.message = message; + return this; + } + + public LegacySlackMessage.Builder withUrl(String url) { + this.url = url; + return this; + } + + public LegacySlackMessage build() { + return new LegacySlackMessage(this.destinationName, this.url, this.message); + } + } + + public String getMessage() { + return message; + } + + public String getUrl() { + return url; + } +} diff --git a/src/main/java/org/opensearch/commons/destination/response/LegacyBaseResponse.java b/src/main/java/org/opensearch/commons/destination/response/LegacyBaseResponse.java new file mode 100644 index 00000000..bbdd8d70 --- /dev/null +++ b/src/main/java/org/opensearch/commons/destination/response/LegacyBaseResponse.java @@ -0,0 +1,60 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + * + * Modifications Copyright OpenSearch Contributors. See + * GitHub history for details. + */ + +/* + * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package org.opensearch.commons.destination.response; + +import java.io.IOException; + +import org.opensearch.common.io.stream.StreamInput; +import org.opensearch.common.io.stream.StreamOutput; +import org.opensearch.common.io.stream.Writeable; + +/** + * This class holds the generic response attributes + */ +public abstract class LegacyBaseResponse implements Writeable { + protected Integer statusCode; + + LegacyBaseResponse(final Integer statusCode) { + if (statusCode == null) { + throw new IllegalArgumentException("status code is invalid"); + } + this.statusCode = statusCode; + } + + public LegacyBaseResponse(StreamInput streamInput) throws IOException { + this.statusCode = streamInput.readInt(); + } + + public int getStatusCode() { + return statusCode; + } + + @Override + public void writeTo(StreamOutput streamOutput) throws IOException { + streamOutput.writeInt(statusCode); + } +} diff --git a/src/main/java/org/opensearch/commons/destination/response/LegacyDestinationResponse.java b/src/main/java/org/opensearch/commons/destination/response/LegacyDestinationResponse.java new file mode 100644 index 00000000..bb927747 --- /dev/null +++ b/src/main/java/org/opensearch/commons/destination/response/LegacyDestinationResponse.java @@ -0,0 +1,82 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + * + * Modifications Copyright OpenSearch Contributors. See + * GitHub history for details. + */ + +/* + * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package org.opensearch.commons.destination.response; + +import java.io.IOException; + +import org.opensearch.common.io.stream.StreamInput; +import org.opensearch.common.io.stream.StreamOutput; + +/** + * This class is a place holder for destination response metadata + */ +public class LegacyDestinationResponse extends LegacyBaseResponse { + + private final String responseContent; + + private LegacyDestinationResponse(final String responseString, final Integer statusCode) { + super(statusCode); + if (responseString == null) { + throw new IllegalArgumentException("Response is missing"); + } + this.responseContent = responseString; + } + + public LegacyDestinationResponse(StreamInput streamInput) throws IOException { + super(streamInput); + this.responseContent = streamInput.readString(); + } + + public static class Builder { + private String responseContent; + private Integer statusCode; + + public LegacyDestinationResponse.Builder withResponseContent(String responseContent) { + this.responseContent = responseContent; + return this; + } + + public LegacyDestinationResponse.Builder withStatusCode(Integer statusCode) { + this.statusCode = statusCode; + return this; + } + + public LegacyDestinationResponse build() { + return new LegacyDestinationResponse(responseContent, statusCode); + } + } + + public String getResponseContent() { + return this.responseContent; + } + + @Override + public void writeTo(StreamOutput streamOutput) throws IOException { + super.writeTo(streamOutput); + streamOutput.writeString(responseContent); + } +} diff --git a/src/main/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterface.kt b/src/main/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterface.kt index 2f043351..c0646d2d 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterface.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterface.kt @@ -31,6 +31,7 @@ import org.opensearch.action.ActionResponse import org.opensearch.client.node.NodeClient import org.opensearch.common.io.stream.Writeable import org.opensearch.commons.ConfigConstants.OPENSEARCH_SECURITY_USER_INFO_THREAD_CONTEXT +import org.opensearch.commons.notifications.NotificationConstants.FEATURE_INDEX_MANAGEMENT import org.opensearch.commons.notifications.action.BaseResponse import org.opensearch.commons.notifications.action.CreateNotificationConfigRequest import org.opensearch.commons.notifications.action.CreateNotificationConfigResponse @@ -44,12 +45,15 @@ import org.opensearch.commons.notifications.action.GetNotificationEventRequest import org.opensearch.commons.notifications.action.GetNotificationEventResponse import org.opensearch.commons.notifications.action.GetPluginFeaturesRequest import org.opensearch.commons.notifications.action.GetPluginFeaturesResponse +import org.opensearch.commons.notifications.action.LegacyPublishNotificationRequest +import org.opensearch.commons.notifications.action.LegacyPublishNotificationResponse import org.opensearch.commons.notifications.action.NotificationsActions.CREATE_NOTIFICATION_CONFIG_ACTION_TYPE import org.opensearch.commons.notifications.action.NotificationsActions.DELETE_NOTIFICATION_CONFIG_ACTION_TYPE import org.opensearch.commons.notifications.action.NotificationsActions.GET_FEATURE_CHANNEL_LIST_ACTION_TYPE import org.opensearch.commons.notifications.action.NotificationsActions.GET_NOTIFICATION_CONFIG_ACTION_TYPE import org.opensearch.commons.notifications.action.NotificationsActions.GET_NOTIFICATION_EVENT_ACTION_TYPE import org.opensearch.commons.notifications.action.NotificationsActions.GET_PLUGIN_FEATURES_ACTION_TYPE +import org.opensearch.commons.notifications.action.NotificationsActions.LEGACY_PUBLISH_NOTIFICATION_ACTION_TYPE import org.opensearch.commons.notifications.action.NotificationsActions.SEND_NOTIFICATION_ACTION_TYPE import org.opensearch.commons.notifications.action.NotificationsActions.UPDATE_NOTIFICATION_CONFIG_ACTION_TYPE import org.opensearch.commons.notifications.action.SendNotificationRequest @@ -217,6 +221,30 @@ object NotificationsPluginInterface { ) } + /** + * Publishes a notification API using the legacy notification implementation. No REST API. + * Internal API only for the Index Management plugin. + * @param client Node client for making transport action + * @param request The legacy publish notification request + * @param listener The listener for getting response + */ + fun publishLegacyNotification( + client: NodeClient, + request: LegacyPublishNotificationRequest, + listener: ActionListener + ) { + if (request.feature != FEATURE_INDEX_MANAGEMENT) { + // Do not change this; do not pass in FEATURE_INDEX_MANAGEMENT if you are not the Index Management plugin. + throw IllegalArgumentException("The publish notification method only supports the Index Management feature.") + } + + client.execute( + LEGACY_PUBLISH_NOTIFICATION_ACTION_TYPE, + request, + wrapActionListener(listener) { response -> recreateObject(response) { LegacyPublishNotificationResponse(it) } } + ) + } + /** * Wrap action listener on concrete response class by a new created one on ActionResponse. * This is required because the response may be loaded by different classloader across plugins. diff --git a/src/main/kotlin/org/opensearch/commons/notifications/action/LegacyPublishNotificationRequest.kt b/src/main/kotlin/org/opensearch/commons/notifications/action/LegacyPublishNotificationRequest.kt new file mode 100644 index 00000000..e5807102 --- /dev/null +++ b/src/main/kotlin/org/opensearch/commons/notifications/action/LegacyPublishNotificationRequest.kt @@ -0,0 +1,82 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + * + * Modifications Copyright OpenSearch Contributors. See + * GitHub history for details. + */ + +package org.opensearch.commons.notifications.action + +import org.opensearch.action.ActionRequest +import org.opensearch.action.ActionRequestValidationException +import org.opensearch.common.io.stream.StreamInput +import org.opensearch.common.io.stream.StreamOutput +import org.opensearch.common.io.stream.Writeable +import org.opensearch.commons.destination.message.LegacyBaseMessage +import org.opensearch.commons.destination.message.LegacyChimeMessage +import org.opensearch.commons.destination.message.LegacyCustomWebhookMessage +import org.opensearch.commons.destination.message.LegacyDestinationType +import org.opensearch.commons.destination.message.LegacySlackMessage +import java.io.IOException + +/** + * Action Request to publish notification. This is a legacy implementation. + * This should not be used going forward, instead use [SendNotificationRequest]. + */ +class LegacyPublishNotificationRequest : ActionRequest { + val baseMessage: LegacyBaseMessage + val feature: String + + companion object { + /** + * reader to create instance of class from writable. + */ + val reader = Writeable.Reader { LegacyPublishNotificationRequest(it) } + } + + /** + * constructor for creating the class + * @param baseMessage the base message to send + * @param feature the feature that is trying to use this request + */ + constructor( + baseMessage: LegacyBaseMessage, + feature: String + ) { + this.baseMessage = baseMessage + this.feature = feature + } + + /** + * {@inheritDoc} + */ + @Throws(IOException::class) + constructor(input: StreamInput) : super(input) { + baseMessage = when (requireNotNull(input.readEnum(LegacyDestinationType::class.java)) { "Destination type cannot be null" }) { + LegacyDestinationType.LEGACY_CHIME -> LegacyChimeMessage(input) + LegacyDestinationType.LEGACY_CUSTOM_WEBHOOK -> LegacyCustomWebhookMessage(input) + LegacyDestinationType.LEGACY_SLACK -> LegacySlackMessage(input) + } + feature = input.readString() + } + + /** + * {@inheritDoc} + */ + @Throws(IOException::class) + override fun writeTo(output: StreamOutput) { + super.writeTo(output) + output.writeEnum(baseMessage.channelType) + baseMessage.writeTo(output) + output.writeString(feature) + } + + /** + * {@inheritDoc} + */ + override fun validate(): ActionRequestValidationException? = null +} diff --git a/src/main/kotlin/org/opensearch/commons/notifications/action/LegacyPublishNotificationResponse.kt b/src/main/kotlin/org/opensearch/commons/notifications/action/LegacyPublishNotificationResponse.kt new file mode 100644 index 00000000..60f68e71 --- /dev/null +++ b/src/main/kotlin/org/opensearch/commons/notifications/action/LegacyPublishNotificationResponse.kt @@ -0,0 +1,63 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + * + * Modifications Copyright OpenSearch Contributors. See + * GitHub history for details. + */ + +package org.opensearch.commons.notifications.action + +import org.opensearch.common.io.stream.StreamInput +import org.opensearch.common.io.stream.StreamOutput +import org.opensearch.common.io.stream.Writeable +import org.opensearch.common.xcontent.ToXContent +import org.opensearch.common.xcontent.XContentBuilder +import org.opensearch.commons.destination.response.LegacyDestinationResponse +import java.io.IOException + +/** + * Action Response for legacy publish notification. + */ +class LegacyPublishNotificationResponse : BaseResponse { + val destinationResponse: LegacyDestinationResponse + + companion object { + /** + * reader to create instance of class from writable. + */ + val reader = Writeable.Reader { LegacyPublishNotificationResponse(it) } + } + + /** + * constructor for creating the class + * @param destinationResponse the response of the published notification + */ + constructor(destinationResponse: LegacyDestinationResponse) { + this.destinationResponse = destinationResponse + } + + /** + * {@inheritDoc} + */ + @Throws(IOException::class) + constructor(input: StreamInput) : super(input) { + destinationResponse = LegacyDestinationResponse(input) + } + + /** + * {@inheritDoc} + */ + @Throws(IOException::class) + override fun writeTo(output: StreamOutput) { + destinationResponse.writeTo(output) + } + + // This class is only used across transport wire and does not need to implement toXContent + override fun toXContent(builder: XContentBuilder, params: ToXContent.Params): XContentBuilder { + throw IllegalStateException("Legacy notification response is not intended for REST or persistence and does not support XContent.") + } +} diff --git a/src/main/kotlin/org/opensearch/commons/notifications/action/NotificationsActions.kt b/src/main/kotlin/org/opensearch/commons/notifications/action/NotificationsActions.kt index fe7457d0..d93dd29a 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/action/NotificationsActions.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/action/NotificationsActions.kt @@ -72,6 +72,12 @@ object NotificationsActions { */ const val SEND_NOTIFICATION_NAME = "cluster:admin/opensearch/notifications/feature/send" + /** + * Publish legacy notification message. Internal only - Inter plugin communication. + * Only for the Index Management plugin. + */ + const val LEGACY_PUBLISH_NOTIFICATION_NAME = "cluster:admin/opensearch/notifications/feature/publish" + /** * Create notification configuration transport action type. */ @@ -119,4 +125,11 @@ object NotificationsActions { */ val SEND_NOTIFICATION_ACTION_TYPE = ActionType(SEND_NOTIFICATION_NAME, ::SendNotificationResponse) + + /** + * Send legacy notification transport action type. Internal only - Inter plugin communication. + * Only for the Index Management plugin. + */ + val LEGACY_PUBLISH_NOTIFICATION_ACTION_TYPE = + ActionType(LEGACY_PUBLISH_NOTIFICATION_NAME, ::LegacyPublishNotificationResponse) } diff --git a/src/test/java/org/opensearch/commons/destination/message/LegacyChimeMessageTest.java b/src/test/java/org/opensearch/commons/destination/message/LegacyChimeMessageTest.java new file mode 100644 index 00000000..4477789e --- /dev/null +++ b/src/test/java/org/opensearch/commons/destination/message/LegacyChimeMessageTest.java @@ -0,0 +1,100 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + * + * Modifications Copyright OpenSearch Contributors. See + * GitHub history for details. + */ + +/* + * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package org.opensearch.commons.destination.message; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.fail; + +import java.io.IOException; + +import org.junit.jupiter.api.Test; +import org.opensearch.common.io.stream.BytesStreamOutput; +import org.opensearch.common.io.stream.StreamInput; + +public class LegacyChimeMessageTest { + + @Test + public void testBuildingLegacyChimeMessage() { + LegacyChimeMessage message = new LegacyChimeMessage.Builder("custom_webhook") + .withMessage("Hello world") + .withUrl("https://amazon.com") + .build(); + + assertEquals("custom_webhook", message.destinationName); + assertEquals(LegacyDestinationType.LEGACY_CHIME, message.getChannelType()); + assertEquals("Hello world", message.getMessageContent()); + assertEquals("https://amazon.com", message.url); + } + + @Test + public void testRoundTrippingLegacyChimeMessage() throws IOException { + LegacyChimeMessage message = new LegacyChimeMessage.Builder("custom_webhook") + .withMessage("Hello world") + .withUrl("https://amazon.com") + .build(); + BytesStreamOutput out = new BytesStreamOutput(); + message.writeTo(out); + + StreamInput in = StreamInput.wrap(out.bytes().toBytesRef().bytes); + LegacyChimeMessage newMessage = new LegacyChimeMessage(in); + + assertEquals(newMessage.destinationName, message.destinationName); + assertEquals(newMessage.getChannelType(), message.getChannelType()); + assertEquals(newMessage.getMessageContent(), message.getMessageContent()); + assertEquals(newMessage.url, message.url); + } + + @Test + public void testContentMissingMessage() { + try { + new LegacyChimeMessage.Builder("custom_webhook").withUrl("https://amazon.com").build(); + fail("Building legacy chime message without message should fail"); + } catch (IllegalArgumentException e) { + assertEquals("Message content is missing", e.getMessage()); + } + } + + @Test + public void testUrlMissingMessage() { + try { + new LegacyChimeMessage.Builder("custom_webhook").withMessage("Hello world").build(); + fail("Building legacy chime message without url should fail"); + } catch (IllegalArgumentException e) { + assertEquals("url is invalid or empty", e.getMessage()); + } + } + + @Test + public void testMissingDestinationName() { + try { + new LegacyChimeMessage.Builder(null).withMessage("Hello world").withUrl("https://amazon.com").build(); + fail("Building legacy chime message with null destination name should fail"); + } catch (IllegalArgumentException e) { + assertEquals("Channel name must be defined", e.getMessage()); + } + } +} diff --git a/src/test/java/org/opensearch/commons/destination/message/LegacyCustomWebhookMessageTest.java b/src/test/java/org/opensearch/commons/destination/message/LegacyCustomWebhookMessageTest.java new file mode 100644 index 00000000..fba614fd --- /dev/null +++ b/src/test/java/org/opensearch/commons/destination/message/LegacyCustomWebhookMessageTest.java @@ -0,0 +1,177 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + * + * Modifications Copyright OpenSearch Contributors. See + * GitHub history for details. + */ + +/* + * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package org.opensearch.commons.destination.message; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.fail; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpPost; +import org.junit.jupiter.api.Test; +import org.opensearch.common.io.stream.BytesStreamOutput; +import org.opensearch.common.io.stream.StreamInput; + +public class LegacyCustomWebhookMessageTest { + + @Test + public void testBuildingLegacyCustomWebhookMessage() { + LegacyCustomWebhookMessage message = new LegacyCustomWebhookMessage.Builder("custom_webhook") + .withMessage("Hello world") + .withUrl("https://amazon.com") + .build(); + + assertEquals("custom_webhook", message.destinationName); + assertEquals(LegacyDestinationType.LEGACY_CUSTOM_WEBHOOK, message.getChannelType()); + assertEquals("Hello world", message.getMessageContent()); + assertEquals("https://amazon.com", message.getUrl()); + } + + @Test + public void testRoundTrippingLegacyCustomWebhookMessageWithUrl() throws IOException { + LegacyCustomWebhookMessage message = new LegacyCustomWebhookMessage.Builder("custom_webhook") + .withMessage("Hello world") + .withUrl("https://amazon.com") + .build(); + BytesStreamOutput out = new BytesStreamOutput(); + message.writeTo(out); + + StreamInput in = StreamInput.wrap(out.bytes().toBytesRef().bytes); + LegacyCustomWebhookMessage newMessage = new LegacyCustomWebhookMessage(in); + + assertEquals(newMessage.destinationName, message.destinationName); + assertEquals(newMessage.getChannelType(), message.getChannelType()); + assertEquals(newMessage.getMessageContent(), message.getMessageContent()); + assertEquals(newMessage.getUrl(), message.getUrl()); + } + + @Test + public void testRoundTrippingLegacyCustomWebhookMessageWithHostFails() throws IOException { + Map queryParams = new HashMap(); + queryParams.put("token", "sometoken"); + Map headers = new HashMap(); + headers.put("x-token", "sometoken"); + LegacyCustomWebhookMessage message = new LegacyCustomWebhookMessage.Builder("custom_webhook") + .withMessage("Hello world") + .withHost("hooks.chime.aws") + .withPath("incomingwebhooks/abc") + .withMethod(HttpPost.METHOD_NAME) + .withQueryParams(queryParams) + .withHeaderParams(headers) + .withPort(8000) + .withScheme("https") + .build(); + BytesStreamOutput out = new BytesStreamOutput(); + try { + message.writeTo(out); + fail("Writing LegacyCustomWebhookMessage with host instead of url to stream output should fail"); + } catch (IllegalStateException e) { + assertEquals("Cannot use LegacyCustomWebhookMessage across transport wire without defining full url.", e.getMessage()); + } + } + + @Test + public void testContentMissingMessage() { + try { + new LegacyCustomWebhookMessage.Builder("custom_webhook").withUrl("https://amazon.com").build(); + fail("Building legacy custom webhook message without message should fail"); + } catch (IllegalArgumentException e) { + assertEquals("Message content is missing", e.getMessage()); + } + } + + @Test + public void testMissingDestinationName() { + try { + new LegacyCustomWebhookMessage.Builder(null).withMessage("Hello world").withUrl("https://amazon.com").build(); + fail("Building legacy custom webhook message with null destination name should fail"); + } catch (IllegalArgumentException e) { + assertEquals("Channel name must be defined", e.getMessage()); + } + } + + @Test + public void testUnsupportedHttpMethods() { + try { + new LegacyCustomWebhookMessage.Builder("custom_webhook") + .withMessage("Hello world") + .withUrl("https://amazon.com") + .withMethod(HttpGet.METHOD_NAME) + .build(); + fail("Building legacy custom webhook message with unsupported http methods should fail"); + } catch (IllegalArgumentException e) { + assertEquals("Invalid method supplied. Only POST, PUT and PATCH are allowed", e.getMessage()); + } + } + + @Test + public void testURLandHostNameMissingOrEmpty() { + try { + new LegacyCustomWebhookMessage.Builder("custom_webhook").withMessage("Hello world").withMethod(HttpGet.METHOD_NAME).build(); + fail("Building legacy custom webhook message missing or empty url and host name should fail"); + } catch (IllegalArgumentException e) { + assertEquals("Either fully qualified URL or host name should be provided", e.getMessage()); + } + + try { + new LegacyCustomWebhookMessage.Builder("custom_webhook") + .withMessage("Hello world") + .withUrl("") + .withMethod(HttpGet.METHOD_NAME) + .build(); + fail("Building legacy custom webhook message with missing or empty url and host name should fail"); + } catch (IllegalArgumentException e) { + assertEquals("Either fully qualified URL or host name should be provided", e.getMessage()); + } + + try { + new LegacyCustomWebhookMessage.Builder("custom_webhook") + .withMessage("Hello world") + .withHost("") + .withMethod(HttpGet.METHOD_NAME) + .build(); + fail("Building legacy custom webhook message with missing or empty url and host name should fail"); + } catch (IllegalArgumentException e) { + assertEquals("Either fully qualified URL or host name should be provided", e.getMessage()); + } + + try { + new LegacyCustomWebhookMessage.Builder("custom_webhook") + .withMessage("Hello world") + .withUrl("") + .withHost("") + .withMethod(HttpGet.METHOD_NAME) + .build(); + fail("Building legacy custom webhook message with missing or empty url and host name should fail"); + } catch (IllegalArgumentException e) { + assertEquals("Either fully qualified URL or host name should be provided", e.getMessage()); + } + } +} diff --git a/src/test/java/org/opensearch/commons/destination/message/LegacySlackMessageTest.java b/src/test/java/org/opensearch/commons/destination/message/LegacySlackMessageTest.java new file mode 100644 index 00000000..a520fc8e --- /dev/null +++ b/src/test/java/org/opensearch/commons/destination/message/LegacySlackMessageTest.java @@ -0,0 +1,110 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + * + * Modifications Copyright OpenSearch Contributors. See + * GitHub history for details. + */ + +/* + * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package org.opensearch.commons.destination.message; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.fail; + +import java.io.IOException; + +import org.junit.jupiter.api.Test; +import org.opensearch.common.io.stream.BytesStreamOutput; +import org.opensearch.common.io.stream.StreamInput; + +public class LegacySlackMessageTest { + + @Test + public void testBuildingLegacySlackMessage() { + LegacySlackMessage message = new LegacySlackMessage.Builder("custom_webhook") + .withMessage("Hello world") + .withUrl("https://amazon.com") + .build(); + + assertEquals("custom_webhook", message.destinationName); + assertEquals(LegacyDestinationType.LEGACY_SLACK, message.getChannelType()); + assertEquals("Hello world", message.getMessageContent()); + assertEquals("https://amazon.com", message.url); + } + + @Test + public void testRoundTrippingLegacySlackMessage() throws IOException { + LegacySlackMessage message = new LegacySlackMessage.Builder("custom_webhook") + .withMessage("Hello world") + .withUrl("https://amazon.com") + .build(); + BytesStreamOutput out = new BytesStreamOutput(); + message.writeTo(out); + + StreamInput in = StreamInput.wrap(out.bytes().toBytesRef().bytes); + LegacySlackMessage newMessage = new LegacySlackMessage(in); + + assertEquals(newMessage.destinationName, message.destinationName); + assertEquals(newMessage.getChannelType(), message.getChannelType()); + assertEquals(newMessage.getMessageContent(), message.getMessageContent()); + assertEquals(newMessage.url, message.url); + } + + @Test + public void testContentMissingMessage() { + try { + new LegacySlackMessage.Builder("custom_webhook").withUrl("https://amazon.com").build(); + fail("Building legacy slack message without message should fail"); + } catch (IllegalArgumentException e) { + assertEquals("Message content is missing", e.getMessage()); + } + } + + @Test + public void testUrlMissingMessage() { + try { + new LegacySlackMessage.Builder("custom_webhook").withMessage("Hello world").build(); + fail("Building legacy slack message without url should fail"); + } catch (IllegalArgumentException e) { + assertEquals("url is invalid or empty", e.getMessage()); + } + } + + @Test + public void testMissingDestinationName() { + try { + new LegacySlackMessage.Builder(null).withMessage("Hello world").withUrl("https://amazon.com").build(); + fail("Building legacy slack message with null destination name should fail"); + } catch (IllegalArgumentException e) { + assertEquals("Channel name must be defined", e.getMessage()); + } + } + + @Test + public void testUrlEmptyMessage() { + try { + new LegacySlackMessage.Builder("custom_webhook").withMessage("Hello world").withUrl("").build(); + fail("Building legacy slack message with empty url should fail"); + } catch (IllegalArgumentException e) { + assertEquals("Fully qualified URL is missing/invalid: ", e.getMessage()); + } + } +} diff --git a/src/test/java/org/opensearch/commons/destination/response/LegacyDestinationResponseTest.java b/src/test/java/org/opensearch/commons/destination/response/LegacyDestinationResponseTest.java new file mode 100644 index 00000000..6175827e --- /dev/null +++ b/src/test/java/org/opensearch/commons/destination/response/LegacyDestinationResponseTest.java @@ -0,0 +1,82 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + * + * Modifications Copyright OpenSearch Contributors. See + * GitHub history for details. + */ + +/* + * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package org.opensearch.commons.destination.response; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.fail; + +import java.io.IOException; + +import org.junit.jupiter.api.Test; +import org.opensearch.common.io.stream.BytesStreamOutput; +import org.opensearch.common.io.stream.StreamInput; + +public class LegacyDestinationResponseTest { + + @Test + public void testBuildingLegacyDestinationResponse() { + LegacyDestinationResponse res = new LegacyDestinationResponse.Builder() + .withStatusCode(200) + .withResponseContent("Hello world") + .build(); + + assertEquals(200, res.statusCode); + assertEquals("Hello world", res.getResponseContent()); + } + + @Test + public void testRoundTrippingLegacyDestinationResponse() throws IOException { + LegacyDestinationResponse res = new LegacyDestinationResponse.Builder() + .withStatusCode(200) + .withResponseContent("Hello world") + .build(); + BytesStreamOutput out = new BytesStreamOutput(); + res.writeTo(out); + + StreamInput in = StreamInput.wrap(out.bytes().toBytesRef().bytes); + LegacyDestinationResponse newRes = new LegacyDestinationResponse(in); + + assertEquals(res.statusCode, newRes.statusCode, "Round tripping doesn't work"); + assertEquals(res.getResponseContent(), newRes.getResponseContent(), "Round tripping doesn't work"); + } + + @Test + public void testMissingLegacyDestinationResponse() { + try { + new LegacyDestinationResponse.Builder().withStatusCode(200).build(); + fail("Creating LegacyDestinationResponse without response content should fail"); + } catch (IllegalArgumentException ignored) {} + } + + @Test + public void testMissingLegacyDestinationStatusCode() { + try { + new LegacyDestinationResponse.Builder().withResponseContent("Hello world").build(); + fail("Creating LegacyDestinationResponse without status code should fail"); + } catch (IllegalArgumentException ignored) {} + } +} diff --git a/src/test/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterfaceTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterfaceTests.kt index cf4f8420..343fecbd 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterfaceTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterfaceTests.kt @@ -25,7 +25,9 @@ import org.mockito.junit.jupiter.MockitoExtension import org.opensearch.action.ActionListener import org.opensearch.action.ActionType import org.opensearch.client.node.NodeClient +import org.opensearch.commons.destination.response.LegacyDestinationResponse import org.opensearch.commons.notifications.NotificationConstants.FEATURE_ALERTING +import org.opensearch.commons.notifications.NotificationConstants.FEATURE_INDEX_MANAGEMENT import org.opensearch.commons.notifications.NotificationConstants.FEATURE_REPORTS import org.opensearch.commons.notifications.action.CreateNotificationConfigRequest import org.opensearch.commons.notifications.action.CreateNotificationConfigResponse @@ -39,6 +41,8 @@ import org.opensearch.commons.notifications.action.GetNotificationEventRequest import org.opensearch.commons.notifications.action.GetNotificationEventResponse import org.opensearch.commons.notifications.action.GetPluginFeaturesRequest import org.opensearch.commons.notifications.action.GetPluginFeaturesResponse +import org.opensearch.commons.notifications.action.LegacyPublishNotificationRequest +import org.opensearch.commons.notifications.action.LegacyPublishNotificationResponse import org.opensearch.commons.notifications.action.SendNotificationResponse import org.opensearch.commons.notifications.action.UpdateNotificationConfigRequest import org.opensearch.commons.notifications.action.UpdateNotificationConfigResponse @@ -223,6 +227,26 @@ internal class NotificationsPluginInterfaceTests { verify(listener, times(1)).onResponse(eq(response)) } + @Test + fun publishLegacyNotification() { + val request = mock(LegacyPublishNotificationRequest::class.java) + val res = LegacyPublishNotificationResponse(LegacyDestinationResponse.Builder().withStatusCode(200).withResponseContent("Nice!").build()) + val l: ActionListener = + mock(ActionListener::class.java) as ActionListener + + doAnswer { + (it.getArgument(2) as ActionListener) + .onResponse(res) + }.whenever(client).execute(any(ActionType::class.java), any(), any()) + + doAnswer { + FEATURE_INDEX_MANAGEMENT + }.whenever(request).feature + + NotificationsPluginInterface.publishLegacyNotification(client, request, l) + verify(l, times(1)).onResponse(eq(res)) + } + private fun mockGetNotificationConfigResponse(): GetNotificationConfigResponse { val sampleSlack = Slack("https://domain.com/sample_url#1234567890") val sampleConfig = NotificationConfig( diff --git a/src/test/kotlin/org/opensearch/commons/notifications/action/LegacyPublishNotificationRequestTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/action/LegacyPublishNotificationRequestTests.kt new file mode 100644 index 00000000..349a1c14 --- /dev/null +++ b/src/test/kotlin/org/opensearch/commons/notifications/action/LegacyPublishNotificationRequestTests.kt @@ -0,0 +1,42 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + * + * Modifications Copyright OpenSearch Contributors. See + * GitHub history for details. + */ + +package org.opensearch.commons.notifications.action + +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.Assertions.assertNull +import org.junit.jupiter.api.Test +import org.opensearch.commons.destination.message.LegacyChimeMessage +import org.opensearch.commons.notifications.NotificationConstants.FEATURE_INDEX_MANAGEMENT +import org.opensearch.commons.utils.recreateObject + +internal class LegacyPublishNotificationRequestTests { + + private fun assertRequestEquals( + expected: LegacyPublishNotificationRequest, + actual: LegacyPublishNotificationRequest + ) { + assertEquals(expected.baseMessage.channelName, actual.baseMessage.channelName) + assertEquals(expected.baseMessage.channelType, actual.baseMessage.channelType) + assertEquals(expected.baseMessage.messageContent, actual.baseMessage.messageContent) + assertEquals(expected.baseMessage.url, actual.baseMessage.url) + assertEquals(expected.feature, actual.feature) + assertNull(actual.validate()) + } + + @Test + fun `publish request serialize and deserialize transport object should be equal`() { + val baseMessage = LegacyChimeMessage.Builder("chime_message").withMessage("Hello world").withUrl("https://amazon.com").build() + val request = LegacyPublishNotificationRequest(baseMessage, FEATURE_INDEX_MANAGEMENT) + val recreatedObject = recreateObject(request) { LegacyPublishNotificationRequest(it) } + assertRequestEquals(request, recreatedObject) + } +} diff --git a/src/test/kotlin/org/opensearch/commons/notifications/action/LegacyPublishNotificationResponseTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/action/LegacyPublishNotificationResponseTests.kt new file mode 100644 index 00000000..4b6f8e0b --- /dev/null +++ b/src/test/kotlin/org/opensearch/commons/notifications/action/LegacyPublishNotificationResponseTests.kt @@ -0,0 +1,29 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + * + * Modifications Copyright OpenSearch Contributors. See + * GitHub history for details. + */ + +package org.opensearch.commons.notifications.action + +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.Test +import org.opensearch.commons.destination.response.LegacyDestinationResponse +import org.opensearch.commons.utils.recreateObject + +internal class LegacyPublishNotificationResponseTests { + + @Test + fun `Create response serialize and deserialize transport object should be equal`() { + val res = LegacyDestinationResponse.Builder().withStatusCode(200).withResponseContent("Hello world").build() + val configResponse = LegacyPublishNotificationResponse(res) + val recreatedObject = recreateObject(configResponse) { LegacyPublishNotificationResponse(it) } + assertEquals(configResponse.destinationResponse.statusCode, recreatedObject.destinationResponse.statusCode) + assertEquals(configResponse.destinationResponse.responseContent, recreatedObject.destinationResponse.responseContent) + } +} From 401802dddcb9d1d8c3d9700a8e4cdc6d96348814 Mon Sep 17 00:00:00 2001 From: Vacha Date: Mon, 16 Aug 2021 07:36:21 -0700 Subject: [PATCH 010/140] Using 1.1 snapshot version for OpenSearch (#57) Signed-off-by: Vacha --- .github/workflows/ci.yml | 6 +++--- build.gradle | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4f0adf94..1872eb2a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -34,16 +34,16 @@ jobs: ref: 'main' - name: Build OpenSearch working-directory: ./OpenSearch - run: ./gradlew publishToMavenLocal -Dbuild.snapshot=false + run: ./gradlew publishToMavenLocal # common-utils - name: Build and Test run: | - ./gradlew build -Dopensearch.version=1.1.0 + ./gradlew build -Dopensearch.version=1.1.0-SNAPSHOT - name: Publish to Maven Local run: | - ./gradlew publishToMavenLocal -Dopensearch.version=1.1.0 + ./gradlew publishToMavenLocal -Dopensearch.version=1.1.0-SNAPSHOT - name: Upload Coverage Report uses: codecov/codecov-action@v1 diff --git a/build.gradle b/build.gradle index 0f2b241a..4917e428 100644 --- a/build.gradle +++ b/build.gradle @@ -12,7 +12,7 @@ buildscript { ext { opensearch_group = "org.opensearch" - opensearch_version = System.getProperty("opensearch.version", "1.1.0") + opensearch_version = System.getProperty("opensearch.version", "1.1.0-SNAPSHOT") kotlin_version = System.getProperty("kotlin.version", "1.4.32") } From 4f30425431751239f318e89722672f81f5bf3457 Mon Sep 17 00:00:00 2001 From: Miki Date: Mon, 16 Aug 2021 07:42:06 -0700 Subject: [PATCH 011/140] Add themed logo to README (#41) Signed-off-by: Miki --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 237509c1..b2778b5d 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ - + - [OpenSearch Common Utils](#opensearch-common-utils) - [Contributing](#contributing) From cc02f237de3ef45c3f7dc0bf526556d09bbaba97 Mon Sep 17 00:00:00 2001 From: "Daniel Doubrovkine (dB.)" Date: Mon, 16 Aug 2021 11:25:48 -0400 Subject: [PATCH 012/140] Build snapshot build by default with the same version as OpenSearch. (#58) Signed-off-by: dblock --- .github/workflows/ci.yml | 2 +- build.gradle | 14 +++++++++++--- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1872eb2a..53c3d9b6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -31,7 +31,7 @@ jobs: with: repository: 'opensearch-project/OpenSearch' path: OpenSearch - ref: 'main' + ref: '1.x' - name: Build OpenSearch working-directory: ./OpenSearch run: ./gradlew publishToMavenLocal diff --git a/build.gradle b/build.gradle index 4917e428..d443ddf4 100644 --- a/build.gradle +++ b/build.gradle @@ -44,7 +44,17 @@ repositories { jcenter() } -group 'org.opensearch.commons' +ext { + isSnapshot = "true" == System.getProperty("build.snapshot", "true") +} + +allprojects { + group 'org.opensearch.commons' + version = opensearch_version - '-SNAPSHOT' + '.0' + if (isSnapshot) { + version += "-SNAPSHOT" + } +} sourceCompatibility = 1.8 @@ -146,8 +156,6 @@ task javadocJar(type: Jar) { from javadoc.destinationDir } -version '1.1.0.0' - publishing { publications { shadow(MavenPublication) { From 3913d7097934cbfe1fdcf919347f22a597d00b76 Mon Sep 17 00:00:00 2001 From: Anantha Krishna Bhatta <31894175+akbhatta@users.noreply.github.com> Date: Mon, 16 Aug 2021 15:49:54 -0700 Subject: [PATCH 013/140] BugFix: Allow null values for role_arn in json parsing (#60) Signed-off-by: @akbhatta --- .../commons/notifications/model/SesAccount.kt | 5 +-- .../notifications/model/SesAccountTests.kt | 35 +++++++++++++++++++ 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/SesAccount.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/SesAccount.kt index d529b407..aa9aca26 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/SesAccount.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/SesAccount.kt @@ -22,6 +22,7 @@ import org.opensearch.common.xcontent.XContentParserUtils import org.opensearch.commons.notifications.NotificationConstants.FROM_ADDRESS_TAG import org.opensearch.commons.notifications.NotificationConstants.REGION_TAG import org.opensearch.commons.notifications.NotificationConstants.ROLE_ARN_TAG +import org.opensearch.commons.utils.fieldIfNotNull import org.opensearch.commons.utils.logger import org.opensearch.commons.utils.validateEmail import org.opensearch.commons.utils.validateIamRoleArn @@ -74,7 +75,7 @@ data class SesAccount( parser.nextToken() when (fieldName) { REGION_TAG -> awsRegion = parser.text() - ROLE_ARN_TAG -> roleArn = parser.text() + ROLE_ARN_TAG -> roleArn = parser.textOrNull() FROM_ADDRESS_TAG -> fromAddress = parser.text() else -> { parser.skipChildren() @@ -98,7 +99,7 @@ data class SesAccount( override fun toXContent(builder: XContentBuilder?, params: ToXContent.Params?): XContentBuilder { return builder!!.startObject() .field(REGION_TAG, awsRegion) - .field(ROLE_ARN_TAG, roleArn) + .fieldIfNotNull(ROLE_ARN_TAG, roleArn) .field(FROM_ADDRESS_TAG, fromAddress) .endObject() } diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/SesAccountTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/SesAccountTests.kt index c99506fd..e999e534 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/SesAccountTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/SesAccountTests.kt @@ -82,6 +82,14 @@ internal class SesAccountTests { assertEquals(sesAccount, recreatedObject) } + @Test + fun `SES serialize and deserialize using json object should be equal with null roleArn`() { + val sesAccount = SesAccount("us-east-1", null, "from@domain.com") + val jsonString = getJsonString(sesAccount) + val recreatedObject = createObjectFromJsonString(jsonString) { SesAccount.parse(it) } + assertEquals(sesAccount, recreatedObject) + } + @Test fun `SES should deserialize json object using parser`() { val sesAccount = SesAccount("us-east-1", "arn:aws:iam::012345678912:role/iam-test", "from@domain.com") @@ -96,6 +104,33 @@ internal class SesAccountTests { assertEquals(sesAccount, recreatedObject) } + @Test + fun `SES should deserialize json object will null role_arn using parser`() { + val sesAccount = SesAccount("us-east-1", null, "from@domain.com") + val jsonString = """ + { + "region":"${sesAccount.awsRegion}", + "role_arn":null, + "from_address":"${sesAccount.fromAddress}" + } + """.trimIndent() + val recreatedObject = createObjectFromJsonString(jsonString) { SesAccount.parse(it) } + assertEquals(sesAccount, recreatedObject) + } + + @Test + fun `SES should deserialize json object will missing role_arn using parser`() { + val sesAccount = SesAccount("us-east-1", null, "from@domain.com") + val jsonString = """ + { + "region":"${sesAccount.awsRegion}", + "from_address":"${sesAccount.fromAddress}" + } + """.trimIndent() + val recreatedObject = createObjectFromJsonString(jsonString) { SesAccount.parse(it) } + assertEquals(sesAccount, recreatedObject) + } + @Test fun `SES should throw exception when invalid json object is passed`() { val jsonString = "sample message" From 8fccbea9867e7d185ad46eccd7d3d2c0f5d14225 Mon Sep 17 00:00:00 2001 From: Anantha Krishna Bhatta <31894175+akbhatta@users.noreply.github.com> Date: Fri, 17 Sep 2021 11:34:55 -0700 Subject: [PATCH 014/140] Removed tenant information from the models (#73) * Removed tenant information from the models [Tests] Updated unit tests Signed-off-by: @akbhatta * Updated OpenSearch branch to 1.1 Signed-off-by: @akbhatta --- .github/workflows/ci.yml | 2 +- .../notifications/NotificationConstants.kt | 1 - .../action/GetFeatureChannelListRequest.kt | 3 - .../model/NotificationConfigInfo.kt | 9 --- .../model/NotificationEventInfo.kt | 9 --- .../NotificationsPluginInterfaceTests.kt | 2 - .../GetNotificationConfigResponseTests.kt | 13 +--- .../GetNotificationEventResponseTests.kt | 15 +---- .../model/NotificationConfigInfoTests.kt | 50 +------------- .../NotificationConfigSearchResultsTests.kt | 15 +---- .../model/NotificationEventInfoTests.kt | 67 +------------------ .../NotificationEventSearchResultTests.kt | 19 +----- 12 files changed, 7 insertions(+), 198 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 53c3d9b6..8f83153e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -31,7 +31,7 @@ jobs: with: repository: 'opensearch-project/OpenSearch' path: OpenSearch - ref: '1.x' + ref: '1.1' - name: Build OpenSearch working-directory: ./OpenSearch run: ./gradlew publishToMavenLocal diff --git a/src/main/kotlin/org/opensearch/commons/notifications/NotificationConstants.kt b/src/main/kotlin/org/opensearch/commons/notifications/NotificationConstants.kt index 55dc9a44..dc16a39f 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/NotificationConstants.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/NotificationConstants.kt @@ -51,7 +51,6 @@ object NotificationConstants { const val FROM_ADDRESS_TAG = "from_address" const val UPDATED_TIME_TAG = "last_updated_time_ms" const val CREATED_TIME_TAG = "created_time_ms" - const val TENANT_TAG = "tenant" const val CONFIG_LIST_TAG = "config_list" const val EVENT_LIST_TAG = "event_list" const val FEATURE_CONFIG_LIST_TAG = "feature_channel_list" diff --git a/src/main/kotlin/org/opensearch/commons/notifications/action/GetFeatureChannelListRequest.kt b/src/main/kotlin/org/opensearch/commons/notifications/action/GetFeatureChannelListRequest.kt index 309a31bc..ba6e3b19 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/action/GetFeatureChannelListRequest.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/action/GetFeatureChannelListRequest.kt @@ -42,9 +42,6 @@ import java.io.IOException /** * This request is plugin-only call. i.e. REST interface is not exposed. - * Also the library will remove the user context while making this call - * so that user making this call need not have to set permission to this API. - * Hence the request also contains tenant info for space isolation. */ class GetFeatureChannelListRequest : ActionRequest, ToXContentObject { val feature: String diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationConfigInfo.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationConfigInfo.kt index 7a949bbb..3c17a28c 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationConfigInfo.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationConfigInfo.kt @@ -37,7 +37,6 @@ import org.opensearch.common.xcontent.XContentParserUtils import org.opensearch.commons.notifications.NotificationConstants.CONFIG_ID_TAG import org.opensearch.commons.notifications.NotificationConstants.CONFIG_TAG import org.opensearch.commons.notifications.NotificationConstants.CREATED_TIME_TAG -import org.opensearch.commons.notifications.NotificationConstants.TENANT_TAG import org.opensearch.commons.notifications.NotificationConstants.UPDATED_TIME_TAG import org.opensearch.commons.utils.logger import java.io.IOException @@ -50,7 +49,6 @@ data class NotificationConfigInfo( val configId: String, val lastUpdatedTime: Instant, val createdTime: Instant, - val tenant: String, val notificationConfig: NotificationConfig ) : BaseModel { @@ -76,7 +74,6 @@ data class NotificationConfigInfo( var configId: String? = null var lastUpdatedTime: Instant? = null var createdTime: Instant? = null - var tenant: String? = null var notificationConfig: NotificationConfig? = null XContentParserUtils.ensureExpectedToken( @@ -91,7 +88,6 @@ data class NotificationConfigInfo( CONFIG_ID_TAG -> configId = parser.text() UPDATED_TIME_TAG -> lastUpdatedTime = Instant.ofEpochMilli(parser.longValue()) CREATED_TIME_TAG -> createdTime = Instant.ofEpochMilli(parser.longValue()) - TENANT_TAG -> tenant = parser.text() CONFIG_TAG -> notificationConfig = NotificationConfig.parse(parser) else -> { parser.skipChildren() @@ -102,13 +98,11 @@ data class NotificationConfigInfo( configId ?: throw IllegalArgumentException("$CONFIG_ID_TAG field absent") lastUpdatedTime ?: throw IllegalArgumentException("$UPDATED_TIME_TAG field absent") createdTime ?: throw IllegalArgumentException("$CREATED_TIME_TAG field absent") - tenant = tenant ?: "" notificationConfig ?: throw IllegalArgumentException("$CONFIG_TAG field absent") return NotificationConfigInfo( configId, lastUpdatedTime, createdTime, - tenant, notificationConfig ) } @@ -122,7 +116,6 @@ data class NotificationConfigInfo( configId = input.readString(), lastUpdatedTime = input.readInstant(), createdTime = input.readInstant(), - tenant = input.readString(), notificationConfig = NotificationConfig.reader.read(input) ) @@ -133,7 +126,6 @@ data class NotificationConfigInfo( output.writeString(configId) output.writeInstant(lastUpdatedTime) output.writeInstant(createdTime) - output.writeString(tenant) notificationConfig.writeTo(output) } @@ -146,7 +138,6 @@ data class NotificationConfigInfo( .field(CONFIG_ID_TAG, configId) .field(UPDATED_TIME_TAG, lastUpdatedTime.toEpochMilli()) .field(CREATED_TIME_TAG, createdTime.toEpochMilli()) - .field(TENANT_TAG, tenant) .field(CONFIG_TAG, notificationConfig) .endObject() } diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationEventInfo.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationEventInfo.kt index 27f9d0ad..3e4ff552 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationEventInfo.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationEventInfo.kt @@ -37,7 +37,6 @@ import org.opensearch.common.xcontent.XContentParserUtils import org.opensearch.commons.notifications.NotificationConstants.CREATED_TIME_TAG import org.opensearch.commons.notifications.NotificationConstants.EVENT_ID_TAG import org.opensearch.commons.notifications.NotificationConstants.EVENT_TAG -import org.opensearch.commons.notifications.NotificationConstants.TENANT_TAG import org.opensearch.commons.notifications.NotificationConstants.UPDATED_TIME_TAG import org.opensearch.commons.utils.logger import java.io.IOException @@ -50,7 +49,6 @@ data class NotificationEventInfo( val eventId: String, val lastUpdatedTime: Instant, val createdTime: Instant, - val tenant: String, val notificationEvent: NotificationEvent ) : BaseModel { @@ -76,7 +74,6 @@ data class NotificationEventInfo( var eventId: String? = null var lastUpdatedTime: Instant? = null var createdTime: Instant? = null - var tenant: String? = null var notificationEvent: NotificationEvent? = null XContentParserUtils.ensureExpectedToken( @@ -91,7 +88,6 @@ data class NotificationEventInfo( EVENT_ID_TAG -> eventId = parser.text() UPDATED_TIME_TAG -> lastUpdatedTime = Instant.ofEpochMilli(parser.longValue()) CREATED_TIME_TAG -> createdTime = Instant.ofEpochMilli(parser.longValue()) - TENANT_TAG -> tenant = parser.text() EVENT_TAG -> notificationEvent = NotificationEvent.parse(parser) else -> { parser.skipChildren() @@ -102,13 +98,11 @@ data class NotificationEventInfo( eventId ?: throw IllegalArgumentException("$EVENT_ID_TAG field absent") lastUpdatedTime ?: throw IllegalArgumentException("$UPDATED_TIME_TAG field absent") createdTime ?: throw IllegalArgumentException("$CREATED_TIME_TAG field absent") - tenant = tenant ?: "" notificationEvent ?: throw IllegalArgumentException("$EVENT_TAG field absent") return NotificationEventInfo( eventId, lastUpdatedTime, createdTime, - tenant, notificationEvent ) } @@ -123,7 +117,6 @@ data class NotificationEventInfo( .field(EVENT_ID_TAG, eventId) .field(UPDATED_TIME_TAG, lastUpdatedTime.toEpochMilli()) .field(CREATED_TIME_TAG, createdTime.toEpochMilli()) - .field(TENANT_TAG, tenant) .field(EVENT_TAG, notificationEvent) .endObject() } @@ -136,7 +129,6 @@ data class NotificationEventInfo( eventId = input.readString(), lastUpdatedTime = input.readInstant(), createdTime = input.readInstant(), - tenant = input.readString(), notificationEvent = NotificationEvent.reader.read(input) ) @@ -147,7 +139,6 @@ data class NotificationEventInfo( output.writeString(eventId) output.writeInstant(lastUpdatedTime) output.writeInstant(createdTime) - output.writeString(tenant) notificationEvent.writeTo(output) } } diff --git a/src/test/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterfaceTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterfaceTests.kt index 343fecbd..77d12ff2 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterfaceTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterfaceTests.kt @@ -260,7 +260,6 @@ internal class NotificationsPluginInterfaceTests { "config_id", Instant.now(), Instant.now(), - "tenant", sampleConfig ) return GetNotificationConfigResponse(NotificationConfigSearchResult(configInfo)) @@ -284,7 +283,6 @@ internal class NotificationsPluginInterfaceTests { "event_id", Instant.now(), Instant.now(), - "tenant", sampleEvent ) return GetNotificationEventResponse(NotificationEventSearchResult(eventInfo)) diff --git a/src/test/kotlin/org/opensearch/commons/notifications/action/GetNotificationConfigResponseTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/action/GetNotificationConfigResponseTests.kt index 2ec08913..8cc66d80 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/action/GetNotificationConfigResponseTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/action/GetNotificationConfigResponseTests.kt @@ -70,7 +70,6 @@ internal class GetNotificationConfigResponseTests { "config_id", Instant.now(), Instant.now(), - "tenant", sampleConfig ) val searchResult = NotificationConfigSearchResult(configInfo) @@ -92,7 +91,6 @@ internal class GetNotificationConfigResponseTests { "config_id1", Instant.now(), Instant.now(), - "tenant", sampleConfig1 ) val sampleConfig2 = NotificationConfig( @@ -106,7 +104,6 @@ internal class GetNotificationConfigResponseTests { "config_id2", Instant.now(), Instant.now(), - "tenant", sampleConfig2 ) val searchResult = NotificationConfigSearchResult( @@ -136,7 +133,6 @@ internal class GetNotificationConfigResponseTests { "config_id", lastUpdatedTimeMs, createdTimeMs, - "tenant", sampleConfig ) val searchResult = NotificationConfigSearchResult(configInfo) @@ -161,7 +157,6 @@ internal class GetNotificationConfigResponseTests { "config_id1", lastUpdatedTimeMs, createdTimeMs, - "tenant", sampleConfig1 ) val sampleConfig2 = NotificationConfig( @@ -175,7 +170,6 @@ internal class GetNotificationConfigResponseTests { "config_id2", lastUpdatedTimeMs, createdTimeMs, - "tenant", sampleConfig2 ) val searchResult = NotificationConfigSearchResult( @@ -207,7 +201,6 @@ internal class GetNotificationConfigResponseTests { "config-Id", lastUpdatedTimeMs, createdTimeMs, - "selectedTenant", sampleConfig ) val searchResult = NotificationConfigSearchResult(configInfo) @@ -221,7 +214,6 @@ internal class GetNotificationConfigResponseTests { "config_id":"config-Id", "last_updated_time_ms":"${lastUpdatedTimeMs.toEpochMilli()}", "created_time_ms":"${createdTimeMs.toEpochMilli()}", - "tenant":"selectedTenant", "config":{ "name":"name", "description":"description", @@ -258,7 +250,6 @@ internal class GetNotificationConfigResponseTests { "config-Id", lastUpdatedTimeMs, createdTimeMs, - "selectedTenant", sampleConfig ) val searchResult = NotificationConfigSearchResult(configInfo) @@ -269,7 +260,6 @@ internal class GetNotificationConfigResponseTests { "config_id":"config-Id", "last_updated_time_ms":"${lastUpdatedTimeMs.toEpochMilli()}", "created_time_ms":"${createdTimeMs.toEpochMilli()}", - "tenant":"selectedTenant", "config":{ "name":"name", "description":"description", @@ -299,8 +289,7 @@ internal class GetNotificationConfigResponseTests { { "config_id":"config-Id", "last_updated_time_ms":"${lastUpdatedTimeMs.toEpochMilli()}", - "created_time_ms":"${createdTimeMs.toEpochMilli()}", - "tenant":"selectedTenant" + "created_time_ms":"${createdTimeMs.toEpochMilli()}" } ] } diff --git a/src/test/kotlin/org/opensearch/commons/notifications/action/GetNotificationEventResponseTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/action/GetNotificationEventResponseTests.kt index 1895d1d3..be6af960 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/action/GetNotificationEventResponseTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/action/GetNotificationEventResponseTests.kt @@ -77,7 +77,6 @@ internal class GetNotificationEventResponseTests { "event_id", Instant.now(), Instant.now(), - "tenant", sampleEvent ) val searchResult = NotificationEventSearchResult(eventInfo) @@ -116,28 +115,24 @@ internal class GetNotificationEventResponseTests { "event_id1", Instant.now(), Instant.now(), - "tenant", NotificationEvent(eventSource1, listOf(status1)) ) val eventInfo2 = NotificationEventInfo( "event_id2", Instant.now(), Instant.now(), - "tenant", NotificationEvent(eventSource2, listOf(status2)) ) val eventInfo3 = NotificationEventInfo( "event_id3", Instant.now(), Instant.now(), - "tenant", NotificationEvent(eventSource1, listOf(status1, status2)) ) val eventInfo4 = NotificationEventInfo( "event_id4", Instant.now(), Instant.now(), - "tenant", NotificationEvent(eventSource2, listOf(status1, status2)) ) val searchResult = NotificationEventSearchResult( @@ -172,7 +167,6 @@ internal class GetNotificationEventResponseTests { "event_id", lastUpdatedTimeMs, createdTimeMs, - "tenant", sampleEvent ) val searchResult = NotificationEventSearchResult(eventInfo) @@ -214,14 +208,12 @@ internal class GetNotificationEventResponseTests { "event_id1", lastUpdatedTimeMs, createdTimeMs, - "tenant", NotificationEvent(eventSource1, listOf(status1)) ) val eventInfo2 = NotificationEventInfo( "event_id2", lastUpdatedTimeMs, createdTimeMs, - "tenant", NotificationEvent(eventSource2, listOf(status2)) ) val searchResult = NotificationEventSearchResult( @@ -257,7 +249,6 @@ internal class GetNotificationEventResponseTests { "event_id", lastUpdatedTimeMs, createdTimeMs, - "selectedTenant", sampleEvent ) val searchResult = NotificationEventSearchResult(eventInfo) @@ -271,7 +262,6 @@ internal class GetNotificationEventResponseTests { "event_id":"event_id", "last_updated_time_ms":"${lastUpdatedTimeMs.toEpochMilli()}", "created_time_ms":"${createdTimeMs.toEpochMilli()}", - "tenant":"selectedTenant", "event":{ "event_source":{ "title":"title", @@ -325,7 +315,6 @@ internal class GetNotificationEventResponseTests { "event_id", lastUpdatedTimeMs, createdTimeMs, - "selectedTenant", sampleEvent ) val searchResult = NotificationEventSearchResult(eventInfo) @@ -336,7 +325,6 @@ internal class GetNotificationEventResponseTests { "event_id":"event_id", "last_updated_time_ms":"${lastUpdatedTimeMs.toEpochMilli()}", "created_time_ms":"${createdTimeMs.toEpochMilli()}", - "tenant":"selectedTenant", "event":{ "event_source":{ "title":"title", @@ -379,8 +367,7 @@ internal class GetNotificationEventResponseTests { { "event_id":"event_id", "last_updated_time_ms":"${lastUpdatedTimeMs.toEpochMilli()}", - "created_time_ms":"${createdTimeMs.toEpochMilli()}", - "tenant":"selectedTenant" + "created_time_ms":"${createdTimeMs.toEpochMilli()}" } ] } diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationConfigInfoTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationConfigInfoTests.kt index 409decd7..6f532fb0 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationConfigInfoTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationConfigInfoTests.kt @@ -52,7 +52,6 @@ internal class NotificationConfigInfoTests { "config_id", Instant.now(), Instant.now(), - "tenant", sampleConfig ) val recreatedObject = recreateObject(configInfo) { NotificationConfigInfo(it) } @@ -75,7 +74,6 @@ internal class NotificationConfigInfoTests { "config_id", lastUpdatedTimeMs, createdTimeMs, - "tenant", sampleConfig ) val jsonString = getJsonString(configInfo) @@ -83,45 +81,6 @@ internal class NotificationConfigInfoTests { assertEquals(configInfo, recreatedObject) } - @Test - fun `Config info should take default tenant when field is absent in json object`() { - val lastUpdatedTimeMs = Instant.ofEpochMilli(Instant.now().toEpochMilli()) - val createdTimeMs = lastUpdatedTimeMs.minusSeconds(1000) - val sampleSlack = Slack("https://domain.com/sample_slack_url#1234567890") - val sampleConfig = NotificationConfig( - "name", - "description", - ConfigType.SLACK, - setOf(FEATURE_INDEX_MANAGEMENT), - isEnabled = true, - configData = sampleSlack - ) - val configInfo = NotificationConfigInfo( - "config-Id", - lastUpdatedTimeMs, - createdTimeMs, - "", // Default tenant - sampleConfig - ) - val jsonString = """ - { - "config_id":"config-Id", - "last_updated_time_ms":"${lastUpdatedTimeMs.toEpochMilli()}", - "created_time_ms":"${createdTimeMs.toEpochMilli()}", - "config":{ - "name":"name", - "description":"description", - "config_type":"slack", - "feature_list":["index_management"], - "is_enabled":true, - "slack":{"url":"https://domain.com/sample_slack_url#1234567890"} - } - } - """.trimIndent() - val recreatedObject = createObjectFromJsonString(jsonString) { NotificationConfigInfo.parse(it) } - assertEquals(configInfo, recreatedObject) - } - @Test fun `Config info should safely ignore extra field in json object`() { val lastUpdatedTimeMs = Instant.ofEpochMilli(Instant.now().toEpochMilli()) @@ -139,7 +98,6 @@ internal class NotificationConfigInfoTests { "config-Id", lastUpdatedTimeMs, createdTimeMs, - "selectedTenant", sampleConfig ) val jsonString = """ @@ -147,7 +105,6 @@ internal class NotificationConfigInfoTests { "config_id":"config-Id", "last_updated_time_ms":"${lastUpdatedTimeMs.toEpochMilli()}", "created_time_ms":"${createdTimeMs.toEpochMilli()}", - "tenant":"selectedTenant", "config":{ "name":"name", "description":"description", @@ -180,7 +137,6 @@ internal class NotificationConfigInfoTests { "", Instant.now(), Instant.now(), - "tenant", sampleConfig ) } @@ -194,7 +150,6 @@ internal class NotificationConfigInfoTests { { "last_updated_time_ms":"${lastUpdatedTimeMs.toEpochMilli()}", "created_time_ms":"${createdTimeMs.toEpochMilli()}", - "tenant":"selectedTenant", "config":{ "name":"name", "description":"description", @@ -218,7 +173,6 @@ internal class NotificationConfigInfoTests { { "config_id":"config-Id", "created_time_ms":"${createdTimeMs.toEpochMilli()}", - "tenant":"selectedTenant", "config":{ "name":"name", "description":"description", @@ -241,7 +195,6 @@ internal class NotificationConfigInfoTests { { "config_id":"config-Id", "last_updated_time_ms":"${lastUpdatedTimeMs.toEpochMilli()}", - "tenant":"selectedTenant", "config":{ "name":"name", "description":"description", @@ -265,8 +218,7 @@ internal class NotificationConfigInfoTests { { "config_id":"config-Id", "last_updated_time_ms":"${lastUpdatedTimeMs.toEpochMilli()}", - "created_time_ms":"${createdTimeMs.toEpochMilli()}", - "tenant":"selectedTenant" + "created_time_ms":"${createdTimeMs.toEpochMilli()}" } """.trimIndent() Assertions.assertThrows(IllegalArgumentException::class.java) { diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationConfigSearchResultsTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationConfigSearchResultsTests.kt index 6a10935f..dab33090 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationConfigSearchResultsTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationConfigSearchResultsTests.kt @@ -64,7 +64,6 @@ internal class NotificationConfigSearchResultsTests { "config_id", Instant.now(), Instant.now(), - "tenant", sampleConfig ) val searchResult = NotificationConfigSearchResult(configInfo) @@ -85,7 +84,6 @@ internal class NotificationConfigSearchResultsTests { "config_id1", Instant.now(), Instant.now(), - "tenant", sampleConfig1 ) val sampleConfig2 = NotificationConfig( @@ -99,7 +97,6 @@ internal class NotificationConfigSearchResultsTests { "config_id2", Instant.now(), Instant.now(), - "tenant", sampleConfig2 ) val searchResult = NotificationConfigSearchResult(listOf(configInfo1, configInfo2)) @@ -126,7 +123,6 @@ internal class NotificationConfigSearchResultsTests { "config_id1", Instant.now(), Instant.now(), - "tenant", sampleConfig1 ) val sampleConfig2 = NotificationConfig( @@ -140,7 +136,6 @@ internal class NotificationConfigSearchResultsTests { "config_id2", Instant.now(), Instant.now(), - "tenant", sampleConfig2 ) val searchResult = NotificationConfigSearchResult( @@ -169,7 +164,6 @@ internal class NotificationConfigSearchResultsTests { "config_id", lastUpdatedTimeMs, createdTimeMs, - "tenant", sampleConfig ) val searchResult = NotificationConfigSearchResult(configInfo) @@ -193,7 +187,6 @@ internal class NotificationConfigSearchResultsTests { "config_id1", lastUpdatedTimeMs, createdTimeMs, - "tenant", sampleConfig1 ) val sampleConfig2 = NotificationConfig( @@ -207,7 +200,6 @@ internal class NotificationConfigSearchResultsTests { "config_id2", lastUpdatedTimeMs, createdTimeMs, - "tenant", sampleConfig2 ) val searchResult = NotificationConfigSearchResult( @@ -238,7 +230,6 @@ internal class NotificationConfigSearchResultsTests { "config-Id", lastUpdatedTimeMs, createdTimeMs, - "selectedTenant", sampleConfig ) val searchResult = NotificationConfigSearchResult(configInfo) @@ -252,7 +243,6 @@ internal class NotificationConfigSearchResultsTests { "config_id":"config-Id", "last_updated_time_ms":"${lastUpdatedTimeMs.toEpochMilli()}", "created_time_ms":"${createdTimeMs.toEpochMilli()}", - "tenant":"selectedTenant", "config":{ "name":"name", "description":"description", @@ -289,7 +279,6 @@ internal class NotificationConfigSearchResultsTests { "config-Id", lastUpdatedTimeMs, createdTimeMs, - "selectedTenant", sampleConfig ) val searchResult = NotificationConfigSearchResult(configInfo) @@ -300,7 +289,6 @@ internal class NotificationConfigSearchResultsTests { "config_id":"config-Id", "last_updated_time_ms":"${lastUpdatedTimeMs.toEpochMilli()}", "created_time_ms":"${createdTimeMs.toEpochMilli()}", - "tenant":"selectedTenant", "config":{ "name":"name", "description":"description", @@ -330,8 +318,7 @@ internal class NotificationConfigSearchResultsTests { { "config_id":"config-Id", "last_updated_time_ms":"${lastUpdatedTimeMs.toEpochMilli()}", - "created_time_ms":"${createdTimeMs.toEpochMilli()}", - "tenant":"selectedTenant" + "created_time_ms":"${createdTimeMs.toEpochMilli()}" } ] } diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationEventInfoTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationEventInfoTests.kt index 9f45fbb0..3937c252 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationEventInfoTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationEventInfoTests.kt @@ -56,7 +56,6 @@ internal class NotificationEventInfoTests { "event_id", Instant.now(), Instant.now(), - "tenant", sampleEvent ) val recreatedObject = recreateObject(eventInfo) { NotificationEventInfo(it) } @@ -84,7 +83,6 @@ internal class NotificationEventInfoTests { "event_id", lastUpdatedTimeMs, createdTimeMs, - "tenant", sampleEvent ) val jsonString = getJsonString(eventInfo) @@ -92,63 +90,6 @@ internal class NotificationEventInfoTests { assertEquals(eventInfo, recreatedObject) } - @Test - fun `Event info should take default tenant when field is absent in json object`() { - val lastUpdatedTimeMs = Instant.ofEpochMilli(Instant.now().toEpochMilli()) - val createdTimeMs = lastUpdatedTimeMs.minusSeconds(1000) - val sampleEventSource = EventSource( - "title", - "reference_id", - FEATURE_ALERTING, - severity = SeverityType.INFO - ) - val sampleStatus = EventStatus( - "config_id", - "name", - ConfigType.SLACK, - deliveryStatus = DeliveryStatus("200", "success") - ) - val sampleEvent = NotificationEvent(sampleEventSource, listOf(sampleStatus)) - val eventInfo = NotificationEventInfo( - "event_id", - lastUpdatedTimeMs, - createdTimeMs, - "tenant", - sampleEvent - ) - val jsonString = """ - { - "event_id":"event_id", - "last_updated_time_ms":"${lastUpdatedTimeMs.toEpochMilli()}", - "created_time_ms":"${createdTimeMs.toEpochMilli()}", - "tenant":"tenant", - "event":{ - "event_source":{ - "title":"title", - "reference_id":"reference_id", - "feature":"alerting", - "severity":"info", - "tags":[] - }, - "status_list":[ - { - "config_id":"config_id", - "config_type":"slack", - "config_name":"name", - "delivery_status": - { - "status_code":"200", - "status_text":"success" - } - } - ] - } - } - """.trimIndent() - val recreatedObject = createObjectFromJsonString(jsonString) { NotificationEventInfo.parse(it) } - assertEquals(eventInfo, recreatedObject) - } - @Test fun `Event info should safely ignore extra field in json object`() { val lastUpdatedTimeMs = Instant.ofEpochMilli(Instant.now().toEpochMilli()) @@ -170,7 +111,6 @@ internal class NotificationEventInfoTests { "event_id", lastUpdatedTimeMs, createdTimeMs, - "tenant", sampleEvent ) val jsonString = """ @@ -178,7 +118,6 @@ internal class NotificationEventInfoTests { "event_id":"event_id", "last_updated_time_ms":"${lastUpdatedTimeMs.toEpochMilli()}", "created_time_ms":"${createdTimeMs.toEpochMilli()}", - "tenant":"tenant", "event":{ "event_source":{ "title":"title", @@ -231,7 +170,6 @@ internal class NotificationEventInfoTests { "", lastUpdatedTimeMs, createdTimeMs, - "tenant", sampleEvent ) } @@ -281,7 +219,6 @@ internal class NotificationEventInfoTests { { "event_id":"event_id", "created_time_ms":"${createdTimeMs.toEpochMilli()}", - "tenant":"selectedTenant", "event":{ "event_source":{ "title":"title", @@ -317,7 +254,6 @@ internal class NotificationEventInfoTests { { "event_id":"event_id", "last_updated_time_ms":"${lastUpdatedTimeMs.toEpochMilli()}", - "tenant":"selectedTenant", "event":{ "event_source":{ "title":"title", @@ -354,8 +290,7 @@ internal class NotificationEventInfoTests { { "event_id":"event_id", "last_updated_time_ms":"${lastUpdatedTimeMs.toEpochMilli()}", - "created_time_ms":"${createdTimeMs.toEpochMilli()}", - "tenant":"selectedTenant" + "created_time_ms":"${createdTimeMs.toEpochMilli()}" } """.trimIndent() Assertions.assertThrows(IllegalArgumentException::class.java) { diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationEventSearchResultTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationEventSearchResultTests.kt index 078d4910..c0e9786d 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationEventSearchResultTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationEventSearchResultTests.kt @@ -69,7 +69,6 @@ internal class NotificationEventSearchResultTests { "event_id", Instant.now(), Instant.now(), - "tenant", sampleEvent ) val searchResult = NotificationEventSearchResult(eventInfo) @@ -107,28 +106,24 @@ internal class NotificationEventSearchResultTests { "event_id1", Instant.now(), Instant.now(), - "tenant", NotificationEvent(eventSource1, listOf(status1)) ) val eventInfo2 = NotificationEventInfo( "event_id2", Instant.now(), Instant.now(), - "tenant", NotificationEvent(eventSource2, listOf(status2)) ) val eventInfo3 = NotificationEventInfo( "event_id3", Instant.now(), Instant.now(), - "tenant", NotificationEvent(eventSource1, listOf(status1, status2)) ) val eventInfo4 = NotificationEventInfo( "event_id4", Instant.now(), Instant.now(), - "tenant", NotificationEvent(eventSource2, listOf(status1, status2)) ) val searchResult = NotificationEventSearchResult( @@ -174,28 +169,24 @@ internal class NotificationEventSearchResultTests { "event_id1", Instant.now(), Instant.now(), - "tenant", NotificationEvent(eventSource1, listOf(status1)) ) val eventInfo2 = NotificationEventInfo( "event_id2", Instant.now(), Instant.now(), - "tenant", NotificationEvent(eventSource2, listOf(status2)) ) val eventInfo3 = NotificationEventInfo( "event_id3", Instant.now(), Instant.now(), - "tenant", NotificationEvent(eventSource1, listOf(status1, status2)) ) val eventInfo4 = NotificationEventInfo( "event_id4", Instant.now(), Instant.now(), - "tenant", NotificationEvent(eventSource2, listOf(status1, status2)) ) val searchResult = NotificationEventSearchResult( @@ -229,7 +220,6 @@ internal class NotificationEventSearchResultTests { "event_id", lastUpdatedTimeMs, createdTimeMs, - "tenant", sampleEvent ) val searchResult = NotificationEventSearchResult(eventInfo) @@ -270,14 +260,12 @@ internal class NotificationEventSearchResultTests { "event_id1", lastUpdatedTimeMs, createdTimeMs, - "tenant", NotificationEvent(eventSource1, listOf(status1)) ) val eventInfo2 = NotificationEventInfo( "event_id2", lastUpdatedTimeMs, createdTimeMs, - "tenant", NotificationEvent(eventSource2, listOf(status2)) ) val searchResult = NotificationEventSearchResult( @@ -312,7 +300,6 @@ internal class NotificationEventSearchResultTests { "event_id", lastUpdatedTimeMs, createdTimeMs, - "selectedTenant", sampleEvent ) val searchResult = NotificationEventSearchResult(eventInfo) @@ -326,7 +313,6 @@ internal class NotificationEventSearchResultTests { "event_id":"event_id", "last_updated_time_ms":"${lastUpdatedTimeMs.toEpochMilli()}", "created_time_ms":"${createdTimeMs.toEpochMilli()}", - "tenant":"selectedTenant", "event":{ "event_source":{ "title":"title", @@ -380,7 +366,6 @@ internal class NotificationEventSearchResultTests { "event_id", lastUpdatedTimeMs, createdTimeMs, - "selectedTenant", sampleEvent ) val searchResult = NotificationEventSearchResult(eventInfo) @@ -391,7 +376,6 @@ internal class NotificationEventSearchResultTests { "event_id":"event_id", "last_updated_time_ms":"${lastUpdatedTimeMs.toEpochMilli()}", "created_time_ms":"${createdTimeMs.toEpochMilli()}", - "tenant":"selectedTenant", "event":{ "event_source":{ "title":"title", @@ -434,8 +418,7 @@ internal class NotificationEventSearchResultTests { { "event_id":"event_id", "last_updated_time_ms":"${lastUpdatedTimeMs.toEpochMilli()}", - "created_time_ms":"${createdTimeMs.toEpochMilli()}", - "tenant":"selectedTenant" + "created_time_ms":"${createdTimeMs.toEpochMilli()}" } ] } From 21b951def468ac06bef87145822f5ec6927f5863 Mon Sep 17 00:00:00 2001 From: Anantha Krishna Bhatta <31894175+akbhatta@users.noreply.github.com> Date: Thu, 23 Sep 2021 15:48:16 -0700 Subject: [PATCH 015/140] Updated the plugin feature response with allowed config features (#74) [Tests] Updated the unit tests Signed-off-by: @akbhatta --- .../notifications/NotificationConstants.kt | 3 +- .../action/GetPluginFeaturesResponse.kt | 38 +++++++++++++------ .../NotificationsPluginInterfaceTests.kt | 1 + .../action/GetPluginFeaturesResponseTests.kt | 31 +++++++++++++-- 4 files changed, 56 insertions(+), 17 deletions(-) diff --git a/src/main/kotlin/org/opensearch/commons/notifications/NotificationConstants.kt b/src/main/kotlin/org/opensearch/commons/notifications/NotificationConstants.kt index dc16a39f..7a958154 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/NotificationConstants.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/NotificationConstants.kt @@ -66,7 +66,8 @@ object NotificationConstants { const val TOTAL_HIT_RELATION_TAG = "total_hit_relation" const val QUERY_TAG = "query" const val COMPACT_TAG = "compact" - const val CONFIG_TYPE_LIST_TAG = "config_type_list" + const val ALLOWED_CONFIG_TYPE_LIST_TAG = "allowed_config_type_list" + const val ALLOWED_CONFIG_FEATURE_LIST_TAG = "allowed_config_feature_list" const val PLUGIN_FEATURES_TAG = "plugin_features" const val FEATURE_ALERTING = "alerting" diff --git a/src/main/kotlin/org/opensearch/commons/notifications/action/GetPluginFeaturesResponse.kt b/src/main/kotlin/org/opensearch/commons/notifications/action/GetPluginFeaturesResponse.kt index 681b943e..dde25709 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/action/GetPluginFeaturesResponse.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/action/GetPluginFeaturesResponse.kt @@ -33,7 +33,8 @@ import org.opensearch.common.xcontent.ToXContent import org.opensearch.common.xcontent.XContentBuilder import org.opensearch.common.xcontent.XContentParser import org.opensearch.common.xcontent.XContentParserUtils -import org.opensearch.commons.notifications.NotificationConstants.CONFIG_TYPE_LIST_TAG +import org.opensearch.commons.notifications.NotificationConstants.ALLOWED_CONFIG_FEATURE_LIST_TAG +import org.opensearch.commons.notifications.NotificationConstants.ALLOWED_CONFIG_TYPE_LIST_TAG import org.opensearch.commons.notifications.NotificationConstants.PLUGIN_FEATURES_TAG import org.opensearch.commons.utils.STRING_READER import org.opensearch.commons.utils.STRING_WRITER @@ -45,7 +46,8 @@ import java.io.IOException * Action Response for getting notification plugin features. */ class GetPluginFeaturesResponse : BaseResponse { - val configTypeList: List + val allowedConfigTypeList: List + val allowedConfigFeatureList: List val pluginFeatures: Map companion object { @@ -63,7 +65,8 @@ class GetPluginFeaturesResponse : BaseResponse { @JvmStatic @Throws(IOException::class) fun parse(parser: XContentParser): GetPluginFeaturesResponse { - var configTypeList: List? = null + var allowedConfigTypeList: List? = null + var allowedConfigFeatureList: List? = null var pluginFeatures: Map? = null XContentParserUtils.ensureExpectedToken( @@ -75,7 +78,8 @@ class GetPluginFeaturesResponse : BaseResponse { val fieldName = parser.currentName() parser.nextToken() when (fieldName) { - CONFIG_TYPE_LIST_TAG -> configTypeList = parser.stringList() + ALLOWED_CONFIG_TYPE_LIST_TAG -> allowedConfigTypeList = parser.stringList() + ALLOWED_CONFIG_FEATURE_LIST_TAG -> allowedConfigFeatureList = parser.stringList() PLUGIN_FEATURES_TAG -> pluginFeatures = parser.mapStrings() else -> { parser.skipChildren() @@ -83,9 +87,10 @@ class GetPluginFeaturesResponse : BaseResponse { } } } - configTypeList ?: throw IllegalArgumentException("$CONFIG_TYPE_LIST_TAG field absent") + allowedConfigTypeList ?: throw IllegalArgumentException("$ALLOWED_CONFIG_TYPE_LIST_TAG field absent") + allowedConfigFeatureList ?: throw IllegalArgumentException("$ALLOWED_CONFIG_TYPE_LIST_TAG field absent") pluginFeatures ?: throw IllegalArgumentException("$PLUGIN_FEATURES_TAG field absent") - return GetPluginFeaturesResponse(configTypeList, pluginFeatures) + return GetPluginFeaturesResponse(allowedConfigTypeList, allowedConfigFeatureList, pluginFeatures) } } @@ -94,18 +99,25 @@ class GetPluginFeaturesResponse : BaseResponse { */ override fun toXContent(builder: XContentBuilder?, params: ToXContent.Params?): XContentBuilder { return builder!!.startObject() - .field(CONFIG_TYPE_LIST_TAG, configTypeList) + .field(ALLOWED_CONFIG_TYPE_LIST_TAG, allowedConfigTypeList) + .field(ALLOWED_CONFIG_FEATURE_LIST_TAG, allowedConfigFeatureList) .field(PLUGIN_FEATURES_TAG, pluginFeatures) .endObject() } /** * constructor for creating the class - * @param configTypeList the list of config types supported by plugin + * @param allowedConfigTypeList the list of config types supported by plugin + * @param allowedConfigFeatureList the list of config features supported by plugin * @param pluginFeatures the map of plugin features supported to its value */ - constructor(configTypeList: List, pluginFeatures: Map) { - this.configTypeList = configTypeList + constructor( + allowedConfigTypeList: List, + allowedConfigFeatureList: List, + pluginFeatures: Map + ) { + this.allowedConfigTypeList = allowedConfigTypeList + this.allowedConfigFeatureList = allowedConfigFeatureList this.pluginFeatures = pluginFeatures } @@ -114,7 +126,8 @@ class GetPluginFeaturesResponse : BaseResponse { */ @Throws(IOException::class) constructor(input: StreamInput) : super(input) { - configTypeList = input.readStringList() + allowedConfigTypeList = input.readStringList() + allowedConfigFeatureList = input.readStringList() pluginFeatures = input.readMap(STRING_READER, STRING_READER) } @@ -123,7 +136,8 @@ class GetPluginFeaturesResponse : BaseResponse { */ @Throws(IOException::class) override fun writeTo(output: StreamOutput) { - output.writeStringCollection(configTypeList) + output.writeStringCollection(allowedConfigTypeList) + output.writeStringCollection(allowedConfigFeatureList) output.writeMap(pluginFeatures, STRING_WRITER, STRING_WRITER) } } diff --git a/src/test/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterfaceTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterfaceTests.kt index 77d12ff2..31d47bba 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterfaceTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterfaceTests.kt @@ -156,6 +156,7 @@ internal class NotificationsPluginInterfaceTests { val request = mock(GetPluginFeaturesRequest::class.java) val response = GetPluginFeaturesResponse( listOf("config_type_1", "config_type_2", "config_type_3"), + listOf("config_feature_1", "config_feature_2", "config_feature_3"), mapOf( Pair("FeatureKey1", "FeatureValue1"), Pair("FeatureKey2", "FeatureValue2"), diff --git a/src/test/kotlin/org/opensearch/commons/notifications/action/GetPluginFeaturesResponseTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/action/GetPluginFeaturesResponseTests.kt index 3103825f..930d430f 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/action/GetPluginFeaturesResponseTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/action/GetPluginFeaturesResponseTests.kt @@ -39,7 +39,7 @@ internal class GetPluginFeaturesResponseTests { expected: GetPluginFeaturesResponse, actual: GetPluginFeaturesResponse ) { - assertEquals(expected.configTypeList, actual.configTypeList) + assertEquals(expected.allowedConfigTypeList, actual.allowedConfigTypeList) assertEquals(expected.pluginFeatures, actual.pluginFeatures) } @@ -47,6 +47,7 @@ internal class GetPluginFeaturesResponseTests { fun `Get Response serialize and deserialize transport object should be equal`() { val response = GetPluginFeaturesResponse( listOf("config_type_1", "config_type_2", "config_type_3"), + listOf("config_feature_1", "config_feature_2", "config_feature_3"), mapOf( Pair("FeatureKey1", "FeatureValue1"), Pair("FeatureKey2", "FeatureValue2"), @@ -61,6 +62,7 @@ internal class GetPluginFeaturesResponseTests { fun `Get Response serialize and deserialize using json config object should be equal`() { val response = GetPluginFeaturesResponse( listOf("config_type_1", "config_type_2", "config_type_3"), + listOf("config_feature_1", "config_feature_2", "config_feature_3"), mapOf( Pair("FeatureKey1", "FeatureValue1"), Pair("FeatureKey2", "FeatureValue2"), @@ -76,6 +78,7 @@ internal class GetPluginFeaturesResponseTests { fun `Get Response should safely ignore extra field in json object`() { val response = GetPluginFeaturesResponse( listOf("config_type_1", "config_type_2", "config_type_3"), + listOf("config_feature_1", "config_feature_2", "config_feature_3"), mapOf( Pair("FeatureKey1", "FeatureValue1"), Pair("FeatureKey2", "FeatureValue2"), @@ -84,7 +87,8 @@ internal class GetPluginFeaturesResponseTests { ) val jsonString = """ { - "config_type_list":["config_type_1", "config_type_2", "config_type_3"], + "allowed_config_type_list":["config_type_1", "config_type_2", "config_type_3"], + "allowed_config_feature_list":["config_feature_1", "config_feature_2", "config_feature_3"], "plugin_features":{ "FeatureKey1":"FeatureValue1", "FeatureKey2":"FeatureValue2", @@ -100,9 +104,27 @@ internal class GetPluginFeaturesResponseTests { } @Test - fun `Get Response should throw exception if config_type_list is absent in json`() { + fun `Get Response should throw exception if allowed_config_type_list is absent in json`() { val jsonString = """ { + "allowed_config_feature_list":["config_feature_1", "config_feature_2", "config_feature_3"], + "plugin_features":{ + "FeatureKey1":"FeatureValue1", + "FeatureKey2":"FeatureValue2", + "FeatureKey3":"FeatureValue3" + } + } + """.trimIndent() + Assertions.assertThrows(IllegalArgumentException::class.java) { + createObjectFromJsonString(jsonString) { GetPluginFeaturesResponse.parse(it) } + } + } + + @Test + fun `Get Response should throw exception if allowed_config_feature_list is absent in json`() { + val jsonString = """ + { + "allowed_config_type_list":["config_type_1", "config_type_2", "config_type_3"], "plugin_features":{ "FeatureKey1":"FeatureValue1", "FeatureKey2":"FeatureValue2", @@ -119,7 +141,8 @@ internal class GetPluginFeaturesResponseTests { fun `Get Response should throw exception if plugin_features is absent in json`() { val jsonString = """ { - "config_type_list":["config_type_1", "config_type_2", "config_type_3"] + "config_type_list":["config_type_1", "config_type_2", "config_type_3"], + "allowed_config_feature_list":["config_feature_1", "config_feature_2", "config_feature_3"] } """.trimIndent() Assertions.assertThrows(IllegalArgumentException::class.java) { From 486c2e194a145d3719274650cf3cac3537eae3e9 Mon Sep 17 00:00:00 2001 From: Clay Downs <89109232+downsrob@users.noreply.github.com> Date: Thu, 30 Sep 2021 17:41:03 -0700 Subject: [PATCH 016/140] Updates common-utils version to 1.2 (#77) * Updates common-utils version to 1.2 and Uses Maven for 1.2 dependencies Signed-off-by: Clay Downs --- .github/workflows/ci.yml | 15 ++------------- build.gradle | 4 +++- 2 files changed, 5 insertions(+), 14 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8f83153e..52eea2f1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -25,25 +25,14 @@ jobs: with: java-version: ${{ matrix.java }} - # dependencies: OpenSearch - - name: Checkout OpenSearch - uses: actions/checkout@v2 - with: - repository: 'opensearch-project/OpenSearch' - path: OpenSearch - ref: '1.1' - - name: Build OpenSearch - working-directory: ./OpenSearch - run: ./gradlew publishToMavenLocal - # common-utils - name: Build and Test run: | - ./gradlew build -Dopensearch.version=1.1.0-SNAPSHOT + ./gradlew build -Dopensearch.version=1.2.0-SNAPSHOT - name: Publish to Maven Local run: | - ./gradlew publishToMavenLocal -Dopensearch.version=1.1.0-SNAPSHOT + ./gradlew publishToMavenLocal -Dopensearch.version=1.2.0-SNAPSHOT - name: Upload Coverage Report uses: codecov/codecov-action@v1 diff --git a/build.gradle b/build.gradle index d443ddf4..dc33b6d9 100644 --- a/build.gradle +++ b/build.gradle @@ -12,7 +12,7 @@ buildscript { ext { opensearch_group = "org.opensearch" - opensearch_version = System.getProperty("opensearch.version", "1.1.0-SNAPSHOT") + opensearch_version = System.getProperty("opensearch.version", "1.2.0-SNAPSHOT") kotlin_version = System.getProperty("kotlin.version", "1.4.32") } @@ -21,6 +21,7 @@ buildscript { mavenCentral() maven { url "https://plugins.gradle.org/m2/" } jcenter() + maven { url "https://aws.oss.sonatype.org/content/repositories/snapshots" } } dependencies { @@ -42,6 +43,7 @@ repositories { mavenCentral() maven { url "https://plugins.gradle.org/m2/" } jcenter() + maven { url "https://aws.oss.sonatype.org/content/repositories/snapshots" } } ext { From 151646fb017ff0b64713290b786b10046a3aea3a Mon Sep 17 00:00:00 2001 From: "Daniel Doubrovkine (dB.)" Date: Wed, 6 Oct 2021 13:43:20 -0400 Subject: [PATCH 017/140] Publish .md5 and .sha1 signatures. (#79) (#80) * Publish .md5 and .sha1 signatures. Signed-off-by: dblock * Use OpenSearch 1.1. Signed-off-by: dblock --- .github/workflows/push-common-utils-jar.yml | 44 --------------- build.gradle | 10 ++-- scripts/build.sh | 61 +++++++++++++++++++++ 3 files changed, 66 insertions(+), 49 deletions(-) delete mode 100644 .github/workflows/push-common-utils-jar.yml create mode 100755 scripts/build.sh diff --git a/.github/workflows/push-common-utils-jar.yml b/.github/workflows/push-common-utils-jar.yml deleted file mode 100644 index 6a4bc703..00000000 --- a/.github/workflows/push-common-utils-jar.yml +++ /dev/null @@ -1,44 +0,0 @@ -name: Upload Common-Utils Jar to Maven - -on: - push: - tags: - - v* -jobs: - upload-common-utils-jar: - runs-on: [ubuntu-16.04] - name: Upload common-utils Jar to Maven - steps: - - name: Checkout Repo - uses: actions/checkout@v2 - - - name: Configure AWS CLI - uses: aws-actions/configure-aws-credentials@v1 - with: - aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} - aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} - aws-region: us-east-1 - - - name: Setup Java - uses: actions/setup-java@v1 - with: - java-version: '14' - - - name: Upload common-utils Jar to Maven - env: - passphrase: ${{ secrets.PASSPHRASE }} - run: | - cd .. - export JAVA14_HOME=$JAVA_HOME - aws s3 cp s3://opendistro-docs/github-actions/pgp-public-key . - aws s3 cp s3://opendistro-docs/github-actions/pgp-private-key . - - gpg --import pgp-public-key - gpg --allow-secret-key-import --import pgp-private-key - - mkdir /home/runner/.gradle - aws s3 cp s3://opendistro-docs/github-actions/gradle.properties /home/runner/.gradle/ - - cd common-utils - - ./gradlew publishShadowPublicationToSonatype-stagingRepository -Dcompiler.java=14 -Dbuild.snapshot=false -Djavax.net.ssl.trustStore=$JAVA_HOME/lib/security/cacerts diff --git a/build.gradle b/build.gradle index dc33b6d9..b0a720cf 100644 --- a/build.gradle +++ b/build.gradle @@ -148,6 +148,11 @@ shadowJar { classifier = null } +shadowJar.doLast { + ant.checksum algorithm: 'md5', file: it.archivePath + ant.checksum algorithm: 'sha1', file: it.archivePath +} + task sourcesJar(type: Jar) { classifier = 'sources' from sourceSets.main.allJava @@ -197,9 +202,4 @@ publishing { gradle.startParameter.setShowStacktrace(ShowStacktrace.ALWAYS) gradle.startParameter.setLogLevel(LogLevel.DEBUG) - - signing { - required { gradle.taskGraph.hasTask("publishShadowPublicationToSonatype-stagingRepository") } - sign publishing.publications.shadow - } } diff --git a/scripts/build.sh b/scripts/build.sh new file mode 100755 index 00000000..fdc9be57 --- /dev/null +++ b/scripts/build.sh @@ -0,0 +1,61 @@ +#!/bin/bash + +# Copyright OpenSearch Contributors. +# SPDX-License-Identifier: Apache-2.0 + +set -ex + +function usage() { + echo "Usage: $0 [args]" + echo "" + echo "Arguments:" + echo -e "-v VERSION\t[Required] OpenSearch version." + echo -e "-s SNAPSHOT\t[Optional] Build a snapshot, default is 'false'." + echo -e "-a ARCHITECTURE\t[Optional] Build architecture, ignored." + echo -e "-o OUTPUT\t[Optional] Output path, default is 'artifacts'." + echo -e "-h help" +} + +while getopts ":h:v:s:o:a:" arg; do + case $arg in + h) + usage + exit 1 + ;; + v) + VERSION=$OPTARG + ;; + s) + SNAPSHOT=$OPTARG + ;; + o) + OUTPUT=$OPTARG + ;; + a) + ARCHITECTURE=$OPTARG + ;; + :) + echo "Error: -${OPTARG} requires an argument" + usage + exit 1 + ;; + ?) + echo "Invalid option: -${arg}" + exit 1 + ;; + esac +done + +if [ -z "$VERSION" ]; then + echo "Error: You must specify the OpenSearch version" + usage + exit 1 +fi + +[[ "$SNAPSHOT" == "true" ]] && VERSION=$VERSION-SNAPSHOT +[ -z "$OUTPUT" ] && OUTPUT=artifacts + +./gradlew build -Dopensearch.version=$VERSION -Dbuild.snapshot=$SNAPSHOT +./gradlew publishShadowPublicationToMavenLocal -Dopensearch.version=$VERSION -Dbuild.snapshot=$SNAPSHOT +mkdir -p $OUTPUT/maven/org/opensearch +cp -r ./build/libs $OUTPUT/maven/org/opensearch/common-utils From cbeba12d5a67e4f0079b93f37b3ce7b51961f69b Mon Sep 17 00:00:00 2001 From: "Daniel Doubrovkine (dB.)" Date: Wed, 6 Oct 2021 17:10:21 -0400 Subject: [PATCH 018/140] Publish source and javadoc checksums. (#81) Signed-off-by: dblock --- build.gradle | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/build.gradle b/build.gradle index b0a720cf..92f71cc5 100644 --- a/build.gradle +++ b/build.gradle @@ -148,11 +148,6 @@ shadowJar { classifier = null } -shadowJar.doLast { - ant.checksum algorithm: 'md5', file: it.archivePath - ant.checksum algorithm: 'sha1', file: it.archivePath -} - task sourcesJar(type: Jar) { classifier = 'sources' from sourceSets.main.allJava @@ -163,6 +158,15 @@ task javadocJar(type: Jar) { from javadoc.destinationDir } +tasks.withType(Jar) { task -> + task.doLast { + ant.checksum algorithm: 'md5', file: it.archivePath + ant.checksum algorithm: 'sha1', file: it.archivePath + ant.checksum algorithm: 'sha-256', file: it.archivePath, fileext: '.sha256' + ant.checksum algorithm: 'sha-512', file: it.archivePath, fileext: '.sha512' + } +} + publishing { publications { shadow(MavenPublication) { From e51a67ae47e3382c68d56c7fb05a3bcf01733776 Mon Sep 17 00:00:00 2001 From: Anantha Krishna Bhatta <31894175+akbhatta@users.noreply.github.com> Date: Wed, 13 Oct 2021 12:28:34 -0700 Subject: [PATCH 019/140] Email recipients made nested for backward compatibility with Alerting (#83) [Tests] Unit tests added/updated Signed-off-by: @akbhatta --- .../commons/notifications/model/Email.kt | 15 +- .../commons/notifications/model/EmailGroup.kt | 19 +-- .../notifications/model/EmailRecipient.kt | 119 +++++++++++++++ .../CreateNotificationConfigRequestTests.kt | 18 ++- .../action/GetPluginFeaturesResponseTests.kt | 1 + .../UpdateNotificationConfigRequestTests.kt | 18 ++- .../notifications/model/EmailGroupTests.kt | 90 +++++------ .../model/EmailRecipientTests.kt | 142 ++++++++++++++++++ .../commons/notifications/model/EmailTests.kt | 69 +++------ .../model/NotificationConfigTests.kt | 8 +- .../model/config/ConfigPropertiesTests.kt | 3 +- 11 files changed, 361 insertions(+), 141 deletions(-) create mode 100644 src/main/kotlin/org/opensearch/commons/notifications/model/EmailRecipient.kt create mode 100644 src/test/kotlin/org/opensearch/commons/notifications/model/EmailRecipientTests.kt diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/Email.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/Email.kt index c8da0f85..86d5f67a 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/Email.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/Email.kt @@ -38,8 +38,8 @@ import org.opensearch.commons.notifications.NotificationConstants.EMAIL_ACCOUNT_ import org.opensearch.commons.notifications.NotificationConstants.EMAIL_GROUP_ID_LIST_TAG import org.opensearch.commons.notifications.NotificationConstants.RECIPIENT_LIST_TAG import org.opensearch.commons.utils.logger +import org.opensearch.commons.utils.objectList import org.opensearch.commons.utils.stringList -import org.opensearch.commons.utils.validateEmail import java.io.IOException /** @@ -47,15 +47,12 @@ import java.io.IOException */ data class Email( val emailAccountID: String, - val recipients: List, + val recipients: List, val emailGroupIds: List ) : BaseConfigData { init { require(!Strings.isNullOrEmpty(emailAccountID)) { "emailAccountID is null or empty" } - recipients.forEach { - validateEmail(it) - } } companion object { @@ -79,7 +76,7 @@ data class Email( @Throws(IOException::class) fun parse(parser: XContentParser): Email { var emailAccountID: String? = null - var recipients: List = listOf() + var recipients: List = listOf() var emailGroupIds: List = listOf() XContentParserUtils.ensureExpectedToken( @@ -92,7 +89,7 @@ data class Email( parser.nextToken() when (fieldName) { EMAIL_ACCOUNT_ID_TAG -> emailAccountID = parser.text() - RECIPIENT_LIST_TAG -> recipients = parser.stringList() + RECIPIENT_LIST_TAG -> recipients = parser.objectList { EmailRecipient.parse(it) } EMAIL_GROUP_ID_LIST_TAG -> emailGroupIds = parser.stringList() else -> { parser.skipChildren() @@ -111,7 +108,7 @@ data class Email( */ constructor(input: StreamInput) : this( emailAccountID = input.readString(), - recipients = input.readStringList(), + recipients = input.readList(EmailRecipient.reader), emailGroupIds = input.readStringList() ) @@ -120,7 +117,7 @@ data class Email( */ override fun writeTo(output: StreamOutput) { output.writeString(emailAccountID) - output.writeStringCollection(recipients) + output.writeList(recipients) output.writeStringCollection(emailGroupIds) } diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/EmailGroup.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/EmailGroup.kt index f3beecd8..4940cc39 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/EmailGroup.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/EmailGroup.kt @@ -35,23 +35,16 @@ import org.opensearch.common.xcontent.XContentParser import org.opensearch.common.xcontent.XContentParserUtils import org.opensearch.commons.notifications.NotificationConstants.RECIPIENT_LIST_TAG import org.opensearch.commons.utils.logger -import org.opensearch.commons.utils.stringList -import org.opensearch.commons.utils.validateEmail +import org.opensearch.commons.utils.objectList import java.io.IOException /** * Data class representing Email group. */ data class EmailGroup( - val recipients: List + val recipients: List ) : BaseConfigData { - init { - recipients.forEach { - validateEmail(it) - } - } - companion object { private val log by logger(EmailGroup::class.java) @@ -72,7 +65,7 @@ data class EmailGroup( @JvmStatic @Throws(IOException::class) fun parse(parser: XContentParser): EmailGroup { - var recipients: List? = null + var recipients: List? = null XContentParserUtils.ensureExpectedToken( XContentParser.Token.START_OBJECT, @@ -83,7 +76,7 @@ data class EmailGroup( val fieldName = parser.currentName() parser.nextToken() when (fieldName) { - RECIPIENT_LIST_TAG -> recipients = parser.stringList() + RECIPIENT_LIST_TAG -> recipients = parser.objectList { EmailRecipient.parse(it) } else -> { parser.skipChildren() log.info("Unexpected field: $fieldName, while parsing EmailGroup") @@ -100,14 +93,14 @@ data class EmailGroup( * @param input StreamInput stream to deserialize data from. */ constructor(input: StreamInput) : this( - recipients = input.readStringList() + recipients = input.readList(EmailRecipient.reader) ) /** * {@inheritDoc} */ override fun writeTo(output: StreamOutput) { - output.writeStringCollection(recipients) + output.writeList(recipients) } /** diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/EmailRecipient.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/EmailRecipient.kt new file mode 100644 index 00000000..78c4ae59 --- /dev/null +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/EmailRecipient.kt @@ -0,0 +1,119 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + * + * Modifications Copyright OpenSearch Contributors. See + * GitHub history for details. + */ + +/* + * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + * + */ +package org.opensearch.commons.notifications.model + +import org.opensearch.common.io.stream.StreamInput +import org.opensearch.common.io.stream.StreamOutput +import org.opensearch.common.io.stream.Writeable +import org.opensearch.common.xcontent.ToXContent +import org.opensearch.common.xcontent.XContentBuilder +import org.opensearch.common.xcontent.XContentParser +import org.opensearch.common.xcontent.XContentParserUtils +import org.opensearch.commons.notifications.NotificationConstants.RECIPIENT_TAG +import org.opensearch.commons.utils.logger +import org.opensearch.commons.utils.validateEmail +import java.io.IOException + +/** + * Data class representing Email recipient. + */ +data class EmailRecipient( + val recipient: String +) : BaseConfigData { + + init { + validateEmail(recipient) + } + + companion object { + private val log by logger(EmailRecipient::class.java) + + /** + * reader to create instance of class from writable. + */ + val reader = Writeable.Reader { EmailRecipient(it) } + + /** + * Parser to parse xContent + */ + val xParser = XParser { parse(it) } + + /** + * Creator used in REST communication. + * @param parser XContentParser to deserialize data from. + */ + @JvmStatic + @Throws(IOException::class) + fun parse(parser: XContentParser): EmailRecipient { + var recipient: String? = null + + XContentParserUtils.ensureExpectedToken( + XContentParser.Token.START_OBJECT, + parser.currentToken(), + parser + ) + while (parser.nextToken() != XContentParser.Token.END_OBJECT) { + val fieldName = parser.currentName() + parser.nextToken() + when (fieldName) { + RECIPIENT_TAG -> recipient = parser.text() + else -> { + parser.skipChildren() + log.info("Unexpected field: $fieldName, while parsing EmailRecipient") + } + } + } + recipient ?: throw IllegalArgumentException("$RECIPIENT_TAG field absent") + return EmailRecipient(recipient) + } + } + + /** + * Constructor used in transport action communication. + * @param input StreamInput stream to deserialize data from. + */ + constructor(input: StreamInput) : this( + recipient = input.readString() + ) + + /** + * {@inheritDoc} + */ + override fun writeTo(output: StreamOutput) { + output.writeString(recipient) + } + + /** + * {@inheritDoc} + */ + override fun toXContent(builder: XContentBuilder?, params: ToXContent.Params?): XContentBuilder { + builder!! + return builder.startObject() + .field(RECIPIENT_TAG, recipient) + .endObject() + } +} diff --git a/src/test/kotlin/org/opensearch/commons/notifications/action/CreateNotificationConfigRequestTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/action/CreateNotificationConfigRequestTests.kt index f190e7f6..28f337b8 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/action/CreateNotificationConfigRequestTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/action/CreateNotificationConfigRequestTests.kt @@ -36,6 +36,7 @@ import org.opensearch.commons.notifications.model.Chime import org.opensearch.commons.notifications.model.ConfigType import org.opensearch.commons.notifications.model.Email import org.opensearch.commons.notifications.model.EmailGroup +import org.opensearch.commons.notifications.model.EmailRecipient import org.opensearch.commons.notifications.model.MethodType import org.opensearch.commons.notifications.model.NotificationConfig import org.opensearch.commons.notifications.model.Slack @@ -84,7 +85,7 @@ internal class CreateNotificationConfigRequestTests { } private fun createEmailGroupContentConfigObject(): NotificationConfig { - val sampleEmailGroup = EmailGroup(listOf("dummy@company.com")) + val sampleEmailGroup = EmailGroup(listOf(EmailRecipient("dummy@company.com"))) return NotificationConfig( "name", "description", @@ -98,7 +99,7 @@ internal class CreateNotificationConfigRequestTests { private fun createEmailContentConfigObject(): NotificationConfig { val sampleEmail = Email( emailAccountID = "sample_1@dummy.com", - recipients = listOf("sample_2@dummy.com"), + recipients = listOf(EmailRecipient("sample_2@dummy.com")), emailGroupIds = listOf("sample_3@dummy.com") ) return NotificationConfig( @@ -365,7 +366,7 @@ internal class CreateNotificationConfigRequestTests { @Test fun `Create config should deserialize json object using parser Email Group`() { - val sampleEmailGroup = EmailGroup(listOf("dummy@company.com")) + val sampleEmailGroup = EmailGroup(listOf(EmailRecipient("dummy@company.com"))) val config = NotificationConfig( "name", "description", @@ -384,7 +385,7 @@ internal class CreateNotificationConfigRequestTests { "config_type":"email_group", "feature_list":["index_management"], "is_enabled":true, - "email_group":{"recipient_list":["dummy@company.com"]} + "email_group":{"recipient_list":[{"recipient":"dummy@company.com"}]} } } """.trimIndent() @@ -396,7 +397,7 @@ internal class CreateNotificationConfigRequestTests { fun `Update config should deserialize json object using parser Email`() { val sampleEmail = Email( emailAccountID = "sample_1@dummy.com", - recipients = listOf("sample_2@dummy.com"), + recipients = listOf(EmailRecipient("sample_2@dummy.com")), emailGroupIds = listOf("sample_3@dummy.com") ) val config = NotificationConfig( @@ -417,8 +418,11 @@ internal class CreateNotificationConfigRequestTests { "config_type":"email", "feature_list":["index_management"], "is_enabled":true, - "email":{"email_account_id":"sample_1@dummy.com","recipient_list":["sample_2@dummy.com"], - "email_group_id_list":["sample_3@dummy.com"] } + "email":{ + "email_account_id":"sample_1@dummy.com", + "recipient_list":[{"recipient":"sample_2@dummy.com"}], + "email_group_id_list":["sample_3@dummy.com"] + } } } """.trimIndent() diff --git a/src/test/kotlin/org/opensearch/commons/notifications/action/GetPluginFeaturesResponseTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/action/GetPluginFeaturesResponseTests.kt index 930d430f..c9924269 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/action/GetPluginFeaturesResponseTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/action/GetPluginFeaturesResponseTests.kt @@ -40,6 +40,7 @@ internal class GetPluginFeaturesResponseTests { actual: GetPluginFeaturesResponse ) { assertEquals(expected.allowedConfigTypeList, actual.allowedConfigTypeList) + assertEquals(expected.allowedConfigFeatureList, actual.allowedConfigFeatureList) assertEquals(expected.pluginFeatures, actual.pluginFeatures) } diff --git a/src/test/kotlin/org/opensearch/commons/notifications/action/UpdateNotificationConfigRequestTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/action/UpdateNotificationConfigRequestTests.kt index 2dfcff69..9599d60e 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/action/UpdateNotificationConfigRequestTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/action/UpdateNotificationConfigRequestTests.kt @@ -36,6 +36,7 @@ import org.opensearch.commons.notifications.model.Chime import org.opensearch.commons.notifications.model.ConfigType import org.opensearch.commons.notifications.model.Email import org.opensearch.commons.notifications.model.EmailGroup +import org.opensearch.commons.notifications.model.EmailRecipient import org.opensearch.commons.notifications.model.MethodType import org.opensearch.commons.notifications.model.NotificationConfig import org.opensearch.commons.notifications.model.Slack @@ -84,7 +85,7 @@ internal class UpdateNotificationConfigRequestTests { } private fun createEmailGroupContentConfigObject(): NotificationConfig { - val sampleEmailGroup = EmailGroup(listOf("dummy@company.com")) + val sampleEmailGroup = EmailGroup(listOf(EmailRecipient("dummy@company.com"))) return NotificationConfig( "name", "description", @@ -98,7 +99,7 @@ internal class UpdateNotificationConfigRequestTests { private fun createEmailContentConfigObject(): NotificationConfig { val sampleEmail = Email( emailAccountID = "sample_1@dummy.com", - recipients = listOf("sample_2@dummy.com"), + recipients = listOf(EmailRecipient("sample_2@dummy.com")), emailGroupIds = listOf("sample_3@dummy.com") ) return NotificationConfig( @@ -334,7 +335,7 @@ internal class UpdateNotificationConfigRequestTests { @Test fun `Update config should deserialize json object using parser Email Group`() { - val sampleEmailGroup = EmailGroup(listOf("dummy@company.com")) + val sampleEmailGroup = EmailGroup(listOf(EmailRecipient("dummy@company.com"))) val config = NotificationConfig( "name", "description", @@ -353,7 +354,7 @@ internal class UpdateNotificationConfigRequestTests { "config_type":"email_group", "feature_list":["index_management"], "is_enabled":true, - "email_group":{"recipient_list":["dummy@company.com"]} + "email_group":{"recipient_list":[{"recipient":"dummy@company.com"}]} } } """.trimIndent() @@ -366,7 +367,7 @@ internal class UpdateNotificationConfigRequestTests { fun `Update config should deserialize json object using parser Email`() { val sampleEmail = Email( emailAccountID = "sample_1@dummy.com", - recipients = listOf("sample_2@dummy.com"), + recipients = listOf(EmailRecipient("sample_2@dummy.com")), emailGroupIds = listOf("sample_3@dummy.com") ) val config = NotificationConfig( @@ -387,8 +388,11 @@ internal class UpdateNotificationConfigRequestTests { "config_type":"email", "feature_list":["index_management"], "is_enabled":true, - "email":{"email_account_id":"sample_1@dummy.com","recipient_list":["sample_2@dummy.com"], - "email_group_id_list":["sample_3@dummy.com"] } + "email":{ + "email_account_id":"sample_1@dummy.com", + "recipient_list":[{"recipient":"sample_2@dummy.com"}], + "email_group_id_list":["sample_3@dummy.com"] + } } } """.trimIndent() diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/EmailGroupTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/EmailGroupTests.kt index 5146d785..dbf2f77b 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/EmailGroupTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/EmailGroupTests.kt @@ -29,7 +29,6 @@ package org.opensearch.commons.notifications.model import com.fasterxml.jackson.core.JsonParseException import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Test -import org.junit.jupiter.api.assertDoesNotThrow import org.junit.jupiter.api.assertThrows import org.opensearch.commons.utils.createObjectFromJsonString import org.opensearch.commons.utils.getJsonString @@ -37,56 +36,26 @@ import org.opensearch.commons.utils.recreateObject internal class EmailGroupTests { - private fun checkValidEmailAddress(emailAddress: String) { - assertDoesNotThrow("should accept $emailAddress") { - EmailGroup(listOf(emailAddress)) - } - } - - private fun checkInvalidEmailAddress(emailAddress: String) { - assertThrows("Should throw an Exception for invalid email $emailAddress") { - EmailGroup(listOf(emailAddress)) - } - } - - @Test - fun `EmailGroup should accept valid email address`() { - checkValidEmailAddress("email1234@email.com") - checkValidEmailAddress("email+1234@email.com") - checkValidEmailAddress("email-1234@email.com") - checkValidEmailAddress("email_1234@email.com") - checkValidEmailAddress("email.1234@email.com") - checkValidEmailAddress("e.ma_il-1+2@test-email-domain.co.uk") - checkValidEmailAddress("email-.+_=#|@domain.com") - checkValidEmailAddress("e@mail.com") - } - - @Test - fun `EmailGroup should throw exception for invalid email address`() { - checkInvalidEmailAddress("email") - checkInvalidEmailAddress("email@") - checkInvalidEmailAddress("email@1234@email.com") - checkInvalidEmailAddress(".email@email.com") - checkInvalidEmailAddress("email.@email.com") - checkInvalidEmailAddress("email..1234@email.com") - checkInvalidEmailAddress("email@email..com") - checkInvalidEmailAddress("email@.com") - checkInvalidEmailAddress("email@email.com.") - checkInvalidEmailAddress("email@.email.com") - checkInvalidEmailAddress("email@email.com-") - checkInvalidEmailAddress("email@email_domain.com") - } - @Test fun `EmailGroup serialize and deserialize transport object should be equal`() { - val sampleEmailGroup = EmailGroup(listOf("email1@email.com", "email2@email.com")) + val sampleEmailGroup = EmailGroup( + listOf( + EmailRecipient("email1@email.com"), + EmailRecipient("email2@email.com") + ) + ) val recreatedObject = recreateObject(sampleEmailGroup) { EmailGroup(it) } assertEquals(sampleEmailGroup, recreatedObject) } @Test fun `EmailGroup serialize and deserialize using json object should be equal`() { - val sampleEmailGroup = EmailGroup(listOf("email1@email.com", "email2@email.com")) + val sampleEmailGroup = EmailGroup( + listOf( + EmailRecipient("email1@email.com"), + EmailRecipient("email2@email.com") + ) + ) val jsonString = getJsonString(sampleEmailGroup) val recreatedObject = createObjectFromJsonString(jsonString) { EmailGroup.parse(it) } assertEquals(sampleEmailGroup, recreatedObject) @@ -94,12 +63,17 @@ internal class EmailGroupTests { @Test fun `EmailGroup should deserialize json object using parser`() { - val sampleEmailGroup = EmailGroup(listOf("email1@email.com", "email2@email.com")) + val sampleEmailGroup = EmailGroup( + listOf( + EmailRecipient("email1@email.com"), + EmailRecipient("email2@email.com") + ) + ) val jsonString = """ { "recipient_list":[ - "${sampleEmailGroup.recipients[0]}", - "${sampleEmailGroup.recipients[1]}" + {"recipient":"${sampleEmailGroup.recipients[0].recipient}"}, + {"recipient":"${sampleEmailGroup.recipients[1].recipient}"} ] }" """.trimIndent() @@ -117,12 +91,17 @@ internal class EmailGroupTests { @Test fun `EmailGroup should throw exception when recipients is replaced with recipients2 in json object`() { - val sampleEmailGroup = EmailGroup(listOf("email1@email.com", "email2@email.com")) + val sampleEmailGroup = EmailGroup( + listOf( + EmailRecipient("email1@email.com"), + EmailRecipient("email2@email.com") + ) + ) val jsonString = """ { "recipient_list2":[ - "${sampleEmailGroup.recipients[0]}", - "${sampleEmailGroup.recipients[1]}" + {"recipient":"${sampleEmailGroup.recipients[0]}"}, + {"recipient":"${sampleEmailGroup.recipients[1]}"} ] }" """.trimIndent() @@ -133,8 +112,17 @@ internal class EmailGroupTests { @Test fun `EmailGroup should safely ignore extra field in json object`() { - val sampleEmailGroup = EmailGroup(listOf("email@email.com")) - val jsonString = "{\"recipient_list\":[\"${sampleEmailGroup.recipients[0]}\"], \"another\":\"field\"}" + val sampleEmailGroup = EmailGroup(listOf(EmailRecipient("email1@email.com"))) + val jsonString = """ + { + "recipient_list":[ + {"recipient":"${sampleEmailGroup.recipients[0].recipient}"} + ], + "extra_field_1":["extra", "value"], + "extra_field_2":{"extra":"value"}, + "extra_field_3":"extra value 3" + }" + """.trimIndent() val recreatedObject = createObjectFromJsonString(jsonString) { EmailGroup.parse(it) } assertEquals(sampleEmailGroup, recreatedObject) } diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/EmailRecipientTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/EmailRecipientTests.kt new file mode 100644 index 00000000..c2f2d36d --- /dev/null +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/EmailRecipientTests.kt @@ -0,0 +1,142 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + * + * Modifications Copyright OpenSearch Contributors. See + * GitHub history for details. + */ + +/* + * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + * + */ +package org.opensearch.commons.notifications.model + +import com.fasterxml.jackson.core.JsonParseException +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.assertDoesNotThrow +import org.junit.jupiter.api.assertThrows +import org.opensearch.commons.utils.createObjectFromJsonString +import org.opensearch.commons.utils.getJsonString +import org.opensearch.commons.utils.recreateObject + +internal class EmailRecipientTests { + + private fun checkValidEmailAddress(emailAddress: String) { + assertDoesNotThrow("should accept $emailAddress") { + EmailRecipient(emailAddress) + } + } + + private fun checkInvalidEmailAddress(emailAddress: String) { + assertThrows("Should throw an Exception for invalid email $emailAddress") { + EmailRecipient(emailAddress) + } + } + + @Test + fun `EmailRecipient should accept valid email address`() { + checkValidEmailAddress("email1234@email.com") + checkValidEmailAddress("email+1234@email.com") + checkValidEmailAddress("email-1234@email.com") + checkValidEmailAddress("email_1234@email.com") + checkValidEmailAddress("email.1234@email.com") + checkValidEmailAddress("e.ma_il-1+2@test-email-domain.co.uk") + checkValidEmailAddress("email-.+_=#|@domain.com") + checkValidEmailAddress("e@mail.com") + } + + @Test + fun `EmailRecipient should throw exception for invalid email address`() { + checkInvalidEmailAddress("email") + checkInvalidEmailAddress("email@") + checkInvalidEmailAddress("email@1234@email.com") + checkInvalidEmailAddress(".email@email.com") + checkInvalidEmailAddress("email.@email.com") + checkInvalidEmailAddress("email..1234@email.com") + checkInvalidEmailAddress("email@email..com") + checkInvalidEmailAddress("email@.com") + checkInvalidEmailAddress("email@email.com.") + checkInvalidEmailAddress("email@.email.com") + checkInvalidEmailAddress("email@email.com-") + checkInvalidEmailAddress("email@email_domain.com") + } + + @Test + fun `EmailRecipient serialize and deserialize transport object should be equal`() { + val sampleEmailRecipient = EmailRecipient("email1@email.com") + val recreatedObject = recreateObject(sampleEmailRecipient) { EmailRecipient(it) } + assertEquals(sampleEmailRecipient, recreatedObject) + } + + @Test + fun `EmailRecipient serialize and deserialize using json object should be equal`() { + val sampleEmailRecipient = EmailRecipient("email1@email.com") + val jsonString = getJsonString(sampleEmailRecipient) + val recreatedObject = createObjectFromJsonString(jsonString) { EmailRecipient.parse(it) } + assertEquals(sampleEmailRecipient, recreatedObject) + } + + @Test + fun `EmailRecipient should deserialize json object using parser`() { + val sampleEmailRecipient = EmailRecipient("email1@email.com") + val jsonString = """ + { + "recipient": "${sampleEmailRecipient.recipient}" + }" + """.trimIndent() + val recreatedObject = createObjectFromJsonString(jsonString) { EmailRecipient.parse(it) } + assertEquals(sampleEmailRecipient, recreatedObject) + } + + @Test + fun `EmailRecipient should throw exception when invalid json object is passed`() { + val jsonString = "sample message" + assertThrows { + createObjectFromJsonString(jsonString) { EmailRecipient.parse(it) } + } + } + + @Test + fun `EmailRecipient should throw exception when recipients is replaced with recipients2 in json object`() { + val sampleEmailRecipient = EmailRecipient("email1@email.com") + val jsonString = """ + { + "recipient2": "${sampleEmailRecipient.recipient}" + }" + """.trimIndent() + assertThrows { + createObjectFromJsonString(jsonString) { EmailRecipient.parse(it) } + } + } + + @Test + fun `EmailRecipient should safely ignore extra field in json object`() { + val sampleEmailRecipient = EmailRecipient("email@email.com") + val jsonString = """ + { + "recipient": "${sampleEmailRecipient.recipient}", + "extra_field_1":["extra", "value"], + "extra_field_2":{"extra":"value"}, + "extra_field_3":"extra value 3" + }" + """.trimIndent() + val recreatedObject = createObjectFromJsonString(jsonString) { EmailRecipient.parse(it) } + assertEquals(sampleEmailRecipient, recreatedObject) + } +} diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/EmailTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/EmailTests.kt index 6590f08e..8e4772f5 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/EmailTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/EmailTests.kt @@ -29,7 +29,6 @@ package org.opensearch.commons.notifications.model import com.fasterxml.jackson.core.JsonParseException import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Test -import org.junit.jupiter.api.assertDoesNotThrow import org.junit.jupiter.api.assertThrows import org.opensearch.commons.utils.createObjectFromJsonString import org.opensearch.commons.utils.getJsonString @@ -37,51 +36,14 @@ import org.opensearch.commons.utils.recreateObject internal class EmailTests { - private fun checkValidEmailAddress(emailAddress: String) { - assertDoesNotThrow("should accept $emailAddress") { - Email("sampleId", listOf(emailAddress), listOf()) - } - } - - private fun checkInvalidEmailAddress(emailAddress: String) { - assertThrows("Should throw an Exception for invalid email $emailAddress") { - Email("sampleId", listOf(emailAddress), listOf()) - } - } - - @Test - fun `Email should accept valid email address`() { - checkValidEmailAddress("email1234@email.com") - checkValidEmailAddress("email+1234@email.com") - checkValidEmailAddress("email-1234@email.com") - checkValidEmailAddress("email_1234@email.com") - checkValidEmailAddress("email.1234@email.com") - checkValidEmailAddress("e.ma_il-1+2@test-email-domain.co.uk") - checkValidEmailAddress("email-.+_=#|@domain.com") - checkValidEmailAddress("e@mail.com") - } - - @Test - fun `Email should throw exception for invalid email address`() { - checkInvalidEmailAddress("email") - checkInvalidEmailAddress("email@") - checkInvalidEmailAddress("email@1234@email.com") - checkInvalidEmailAddress(".email@email.com") - checkInvalidEmailAddress("email.@email.com") - checkInvalidEmailAddress("email..1234@email.com") - checkInvalidEmailAddress("email@email..com") - checkInvalidEmailAddress("email@.com") - checkInvalidEmailAddress("email@email.com.") - checkInvalidEmailAddress("email@.email.com") - checkInvalidEmailAddress("email@email.com-") - checkInvalidEmailAddress("email@email_domain.com") - } - @Test fun `Email serialize and deserialize transport object should be equal`() { val sampleEmail = Email( "sampleAccountId", - listOf("email1@email.com", "email2@email.com"), + listOf( + EmailRecipient("email1@email.com"), + EmailRecipient("email2@email.com") + ), listOf("sample_group_id_1", "sample_group_id_2") ) val recreatedObject = recreateObject(sampleEmail) { Email(it) } @@ -92,7 +54,10 @@ internal class EmailTests { fun `Email serialize and deserialize using json object should be equal`() { val sampleEmail = Email( "sampleAccountId", - listOf("email1@email.com", "email2@email.com"), + listOf( + EmailRecipient("email1@email.com"), + EmailRecipient("email2@email.com") + ), listOf("sample_group_id_1", "sample_group_id_2") ) val jsonString = getJsonString(sampleEmail) @@ -104,15 +69,18 @@ internal class EmailTests { fun `Email should deserialize json object using parser`() { val sampleEmail = Email( "sampleAccountId", - listOf("email1@email.com", "email2@email.com"), + listOf( + EmailRecipient("email1@email.com"), + EmailRecipient("email2@email.com") + ), listOf("sample_group_id_1", "sample_group_id_2") ) val jsonString = """ { "email_account_id":"${sampleEmail.emailAccountID}", "recipient_list":[ - "${sampleEmail.recipients[0]}", - "${sampleEmail.recipients[1]}" + {"recipient":"${sampleEmail.recipients[0].recipient}"}, + {"recipient":"${sampleEmail.recipients[1].recipient}"} ], "email_group_id_list":[ "${sampleEmail.emailGroupIds[0]}", @@ -136,15 +104,18 @@ internal class EmailTests { fun `Email should throw exception when emailAccountID is replaced with emailAccountID2 in json object`() { val sampleEmail = Email( "sampleAccountId", - listOf("email1@email.com", "email2@email.com"), + listOf( + EmailRecipient("email1@email.com"), + EmailRecipient("email2@email.com") + ), listOf("sample_group_id_1", "sample_group_id_2") ) val jsonString = """ { "email_account_id2":"${sampleEmail.emailAccountID}", "recipient_list":[ - "${sampleEmail.recipients[0]}", - "${sampleEmail.recipients[1]}" + {"recipient":"${sampleEmail.recipients[0]}"}, + {"recipient":"${sampleEmail.recipients[1]}"} ], "email_group_id_list":[ "${sampleEmail.emailGroupIds[0]}", diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationConfigTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationConfigTests.kt index c7126ab0..0a96c8ed 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationConfigTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationConfigTests.kt @@ -126,7 +126,7 @@ internal class NotificationConfigTests { @Test fun `Config serialize and deserialize with email object should be equal`() { - val sampleEmail = Email("id_1234567890", listOf("email@domain.com"), listOf("groupId")) + val sampleEmail = Email("id_1234567890", listOf(EmailRecipient("email@domain.com")), listOf("groupId")) val sampleConfig = NotificationConfig( "name", "description", @@ -140,7 +140,7 @@ internal class NotificationConfigTests { @Test fun `Config serialize and deserialize with json email object should be equal`() { - val sampleEmail = Email("id_1234567890", listOf("email@domain.com"), listOf("groupId")) + val sampleEmail = Email("id_1234567890", listOf(EmailRecipient("email@domain.com")), listOf("groupId")) val sampleConfig = NotificationConfig( "name", "description", @@ -184,7 +184,7 @@ internal class NotificationConfigTests { @Test fun `Config serialize and deserialize with json emailGroup object should be equal`() { - val sampleEmailGroup = EmailGroup(listOf("email@domain.com")) + val sampleEmailGroup = EmailGroup(listOf(EmailRecipient("email@domain.com"))) val sampleConfig = NotificationConfig( "name", "description", @@ -199,7 +199,7 @@ internal class NotificationConfigTests { @Test fun `Config serialize and deserialize with emailGroup object should be equal`() { - val sampleEmailGroup = EmailGroup(listOf("email@domain.com")) + val sampleEmailGroup = EmailGroup(listOf(EmailRecipient("email@domain.com"))) val sampleConfig = NotificationConfig( "name", "description", diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/config/ConfigPropertiesTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/config/ConfigPropertiesTests.kt index 0217c53f..80a20b88 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/config/ConfigPropertiesTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/config/ConfigPropertiesTests.kt @@ -5,6 +5,7 @@ import org.opensearch.commons.notifications.model.Chime import org.opensearch.commons.notifications.model.ConfigType import org.opensearch.commons.notifications.model.Email import org.opensearch.commons.notifications.model.EmailGroup +import org.opensearch.commons.notifications.model.EmailRecipient import org.opensearch.commons.notifications.model.MethodType import org.opensearch.commons.notifications.model.Slack import org.opensearch.commons.notifications.model.SmtpAccount @@ -72,7 +73,7 @@ internal class ConfigPropertiesTests { @Test fun `Validate config data parse EmailGroup`() { - val sampleEmailGroup = EmailGroup(listOf("email1@email.com", "email2@email.com")) + val sampleEmailGroup = EmailGroup(listOf(EmailRecipient("email1@email.com"), EmailRecipient("email2@email.com"))) val jsonString = getJsonString(sampleEmailGroup) val recreatedObject = createObjectFromJsonString(jsonString) { createConfigData(ConfigType.EMAIL_GROUP, it) } assertEquals(sampleEmailGroup, recreatedObject) From 32f0c6febebefb72d12fc1ff51c25a2c573c13b3 Mon Sep 17 00:00:00 2001 From: Mohammad Qureshi <47198598+qreshi@users.noreply.github.com> Date: Tue, 2 Nov 2021 15:13:11 -0700 Subject: [PATCH 020/140] Update copyright notice (#90) Signed-off-by: Mohammad Qureshi --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b2778b5d..fc95f76e 100644 --- a/README.md +++ b/README.md @@ -44,4 +44,4 @@ This project is licensed under the [Apache v2.0 License](LICENSE.txt). ## Copyright -Copyright 2020-2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. +Copyright OpenSearch Contributors. See [NOTICE](NOTICE.txt) for details. From 225333160429e50b37ca4c8f6bb1065b3b78457d Mon Sep 17 00:00:00 2001 From: Marc Handalian Date: Thu, 4 Nov 2021 07:16:42 -0700 Subject: [PATCH 021/140] Update maven publication to include cksums. (#91) This change adds a local staging repo task that will include cksums. It will also update build.sh to use this new task and copy the contents of the staging repo to the output directory. The maven publish plugin will not include these cksums when publishing to maven local but will when published to a separate folder. Signed-off-by: Marc Handalian --- build.gradle | 16 ++++++---------- scripts/build.sh | 3 ++- 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/build.gradle b/build.gradle index 92f71cc5..92e442ca 100644 --- a/build.gradle +++ b/build.gradle @@ -157,17 +157,13 @@ task javadocJar(type: Jar) { classifier = 'javadoc' from javadoc.destinationDir } - -tasks.withType(Jar) { task -> - task.doLast { - ant.checksum algorithm: 'md5', file: it.archivePath - ant.checksum algorithm: 'sha1', file: it.archivePath - ant.checksum algorithm: 'sha-256', file: it.archivePath, fileext: '.sha256' - ant.checksum algorithm: 'sha-512', file: it.archivePath, fileext: '.sha512' - } -} - publishing { + repositories { + maven { + name = 'staging' + url = "${rootProject.buildDir}/local-staging-repo" + } + } publications { shadow(MavenPublication) { project.shadow.component(it) diff --git a/scripts/build.sh b/scripts/build.sh index fdc9be57..891e27fc 100755 --- a/scripts/build.sh +++ b/scripts/build.sh @@ -57,5 +57,6 @@ fi ./gradlew build -Dopensearch.version=$VERSION -Dbuild.snapshot=$SNAPSHOT ./gradlew publishShadowPublicationToMavenLocal -Dopensearch.version=$VERSION -Dbuild.snapshot=$SNAPSHOT +./gradlew publishShadowPublicationToStagingRepository -Dopensearch.version=$VERSION -Dbuild.snapshot=$SNAPSHOT mkdir -p $OUTPUT/maven/org/opensearch -cp -r ./build/libs $OUTPUT/maven/org/opensearch/common-utils +cp -r ./build/local-staging-repo/org/opensearch/common-utils $OUTPUT/maven/org/opensearch/common-utils From 2679a01d39a1f0daf87201ff9fe24a6f04b77ea1 Mon Sep 17 00:00:00 2001 From: Ashish Agrawal Date: Fri, 5 Nov 2021 16:24:52 -0700 Subject: [PATCH 022/140] Add release notes for version 1.2.0.0 (#92) * Add release notes for version 1.2.0.0 Signed-off-by: Ashish Agrawal --- ...pensearch-common-utils.release-notes-1.2.0.0.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 release-notes/opensearch-common-utils.release-notes-1.2.0.0.md diff --git a/release-notes/opensearch-common-utils.release-notes-1.2.0.0.md b/release-notes/opensearch-common-utils.release-notes-1.2.0.0.md new file mode 100644 index 00000000..afb92873 --- /dev/null +++ b/release-notes/opensearch-common-utils.release-notes-1.2.0.0.md @@ -0,0 +1,14 @@ +## Version 1.2.0.0 2021-11-05 + +Compatible with OpenSearch 1.2.0 + +### Infrastructure + + * Updates common-utils version to 1.2 ([#77](https://github.com/opensearch-project/common-utils/pull/77)) + * Update maven publication to include cksums. ([#91](https://github.com/opensearch-project/common-utils/pull/91)) + +### Documentation + + * Add themed logo to README ([#41](https://github.com/opensearch-project/common-utils/pull/41)) + * Update copyright notice ([#90](https://github.com/opensearch-project/common-utils/pull/90)) + * Add release notes for version 1.2.0.0 ([#92](https://github.com/opensearch-project/common-utils/pull/92)) \ No newline at end of file From 84bb45720fcb8570aad203547cd17354541bebf6 Mon Sep 17 00:00:00 2001 From: Ashish Agrawal Date: Mon, 8 Nov 2021 16:06:09 -0800 Subject: [PATCH 023/140] Fix copyright notice and add DCO check workflow (#94) Signed-off-by: Ashish Agrawal --- .github/workflows/dco.yml | 18 ++++++++++++++ CONTRIBUTING.md | 49 ++++++++++++++++++++++++++++++++++++++- NOTICE | 4 ++-- 3 files changed, 68 insertions(+), 3 deletions(-) create mode 100644 .github/workflows/dco.yml diff --git a/.github/workflows/dco.yml b/.github/workflows/dco.yml new file mode 100644 index 00000000..53ed5304 --- /dev/null +++ b/.github/workflows/dco.yml @@ -0,0 +1,18 @@ +name: Developer Certificate of Origin Check + +on: [pull_request] + +jobs: + check: + runs-on: ubuntu-latest + + steps: + - name: Get PR Commits + id: 'get-pr-commits' + uses: tim-actions/get-pr-commits@v1.1.0 + with: + token: ${{ secrets.GITHUB_TOKEN }} + - name: DCO Check + uses: tim-actions/dco@v1.1.0 + with: + commits: ${{ steps.get-pr-commits.outputs.commits }} \ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c970f9d3..c25787ad 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,4 +1,51 @@ ## Contributing to this Project OpenSearch is a community project that is built and maintained by people just like **you**. -[This document](https://github.com/opensearch-project/.github/blob/main/CONTRIBUTING.md) explains how you can contribute to this and related projects. \ No newline at end of file +[This document](https://github.com/opensearch-project/.github/blob/main/CONTRIBUTING.md) explains how you can contribute to this and related projects. + +## Developer Certificate of Origin + +OpenSearch is an open source product released under the Apache 2.0 license (see either [the Apache site](https://www.apache.org/licenses/LICENSE-2.0) or the [LICENSE.txt file](LICENSE.txt)). The Apache 2.0 license allows you to freely use, modify, distribute, and sell your own products that include Apache 2.0 licensed software. + +We respect intellectual property rights of others and we want to make sure all incoming contributions are correctly attributed and licensed. A Developer Certificate of Origin (DCO) is a lightweight mechanism to do that. + +The DCO is a declaration attached to every contribution made by every developer. In the commit message of the contribution, the developer simply adds a `Signed-off-by` statement and thereby agrees to the DCO, which you can find below or at [DeveloperCertificate.org](http://developercertificate.org/). + +``` +Developer's Certificate of Origin 1.1 + +By making a contribution to this project, I certify that: + +(a) The contribution was created in whole or in part by me and I + have the right to submit it under the open source license + indicated in the file; or + +(b) The contribution is based upon previous work that, to the + best of my knowledge, is covered under an appropriate open + source license and I have the right under that license to + submit that work with modifications, whether created in whole + or in part by me, under the same open source license (unless + I am permitted to submit under a different license), as + Indicated in the file; or + +(c) The contribution was provided directly to me by some other + person who certified (a), (b) or (c) and I have not modified + it. + +(d) I understand and agree that this project and the contribution + are public and that a record of the contribution (including + all personal information I submit with it, including my + sign-off) is maintained indefinitely and may be redistributed + consistent with this project or the open source license(s) + involved. + ``` + +We require that every contribution to OpenSearch is signed with a Developer Certificate of Origin. Additionally, please use your real name. We do not accept anonymous contributors nor those utilizing pseudonyms. + +Each commit must include a DCO which looks like this + +``` +Signed-off-by: Jane Smith +``` + +You may type this line on your own when writing your commit messages. However, if your user.name and user.email are set in your git configs, you can use `-s` or `– – signoff` to add the `Signed-off-by` line to the end of the commit message. \ No newline at end of file diff --git a/NOTICE b/NOTICE index be83767d..6c7dc983 100644 --- a/NOTICE +++ b/NOTICE @@ -1,5 +1,5 @@ -OpenSearch -Copyright 2021 OpenSearch Contributors +OpenSearch (https://opensearch.org/) +Copyright OpenSearch Contributors This product includes software developed by Elasticsearch (http://www.elastic.co). From eb79baeac41e75fa09ee8b9c3c5778ab40fb5937 Mon Sep 17 00:00:00 2001 From: Marc Handalian Date: Fri, 12 Nov 2021 06:29:39 -0800 Subject: [PATCH 024/140] Update build.sh script to include optional platform param. (#95) Signed-off-by: Marc Handalian --- scripts/build.sh | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/scripts/build.sh b/scripts/build.sh index 891e27fc..f68dc52e 100755 --- a/scripts/build.sh +++ b/scripts/build.sh @@ -11,12 +11,13 @@ function usage() { echo "Arguments:" echo -e "-v VERSION\t[Required] OpenSearch version." echo -e "-s SNAPSHOT\t[Optional] Build a snapshot, default is 'false'." + echo -e "-p PLATFORM\t[Optional] Platform, ignored." echo -e "-a ARCHITECTURE\t[Optional] Build architecture, ignored." echo -e "-o OUTPUT\t[Optional] Output path, default is 'artifacts'." echo -e "-h help" } -while getopts ":h:v:s:o:a:" arg; do +while getopts ":h:v:s:o:p:a:" arg; do case $arg in h) usage @@ -31,6 +32,9 @@ while getopts ":h:v:s:o:a:" arg; do o) OUTPUT=$OPTARG ;; + p) + PLATFORM=$OPTARG + ;; a) ARCHITECTURE=$OPTARG ;; From 2ebb5e66bdc1ce44b25daabe5dbb73517046e0de Mon Sep 17 00:00:00 2001 From: Ryan Bogan <10944539+ryanbogan@users.noreply.github.com> Date: Fri, 12 Nov 2021 17:37:12 -0500 Subject: [PATCH 025/140] Add codeowners support for repo (#96) Signed-off-by: Ryan Bogan --- .github/CODEOWNERS | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 .github/CODEOWNERS diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 00000000..b57ed5c8 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,2 @@ +# This should match the owning team set up in https://github.com/orgs/opensearch-project/teams +* @opensearch-project/common-utils \ No newline at end of file From 19ca2c084c7e306dde88246cd0f1c749c6fa47b4 Mon Sep 17 00:00:00 2001 From: Ashish Agrawal Date: Wed, 1 Dec 2021 16:48:53 -0800 Subject: [PATCH 026/140] Bump version to 1.3 (#99) Signed-off-by: Ashish Agrawal --- .github/workflows/ci.yml | 4 ++-- build.gradle | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 52eea2f1..badeafda 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -28,11 +28,11 @@ jobs: # common-utils - name: Build and Test run: | - ./gradlew build -Dopensearch.version=1.2.0-SNAPSHOT + ./gradlew build -Dopensearch.version=1.3.0-SNAPSHOT - name: Publish to Maven Local run: | - ./gradlew publishToMavenLocal -Dopensearch.version=1.2.0-SNAPSHOT + ./gradlew publishToMavenLocal -Dopensearch.version=1.3.0-SNAPSHOT - name: Upload Coverage Report uses: codecov/codecov-action@v1 diff --git a/build.gradle b/build.gradle index 92e442ca..9b97f0ac 100644 --- a/build.gradle +++ b/build.gradle @@ -12,7 +12,7 @@ buildscript { ext { opensearch_group = "org.opensearch" - opensearch_version = System.getProperty("opensearch.version", "1.2.0-SNAPSHOT") + opensearch_version = System.getProperty("opensearch.version", "1.3.0-SNAPSHOT") kotlin_version = System.getProperty("kotlin.version", "1.4.32") } From 643157d7e21c462cba4fbc3c64b36f6efa43fef6 Mon Sep 17 00:00:00 2001 From: "Daniel Doubrovkine (dB.)" Date: Tue, 4 Jan 2022 19:26:01 +0000 Subject: [PATCH 027/140] Auto-increment version on new release tags. (#106) Signed-off-by: dblock --- .github/workflows/ci.yml | 4 ++-- .github/workflows/version.yml | 42 +++++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 2 deletions(-) create mode 100644 .github/workflows/version.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index badeafda..c35e0c0a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -28,11 +28,11 @@ jobs: # common-utils - name: Build and Test run: | - ./gradlew build -Dopensearch.version=1.3.0-SNAPSHOT + ./gradlew build - name: Publish to Maven Local run: | - ./gradlew publishToMavenLocal -Dopensearch.version=1.3.0-SNAPSHOT + ./gradlew publishToMavenLocal - name: Upload Coverage Report uses: codecov/codecov-action@v1 diff --git a/.github/workflows/version.yml b/.github/workflows/version.yml new file mode 100644 index 00000000..196a690d --- /dev/null +++ b/.github/workflows/version.yml @@ -0,0 +1,42 @@ +name: Increment Version + +on: + push: + tags: + - '*.*.*.*' + +jobs: + build: + runs-on: ubuntu-latest + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + steps: + - uses: actions/checkout@v2 + - name: Fetch Tag and Version Information + run: | + TAG=$(echo "${GITHUB_REF#refs/*/}") + CURRENT_VERSION_ARRAY=($(echo "$TAG" | tr . '\n')) + BASE=$(IFS=. ; echo "${CURRENT_VERSION_ARRAY[*]:0:2}") + CURRENT_VERSION=$(IFS=. ; echo "${CURRENT_VERSION_ARRAY[*]:0:3}") + CURRENT_VERSION_ARRAY[2]=$((CURRENT_VERSION_ARRAY[2]+1)) + NEXT_VERSION=$(IFS=. ; echo "${CURRENT_VERSION_ARRAY[*]:0:3}") + echo "TAG=$TAG" >> $GITHUB_ENV + echo "BASE=$BASE" >> $GITHUB_ENV + echo "CURRENT_VERSION=$CURRENT_VERSION" >> $GITHUB_ENV + echo "NEXT_VERSION=$NEXT_VERSION" >> $GITHUB_ENV + - uses: actions/checkout@v2 + with: + ref: ${{ env.BASE }} + - name: Increment Version + run: | + echo Incrementing $CURRENT_VERSION to $NEXT_VERSION + sed -i "s/$CURRENT_VERSION-SNAPSHOT/$NEXT_VERSION-SNAPSHOT/g" build.gradle + - name: Create Pull Request + uses: peter-evans/create-pull-request@v3 + with: + base: ${{ env.BASE }} + commit-message: Incremented version to ${{ env.NEXT_VERSION }} + delete-branch: true + title: '[AUTO] Incremented version to ${{ env.NEXT_VERSION }}.' + body: | + I've noticed that a new tag ${{ env.TAG }} was pushed, and incremented the version from ${{ env.CURRENT_VERSION }} to ${{ env.NEXT_VERSION }}. From 7c0460dba284d7122e9e45117b6ad8a954bc19f2 Mon Sep 17 00:00:00 2001 From: Peter Nied Date: Thu, 17 Feb 2022 15:53:56 -0600 Subject: [PATCH 028/140] Remove jcenter repository (#115) --- build.gradle | 1 - 1 file changed, 1 deletion(-) diff --git a/build.gradle b/build.gradle index 9b97f0ac..43974b0b 100644 --- a/build.gradle +++ b/build.gradle @@ -20,7 +20,6 @@ buildscript { mavenLocal() mavenCentral() maven { url "https://plugins.gradle.org/m2/" } - jcenter() maven { url "https://aws.oss.sonatype.org/content/repositories/snapshots" } } From 31fd4112b162fcded3be378ba7e788fa4f44287b Mon Sep 17 00:00:00 2001 From: Vacha Shah Date: Fri, 18 Feb 2022 17:30:12 -0800 Subject: [PATCH 029/140] Using Github App token to trigger CI for version increment PRs (#116) Signed-off-by: Vacha Shah --- .github/workflows/version.yml | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/.github/workflows/version.yml b/.github/workflows/version.yml index 196a690d..8ca31d8e 100644 --- a/.github/workflows/version.yml +++ b/.github/workflows/version.yml @@ -8,9 +8,15 @@ on: jobs: build: runs-on: ubuntu-latest - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} steps: + - name: GitHub App token + id: github_app_token + uses: tibdex/github-app-token@v1.5.0 + with: + app_id: ${{ secrets.APP_ID }} + private_key: ${{ secrets.APP_PRIVATE_KEY }} + installation_id: 22958780 + - uses: actions/checkout@v2 - name: Fetch Tag and Version Information run: | @@ -27,13 +33,17 @@ jobs: - uses: actions/checkout@v2 with: ref: ${{ env.BASE }} + token: ${{ steps.github_app_token.outputs.token }} + - name: Increment Version run: | echo Incrementing $CURRENT_VERSION to $NEXT_VERSION sed -i "s/$CURRENT_VERSION-SNAPSHOT/$NEXT_VERSION-SNAPSHOT/g" build.gradle + - name: Create Pull Request uses: peter-evans/create-pull-request@v3 with: + token: ${{ steps.github_app_token.outputs.token }} base: ${{ env.BASE }} commit-message: Incremented version to ${{ env.NEXT_VERSION }} delete-branch: true From bccb1bb329517c3c550df9b8fd9df81bbf05e4f1 Mon Sep 17 00:00:00 2001 From: Drew Baugher <46505179+dbbaughe@users.noreply.github.com> Date: Mon, 21 Feb 2022 11:08:03 -0800 Subject: [PATCH 030/140] Fixes copyright headers (#117) Signed-off-by: Drew Baugher <46505179+dbbaughe@users.noreply.github.com> --- build.gradle | 8 +------ detekt.yml | 8 +------ settings.gradle | 8 +------ spotless.license.java | 23 +----------------- .../opensearch/commons/ConfigConstants.java | 23 +----------------- .../opensearch/commons/InjectSecurity.java | 23 +----------------- .../authuser/AuthUserRequestBuilder.java | 23 +----------------- .../org/opensearch/commons/authuser/User.java | 23 +----------------- .../message/LegacyBaseMessage.java | 23 +----------------- .../message/LegacyChimeMessage.java | 23 +----------------- .../message/LegacyCustomWebhookMessage.java | 23 +----------------- .../message/LegacyDestinationType.java | 23 +----------------- .../message/LegacySlackMessage.java | 23 +----------------- .../response/LegacyBaseResponse.java | 23 +----------------- .../response/LegacyDestinationResponse.java | 23 +----------------- .../commons/rest/SecureRestClientBuilder.java | 23 +----------------- .../opensearch/commons/rest/TrustStore.java | 23 +----------------- .../NotificationsPluginInterface.kt | 24 +------------------ .../notifications/action/BaseResponse.kt | 24 +------------------ .../action/CreateNotificationConfigRequest.kt | 24 +------------------ .../CreateNotificationConfigResponse.kt | 24 +------------------ .../action/DeleteNotificationConfigRequest.kt | 24 +------------------ .../DeleteNotificationConfigResponse.kt | 24 +------------------ .../action/GetFeatureChannelListRequest.kt | 24 +------------------ .../action/GetFeatureChannelListResponse.kt | 24 +------------------ .../action/GetNotificationConfigRequest.kt | 24 +------------------ .../action/GetNotificationConfigResponse.kt | 24 +------------------ .../action/GetNotificationEventRequest.kt | 24 +------------------ .../action/GetNotificationEventResponse.kt | 24 +------------------ .../action/GetPluginFeaturesRequest.kt | 24 +------------------ .../action/GetPluginFeaturesResponse.kt | 24 +------------------ .../LegacyPublishNotificationRequest.kt | 8 +------ .../LegacyPublishNotificationResponse.kt | 8 +------ .../action/NotificationsActions.kt | 24 +------------------ .../action/SendNotificationRequest.kt | 24 +------------------ .../action/SendNotificationResponse.kt | 24 +------------------ .../action/UpdateNotificationConfigRequest.kt | 24 +------------------ .../UpdateNotificationConfigResponse.kt | 24 +------------------ .../commons/notifications/model/Attachment.kt | 24 +------------------ .../notifications/model/BaseConfigData.kt | 24 +------------------ .../commons/notifications/model/BaseModel.kt | 24 +------------------ .../notifications/model/ChannelMessage.kt | 24 +------------------ .../commons/notifications/model/Chime.kt | 24 +------------------ .../commons/notifications/model/ConfigType.kt | 24 +------------------ .../notifications/model/DeliveryStatus.kt | 24 +------------------ .../commons/notifications/model/Email.kt | 24 +------------------ .../commons/notifications/model/EmailGroup.kt | 24 +------------------ .../notifications/model/EmailRecipient.kt | 24 +------------------ .../model/EmailRecipientStatus.kt | 24 +------------------ .../notifications/model/EventSource.kt | 24 +------------------ .../notifications/model/EventStatus.kt | 24 +------------------ .../notifications/model/FeatureChannel.kt | 24 +------------------ .../notifications/model/FeatureChannelList.kt | 24 +------------------ .../notifications/model/NotificationConfig.kt | 24 +------------------ .../model/NotificationConfigInfo.kt | 23 +----------------- .../model/NotificationConfigSearchResult.kt | 24 +------------------ .../notifications/model/NotificationEvent.kt | 24 +------------------ .../model/NotificationEventInfo.kt | 24 +------------------ .../model/NotificationEventSearchResult.kt | 24 +------------------ .../notifications/model/SearchResults.kt | 24 +------------------ .../commons/notifications/model/SesAccount.kt | 8 +------ .../notifications/model/SeverityType.kt | 24 +------------------ .../commons/notifications/model/Slack.kt | 24 +------------------ .../notifications/model/SmtpAccount.kt | 24 +------------------ .../commons/notifications/model/Sns.kt | 9 ++----- .../commons/notifications/model/Webhook.kt | 24 +------------------ .../commons/notifications/model/XParser.kt | 24 +------------------ .../model/config/ConfigDataProperties.kt | 24 +------------------ .../opensearch/commons/utils/EnumHelpers.kt | 24 +------------------ .../opensearch/commons/utils/EnumParser.kt | 24 +------------------ .../org/opensearch/commons/utils/Helpers.kt | 24 +------------------ .../commons/utils/OpenForTesting.kt | 24 +------------------ .../commons/utils/SecureClientWrapper.kt | 24 +------------------ .../commons/utils/TransportHelpers.kt | 24 +------------------ .../commons/utils/ValidationHelpers.kt | 24 +------------------ .../commons/utils/XContentHelpers.kt | 24 +------------------ .../commons/InjectSecurityTest.java | 23 +----------------- .../opensearch/commons/authuser/UserTest.java | 23 +----------------- .../message/LegacyChimeMessageTest.java | 23 +----------------- .../LegacyCustomWebhookMessageTest.java | 23 +----------------- .../message/LegacySlackMessageTest.java | 23 +----------------- .../LegacyDestinationResponseTest.java | 23 +----------------- .../commons/rest/IntegrationTests.java | 23 +----------------- .../rest/SecureRestClientBuilderTest.java | 23 +----------------- .../commons/rest/TrustStoreTest.java | 23 +----------------- .../NotificationsPluginInterfaceTests.kt | 9 ++----- .../CreateNotificationConfigRequestTests.kt | 24 +------------------ .../CreateNotificationConfigResponseTests.kt | 24 +------------------ .../DeleteNotificationConfigRequestTests.kt | 24 +------------------ .../DeleteNotificationConfigResponseTests.kt | 24 +------------------ .../GetFeatureChannelListRequestTests.kt | 24 +------------------ .../GetFeatureChannelListResponseTests.kt | 24 +------------------ .../GetNotificationConfigRequestTests.kt | 24 +------------------ .../GetNotificationConfigResponseTests.kt | 24 +------------------ .../GetNotificationEventRequestTests.kt | 24 +------------------ .../GetNotificationEventResponseTests.kt | 24 +------------------ .../action/GetPluginFeaturesRequestTests.kt | 24 +------------------ .../action/GetPluginFeaturesResponseTests.kt | 24 +------------------ .../LegacyPublishNotificationRequestTests.kt | 8 +------ .../LegacyPublishNotificationResponseTests.kt | 8 +------ .../action/SendNotificationRequestTests.kt | 24 +------------------ .../action/SendNotificationResponseTests.kt | 24 +------------------ .../UpdateNotificationConfigRequestTests.kt | 24 +------------------ .../UpdateNotificationConfigResponseTests.kt | 24 +------------------ .../notifications/model/AttachmentTests.kt | 24 +------------------ .../model/ChannelMessageTests.kt | 24 +------------------ .../commons/notifications/model/ChimeTests.kt | 24 +------------------ .../notifications/model/ConfigTypeTests.kt | 24 +------------------ .../model/DeliveryStatusTests.kt | 24 +------------------ .../notifications/model/EmailGroupTests.kt | 24 +------------------ .../model/EmailRecipientStatusTests.kt | 24 +------------------ .../model/EmailRecipientTests.kt | 24 +------------------ .../commons/notifications/model/EmailTests.kt | 24 +------------------ .../notifications/model/EventSourceTests.kt | 24 +------------------ .../notifications/model/EventStatusTests.kt | 24 +------------------ .../model/FeatureChannelListTests.kt | 24 +------------------ .../model/FeatureChannelTests.kt | 24 +------------------ .../model/FilterConfigListTests.kt | 24 +------------------ .../notifications/model/FilterConfigTests.kt | 24 +------------------ .../notifications/model/MethodTypeTests.kt | 24 +------------------ .../model/NotificationConfigInfoTests.kt | 24 +------------------ .../NotificationConfigSearchResultsTests.kt | 24 +------------------ .../model/NotificationConfigTests.kt | 24 +------------------ .../model/NotificationEventInfoTests.kt | 24 +------------------ .../NotificationEventSearchResultTests.kt | 24 +------------------ .../model/NotificationEventTests.kt | 24 +------------------ .../notifications/model/SesAccountTests.kt | 8 +------ .../notifications/model/SeverityTypeTests.kt | 24 +------------------ .../commons/notifications/model/SlackTests.kt | 24 +------------------ .../notifications/model/SmtpAccountTests.kt | 24 +------------------ .../commons/notifications/model/SnsTests.kt | 8 +------ .../notifications/model/WebhookTests.kt | 24 +------------------ .../opensearch/commons/utils/TestHelpers.kt | 24 +------------------ 133 files changed, 135 insertions(+), 2843 deletions(-) diff --git a/build.gradle b/build.gradle index 43974b0b..07768d30 100644 --- a/build.gradle +++ b/build.gradle @@ -1,12 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. */ buildscript { diff --git a/detekt.yml b/detekt.yml index 34ed3c1e..251da688 100644 --- a/detekt.yml +++ b/detekt.yml @@ -1,14 +1,8 @@ --- # +# Copyright OpenSearch Contributors # SPDX-License-Identifier: Apache-2.0 # -# The OpenSearch Contributors require contributions made to -# this file be licensed under the Apache-2.0 license or a -# compatible open source license. -# -# Modifications Copyright OpenSearch Contributors. See -# GitHub history for details. -# style: ForbiddenComment: diff --git a/settings.gradle b/settings.gradle index 7fa821ef..59d3dd1c 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,12 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. */ rootProject.name = 'common-utils' \ No newline at end of file diff --git a/spotless.license.java b/spotless.license.java index 01b9ea6c..9e182dcd 100644 --- a/spotless.license.java +++ b/spotless.license.java @@ -1,26 +1,5 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. */ diff --git a/src/main/java/org/opensearch/commons/ConfigConstants.java b/src/main/java/org/opensearch/commons/ConfigConstants.java index d7516dbc..6fc6e362 100644 --- a/src/main/java/org/opensearch/commons/ConfigConstants.java +++ b/src/main/java/org/opensearch/commons/ConfigConstants.java @@ -1,27 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. */ package org.opensearch.commons; diff --git a/src/main/java/org/opensearch/commons/InjectSecurity.java b/src/main/java/org/opensearch/commons/InjectSecurity.java index 2240ab60..f2644c29 100644 --- a/src/main/java/org/opensearch/commons/InjectSecurity.java +++ b/src/main/java/org/opensearch/commons/InjectSecurity.java @@ -1,27 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. */ package org.opensearch.commons; diff --git a/src/main/java/org/opensearch/commons/authuser/AuthUserRequestBuilder.java b/src/main/java/org/opensearch/commons/authuser/AuthUserRequestBuilder.java index c4b32e5f..32602744 100644 --- a/src/main/java/org/opensearch/commons/authuser/AuthUserRequestBuilder.java +++ b/src/main/java/org/opensearch/commons/authuser/AuthUserRequestBuilder.java @@ -1,27 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. */ package org.opensearch.commons.authuser; diff --git a/src/main/java/org/opensearch/commons/authuser/User.java b/src/main/java/org/opensearch/commons/authuser/User.java index 017405e9..f698d36b 100644 --- a/src/main/java/org/opensearch/commons/authuser/User.java +++ b/src/main/java/org/opensearch/commons/authuser/User.java @@ -1,27 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. */ package org.opensearch.commons.authuser; diff --git a/src/main/java/org/opensearch/commons/destination/message/LegacyBaseMessage.java b/src/main/java/org/opensearch/commons/destination/message/LegacyBaseMessage.java index b5122f31..96bd06ba 100644 --- a/src/main/java/org/opensearch/commons/destination/message/LegacyBaseMessage.java +++ b/src/main/java/org/opensearch/commons/destination/message/LegacyBaseMessage.java @@ -1,27 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. */ package org.opensearch.commons.destination.message; diff --git a/src/main/java/org/opensearch/commons/destination/message/LegacyChimeMessage.java b/src/main/java/org/opensearch/commons/destination/message/LegacyChimeMessage.java index b457d9aa..31b45d1f 100644 --- a/src/main/java/org/opensearch/commons/destination/message/LegacyChimeMessage.java +++ b/src/main/java/org/opensearch/commons/destination/message/LegacyChimeMessage.java @@ -1,27 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. */ package org.opensearch.commons.destination.message; diff --git a/src/main/java/org/opensearch/commons/destination/message/LegacyCustomWebhookMessage.java b/src/main/java/org/opensearch/commons/destination/message/LegacyCustomWebhookMessage.java index 9645b327..d0421ca9 100644 --- a/src/main/java/org/opensearch/commons/destination/message/LegacyCustomWebhookMessage.java +++ b/src/main/java/org/opensearch/commons/destination/message/LegacyCustomWebhookMessage.java @@ -1,27 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. */ package org.opensearch.commons.destination.message; diff --git a/src/main/java/org/opensearch/commons/destination/message/LegacyDestinationType.java b/src/main/java/org/opensearch/commons/destination/message/LegacyDestinationType.java index 85689510..ab50649b 100644 --- a/src/main/java/org/opensearch/commons/destination/message/LegacyDestinationType.java +++ b/src/main/java/org/opensearch/commons/destination/message/LegacyDestinationType.java @@ -1,27 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. */ package org.opensearch.commons.destination.message; diff --git a/src/main/java/org/opensearch/commons/destination/message/LegacySlackMessage.java b/src/main/java/org/opensearch/commons/destination/message/LegacySlackMessage.java index f426894a..02d30bb4 100644 --- a/src/main/java/org/opensearch/commons/destination/message/LegacySlackMessage.java +++ b/src/main/java/org/opensearch/commons/destination/message/LegacySlackMessage.java @@ -1,27 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. */ package org.opensearch.commons.destination.message; diff --git a/src/main/java/org/opensearch/commons/destination/response/LegacyBaseResponse.java b/src/main/java/org/opensearch/commons/destination/response/LegacyBaseResponse.java index bbdd8d70..4d34b67f 100644 --- a/src/main/java/org/opensearch/commons/destination/response/LegacyBaseResponse.java +++ b/src/main/java/org/opensearch/commons/destination/response/LegacyBaseResponse.java @@ -1,27 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. */ package org.opensearch.commons.destination.response; diff --git a/src/main/java/org/opensearch/commons/destination/response/LegacyDestinationResponse.java b/src/main/java/org/opensearch/commons/destination/response/LegacyDestinationResponse.java index bb927747..d55f5f3d 100644 --- a/src/main/java/org/opensearch/commons/destination/response/LegacyDestinationResponse.java +++ b/src/main/java/org/opensearch/commons/destination/response/LegacyDestinationResponse.java @@ -1,27 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. */ package org.opensearch.commons.destination.response; diff --git a/src/main/java/org/opensearch/commons/rest/SecureRestClientBuilder.java b/src/main/java/org/opensearch/commons/rest/SecureRestClientBuilder.java index 109809a8..96af1540 100644 --- a/src/main/java/org/opensearch/commons/rest/SecureRestClientBuilder.java +++ b/src/main/java/org/opensearch/commons/rest/SecureRestClientBuilder.java @@ -1,27 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. */ package org.opensearch.commons.rest; diff --git a/src/main/java/org/opensearch/commons/rest/TrustStore.java b/src/main/java/org/opensearch/commons/rest/TrustStore.java index 95f23796..52832b32 100644 --- a/src/main/java/org/opensearch/commons/rest/TrustStore.java +++ b/src/main/java/org/opensearch/commons/rest/TrustStore.java @@ -1,27 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. */ package org.opensearch.commons.rest; diff --git a/src/main/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterface.kt b/src/main/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterface.kt index c0646d2d..d406bb00 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterface.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterface.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications diff --git a/src/main/kotlin/org/opensearch/commons/notifications/action/BaseResponse.kt b/src/main/kotlin/org/opensearch/commons/notifications/action/BaseResponse.kt index 4bfa2271..e0659e8f 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/action/BaseResponse.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/action/BaseResponse.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.action diff --git a/src/main/kotlin/org/opensearch/commons/notifications/action/CreateNotificationConfigRequest.kt b/src/main/kotlin/org/opensearch/commons/notifications/action/CreateNotificationConfigRequest.kt index e62e92dd..dfbd1b95 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/action/CreateNotificationConfigRequest.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/action/CreateNotificationConfigRequest.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.action diff --git a/src/main/kotlin/org/opensearch/commons/notifications/action/CreateNotificationConfigResponse.kt b/src/main/kotlin/org/opensearch/commons/notifications/action/CreateNotificationConfigResponse.kt index 742e7be5..e8bce5af 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/action/CreateNotificationConfigResponse.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/action/CreateNotificationConfigResponse.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.action diff --git a/src/main/kotlin/org/opensearch/commons/notifications/action/DeleteNotificationConfigRequest.kt b/src/main/kotlin/org/opensearch/commons/notifications/action/DeleteNotificationConfigRequest.kt index 3699369f..1bcd355a 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/action/DeleteNotificationConfigRequest.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/action/DeleteNotificationConfigRequest.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.action diff --git a/src/main/kotlin/org/opensearch/commons/notifications/action/DeleteNotificationConfigResponse.kt b/src/main/kotlin/org/opensearch/commons/notifications/action/DeleteNotificationConfigResponse.kt index e701daa2..efb68005 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/action/DeleteNotificationConfigResponse.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/action/DeleteNotificationConfigResponse.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.action diff --git a/src/main/kotlin/org/opensearch/commons/notifications/action/GetFeatureChannelListRequest.kt b/src/main/kotlin/org/opensearch/commons/notifications/action/GetFeatureChannelListRequest.kt index ba6e3b19..901b4040 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/action/GetFeatureChannelListRequest.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/action/GetFeatureChannelListRequest.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.action diff --git a/src/main/kotlin/org/opensearch/commons/notifications/action/GetFeatureChannelListResponse.kt b/src/main/kotlin/org/opensearch/commons/notifications/action/GetFeatureChannelListResponse.kt index 455109fc..79bf4435 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/action/GetFeatureChannelListResponse.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/action/GetFeatureChannelListResponse.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.action diff --git a/src/main/kotlin/org/opensearch/commons/notifications/action/GetNotificationConfigRequest.kt b/src/main/kotlin/org/opensearch/commons/notifications/action/GetNotificationConfigRequest.kt index a410fe7e..a78d0d51 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/action/GetNotificationConfigRequest.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/action/GetNotificationConfigRequest.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.action diff --git a/src/main/kotlin/org/opensearch/commons/notifications/action/GetNotificationConfigResponse.kt b/src/main/kotlin/org/opensearch/commons/notifications/action/GetNotificationConfigResponse.kt index a810759b..1825ccca 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/action/GetNotificationConfigResponse.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/action/GetNotificationConfigResponse.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.action diff --git a/src/main/kotlin/org/opensearch/commons/notifications/action/GetNotificationEventRequest.kt b/src/main/kotlin/org/opensearch/commons/notifications/action/GetNotificationEventRequest.kt index 27e20554..66bfba6a 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/action/GetNotificationEventRequest.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/action/GetNotificationEventRequest.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.action diff --git a/src/main/kotlin/org/opensearch/commons/notifications/action/GetNotificationEventResponse.kt b/src/main/kotlin/org/opensearch/commons/notifications/action/GetNotificationEventResponse.kt index 176d95ea..c512aa48 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/action/GetNotificationEventResponse.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/action/GetNotificationEventResponse.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.action diff --git a/src/main/kotlin/org/opensearch/commons/notifications/action/GetPluginFeaturesRequest.kt b/src/main/kotlin/org/opensearch/commons/notifications/action/GetPluginFeaturesRequest.kt index 8b9b81b4..9437f376 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/action/GetPluginFeaturesRequest.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/action/GetPluginFeaturesRequest.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.action diff --git a/src/main/kotlin/org/opensearch/commons/notifications/action/GetPluginFeaturesResponse.kt b/src/main/kotlin/org/opensearch/commons/notifications/action/GetPluginFeaturesResponse.kt index dde25709..1e6fa2b9 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/action/GetPluginFeaturesResponse.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/action/GetPluginFeaturesResponse.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.action diff --git a/src/main/kotlin/org/opensearch/commons/notifications/action/LegacyPublishNotificationRequest.kt b/src/main/kotlin/org/opensearch/commons/notifications/action/LegacyPublishNotificationRequest.kt index e5807102..eb5080cf 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/action/LegacyPublishNotificationRequest.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/action/LegacyPublishNotificationRequest.kt @@ -1,12 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. */ package org.opensearch.commons.notifications.action diff --git a/src/main/kotlin/org/opensearch/commons/notifications/action/LegacyPublishNotificationResponse.kt b/src/main/kotlin/org/opensearch/commons/notifications/action/LegacyPublishNotificationResponse.kt index 60f68e71..f7311da2 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/action/LegacyPublishNotificationResponse.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/action/LegacyPublishNotificationResponse.kt @@ -1,12 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. */ package org.opensearch.commons.notifications.action diff --git a/src/main/kotlin/org/opensearch/commons/notifications/action/NotificationsActions.kt b/src/main/kotlin/org/opensearch/commons/notifications/action/NotificationsActions.kt index d93dd29a..10605cac 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/action/NotificationsActions.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/action/NotificationsActions.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.action diff --git a/src/main/kotlin/org/opensearch/commons/notifications/action/SendNotificationRequest.kt b/src/main/kotlin/org/opensearch/commons/notifications/action/SendNotificationRequest.kt index 9943ed57..9f4d3159 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/action/SendNotificationRequest.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/action/SendNotificationRequest.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.action diff --git a/src/main/kotlin/org/opensearch/commons/notifications/action/SendNotificationResponse.kt b/src/main/kotlin/org/opensearch/commons/notifications/action/SendNotificationResponse.kt index 38338fc5..96599b3a 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/action/SendNotificationResponse.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/action/SendNotificationResponse.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.action diff --git a/src/main/kotlin/org/opensearch/commons/notifications/action/UpdateNotificationConfigRequest.kt b/src/main/kotlin/org/opensearch/commons/notifications/action/UpdateNotificationConfigRequest.kt index dcba7b71..765533be 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/action/UpdateNotificationConfigRequest.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/action/UpdateNotificationConfigRequest.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.action diff --git a/src/main/kotlin/org/opensearch/commons/notifications/action/UpdateNotificationConfigResponse.kt b/src/main/kotlin/org/opensearch/commons/notifications/action/UpdateNotificationConfigResponse.kt index 0e15a69b..7de2e58c 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/action/UpdateNotificationConfigResponse.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/action/UpdateNotificationConfigResponse.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.action diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/Attachment.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/Attachment.kt index 282781f0..7768273d 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/Attachment.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/Attachment.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.model diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/BaseConfigData.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/BaseConfigData.kt index a766d3e0..1b8e59bf 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/BaseConfigData.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/BaseConfigData.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.model diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/BaseModel.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/BaseModel.kt index bdc13931..5ead5594 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/BaseModel.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/BaseModel.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.model diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/ChannelMessage.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/ChannelMessage.kt index 5f70efa7..18a65d39 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/ChannelMessage.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/ChannelMessage.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.model diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/Chime.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/Chime.kt index 2ffb0fd0..f39a3f7a 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/Chime.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/Chime.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.model diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/ConfigType.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/ConfigType.kt index 85c10e35..e9888e2b 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/ConfigType.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/ConfigType.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.model diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/DeliveryStatus.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/DeliveryStatus.kt index e824242b..41009ba7 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/DeliveryStatus.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/DeliveryStatus.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.model diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/Email.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/Email.kt index 86d5f67a..07c055d6 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/Email.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/Email.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.model diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/EmailGroup.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/EmailGroup.kt index 4940cc39..c286b66e 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/EmailGroup.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/EmailGroup.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.model diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/EmailRecipient.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/EmailRecipient.kt index 78c4ae59..aa523346 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/EmailRecipient.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/EmailRecipient.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.model diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/EmailRecipientStatus.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/EmailRecipientStatus.kt index a65224de..12774764 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/EmailRecipientStatus.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/EmailRecipientStatus.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.model diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/EventSource.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/EventSource.kt index 98c46d2a..06b28bee 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/EventSource.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/EventSource.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.model diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/EventStatus.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/EventStatus.kt index bf72836d..b322e401 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/EventStatus.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/EventStatus.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.model diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/FeatureChannel.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/FeatureChannel.kt index a108d2ff..c0e74c56 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/FeatureChannel.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/FeatureChannel.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.model diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/FeatureChannelList.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/FeatureChannelList.kt index 6fc57b22..d5df20a1 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/FeatureChannelList.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/FeatureChannelList.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.model diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationConfig.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationConfig.kt index a0f7f5ad..e80a5497 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationConfig.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationConfig.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.model diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationConfigInfo.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationConfigInfo.kt index 3c17a28c..7867a2d2 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationConfigInfo.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationConfigInfo.kt @@ -1,29 +1,8 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. */ -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * - */ package org.opensearch.commons.notifications.model import org.opensearch.common.Strings diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationConfigSearchResult.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationConfigSearchResult.kt index 48952335..579a16cb 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationConfigSearchResult.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationConfigSearchResult.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.model diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationEvent.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationEvent.kt index c6bf6928..a76f552d 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationEvent.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationEvent.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.model diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationEventInfo.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationEventInfo.kt index 3e4ff552..51921fc8 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationEventInfo.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationEventInfo.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.model diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationEventSearchResult.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationEventSearchResult.kt index 71ed1ba5..e9b68406 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationEventSearchResult.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationEventSearchResult.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.model diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/SearchResults.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/SearchResults.kt index 868cfebe..226f8d5d 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/SearchResults.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/SearchResults.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.model diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/SesAccount.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/SesAccount.kt index aa9aca26..4aea8eb4 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/SesAccount.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/SesAccount.kt @@ -1,12 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. */ package org.opensearch.commons.notifications.model diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/SeverityType.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/SeverityType.kt index 6f84f07b..0fa8a427 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/SeverityType.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/SeverityType.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.model diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/Slack.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/Slack.kt index e5d3c3f6..f022470b 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/Slack.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/Slack.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.model diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/SmtpAccount.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/SmtpAccount.kt index 21e2155e..6022a913 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/SmtpAccount.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/SmtpAccount.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.model diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/Sns.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/Sns.kt index 5e723926..583aec49 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/Sns.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/Sns.kt @@ -1,13 +1,8 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. */ + package org.opensearch.commons.notifications.model import org.opensearch.common.io.stream.StreamInput diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/Webhook.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/Webhook.kt index 09dbfe9d..710a9594 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/Webhook.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/Webhook.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.model diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/XParser.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/XParser.kt index 894b21a9..e019acd7 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/XParser.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/XParser.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.model diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/config/ConfigDataProperties.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/config/ConfigDataProperties.kt index e6844934..7fb4327f 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/config/ConfigDataProperties.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/config/ConfigDataProperties.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.model.config diff --git a/src/main/kotlin/org/opensearch/commons/utils/EnumHelpers.kt b/src/main/kotlin/org/opensearch/commons/utils/EnumHelpers.kt index 3a18407e..39db7949 100644 --- a/src/main/kotlin/org/opensearch/commons/utils/EnumHelpers.kt +++ b/src/main/kotlin/org/opensearch/commons/utils/EnumHelpers.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.utils diff --git a/src/main/kotlin/org/opensearch/commons/utils/EnumParser.kt b/src/main/kotlin/org/opensearch/commons/utils/EnumParser.kt index 2a678f1f..b327d53c 100644 --- a/src/main/kotlin/org/opensearch/commons/utils/EnumParser.kt +++ b/src/main/kotlin/org/opensearch/commons/utils/EnumParser.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.utils diff --git a/src/main/kotlin/org/opensearch/commons/utils/Helpers.kt b/src/main/kotlin/org/opensearch/commons/utils/Helpers.kt index ae08c1d0..c31f0cab 100644 --- a/src/main/kotlin/org/opensearch/commons/utils/Helpers.kt +++ b/src/main/kotlin/org/opensearch/commons/utils/Helpers.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.utils diff --git a/src/main/kotlin/org/opensearch/commons/utils/OpenForTesting.kt b/src/main/kotlin/org/opensearch/commons/utils/OpenForTesting.kt index ccbd1536..1549e2e5 100644 --- a/src/main/kotlin/org/opensearch/commons/utils/OpenForTesting.kt +++ b/src/main/kotlin/org/opensearch/commons/utils/OpenForTesting.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.utils diff --git a/src/main/kotlin/org/opensearch/commons/utils/SecureClientWrapper.kt b/src/main/kotlin/org/opensearch/commons/utils/SecureClientWrapper.kt index 45fa29bd..bc0f0596 100644 --- a/src/main/kotlin/org/opensearch/commons/utils/SecureClientWrapper.kt +++ b/src/main/kotlin/org/opensearch/commons/utils/SecureClientWrapper.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.utils diff --git a/src/main/kotlin/org/opensearch/commons/utils/TransportHelpers.kt b/src/main/kotlin/org/opensearch/commons/utils/TransportHelpers.kt index 4763a48a..049dabdc 100644 --- a/src/main/kotlin/org/opensearch/commons/utils/TransportHelpers.kt +++ b/src/main/kotlin/org/opensearch/commons/utils/TransportHelpers.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.utils diff --git a/src/main/kotlin/org/opensearch/commons/utils/ValidationHelpers.kt b/src/main/kotlin/org/opensearch/commons/utils/ValidationHelpers.kt index 9f9082c4..ab9f7409 100644 --- a/src/main/kotlin/org/opensearch/commons/utils/ValidationHelpers.kt +++ b/src/main/kotlin/org/opensearch/commons/utils/ValidationHelpers.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.utils diff --git a/src/main/kotlin/org/opensearch/commons/utils/XContentHelpers.kt b/src/main/kotlin/org/opensearch/commons/utils/XContentHelpers.kt index 92dee033..e4af6007 100644 --- a/src/main/kotlin/org/opensearch/commons/utils/XContentHelpers.kt +++ b/src/main/kotlin/org/opensearch/commons/utils/XContentHelpers.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.utils diff --git a/src/test/java/org/opensearch/commons/InjectSecurityTest.java b/src/test/java/org/opensearch/commons/InjectSecurityTest.java index a9073d93..5a69de07 100644 --- a/src/test/java/org/opensearch/commons/InjectSecurityTest.java +++ b/src/test/java/org/opensearch/commons/InjectSecurityTest.java @@ -1,27 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. */ package org.opensearch.commons; diff --git a/src/test/java/org/opensearch/commons/authuser/UserTest.java b/src/test/java/org/opensearch/commons/authuser/UserTest.java index ca727e6d..4df30a44 100644 --- a/src/test/java/org/opensearch/commons/authuser/UserTest.java +++ b/src/test/java/org/opensearch/commons/authuser/UserTest.java @@ -1,27 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. */ package org.opensearch.commons.authuser; diff --git a/src/test/java/org/opensearch/commons/destination/message/LegacyChimeMessageTest.java b/src/test/java/org/opensearch/commons/destination/message/LegacyChimeMessageTest.java index 4477789e..191fef30 100644 --- a/src/test/java/org/opensearch/commons/destination/message/LegacyChimeMessageTest.java +++ b/src/test/java/org/opensearch/commons/destination/message/LegacyChimeMessageTest.java @@ -1,27 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. */ package org.opensearch.commons.destination.message; diff --git a/src/test/java/org/opensearch/commons/destination/message/LegacyCustomWebhookMessageTest.java b/src/test/java/org/opensearch/commons/destination/message/LegacyCustomWebhookMessageTest.java index fba614fd..7443d060 100644 --- a/src/test/java/org/opensearch/commons/destination/message/LegacyCustomWebhookMessageTest.java +++ b/src/test/java/org/opensearch/commons/destination/message/LegacyCustomWebhookMessageTest.java @@ -1,27 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. */ package org.opensearch.commons.destination.message; diff --git a/src/test/java/org/opensearch/commons/destination/message/LegacySlackMessageTest.java b/src/test/java/org/opensearch/commons/destination/message/LegacySlackMessageTest.java index a520fc8e..6b04d651 100644 --- a/src/test/java/org/opensearch/commons/destination/message/LegacySlackMessageTest.java +++ b/src/test/java/org/opensearch/commons/destination/message/LegacySlackMessageTest.java @@ -1,27 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. */ package org.opensearch.commons.destination.message; diff --git a/src/test/java/org/opensearch/commons/destination/response/LegacyDestinationResponseTest.java b/src/test/java/org/opensearch/commons/destination/response/LegacyDestinationResponseTest.java index 6175827e..e9189d24 100644 --- a/src/test/java/org/opensearch/commons/destination/response/LegacyDestinationResponseTest.java +++ b/src/test/java/org/opensearch/commons/destination/response/LegacyDestinationResponseTest.java @@ -1,27 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. */ package org.opensearch.commons.destination.response; diff --git a/src/test/java/org/opensearch/commons/rest/IntegrationTests.java b/src/test/java/org/opensearch/commons/rest/IntegrationTests.java index ee465086..0c6b7cfe 100644 --- a/src/test/java/org/opensearch/commons/rest/IntegrationTests.java +++ b/src/test/java/org/opensearch/commons/rest/IntegrationTests.java @@ -1,27 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. */ package org.opensearch.commons.rest; diff --git a/src/test/java/org/opensearch/commons/rest/SecureRestClientBuilderTest.java b/src/test/java/org/opensearch/commons/rest/SecureRestClientBuilderTest.java index 1fe5a51e..4a034f7e 100644 --- a/src/test/java/org/opensearch/commons/rest/SecureRestClientBuilderTest.java +++ b/src/test/java/org/opensearch/commons/rest/SecureRestClientBuilderTest.java @@ -1,27 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. */ package org.opensearch.commons.rest; diff --git a/src/test/java/org/opensearch/commons/rest/TrustStoreTest.java b/src/test/java/org/opensearch/commons/rest/TrustStoreTest.java index bea767d0..108a9e8d 100644 --- a/src/test/java/org/opensearch/commons/rest/TrustStoreTest.java +++ b/src/test/java/org/opensearch/commons/rest/TrustStoreTest.java @@ -1,27 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. */ package org.opensearch.commons.rest; diff --git a/src/test/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterfaceTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterfaceTests.kt index 31d47bba..8147650f 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterfaceTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterfaceTests.kt @@ -1,13 +1,8 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. */ + package org.opensearch.commons.notifications import com.nhaarman.mockitokotlin2.whenever diff --git a/src/test/kotlin/org/opensearch/commons/notifications/action/CreateNotificationConfigRequestTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/action/CreateNotificationConfigRequestTests.kt index 28f337b8..9eb1de1f 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/action/CreateNotificationConfigRequestTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/action/CreateNotificationConfigRequestTests.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.action diff --git a/src/test/kotlin/org/opensearch/commons/notifications/action/CreateNotificationConfigResponseTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/action/CreateNotificationConfigResponseTests.kt index b9f0f4e1..0f580fcd 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/action/CreateNotificationConfigResponseTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/action/CreateNotificationConfigResponseTests.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.action diff --git a/src/test/kotlin/org/opensearch/commons/notifications/action/DeleteNotificationConfigRequestTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/action/DeleteNotificationConfigRequestTests.kt index 4c0c016d..c44d1458 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/action/DeleteNotificationConfigRequestTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/action/DeleteNotificationConfigRequestTests.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.action diff --git a/src/test/kotlin/org/opensearch/commons/notifications/action/DeleteNotificationConfigResponseTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/action/DeleteNotificationConfigResponseTests.kt index 5c479b47..fb574114 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/action/DeleteNotificationConfigResponseTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/action/DeleteNotificationConfigResponseTests.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.action diff --git a/src/test/kotlin/org/opensearch/commons/notifications/action/GetFeatureChannelListRequestTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/action/GetFeatureChannelListRequestTests.kt index 8c5c770f..98d577de 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/action/GetFeatureChannelListRequestTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/action/GetFeatureChannelListRequestTests.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.action diff --git a/src/test/kotlin/org/opensearch/commons/notifications/action/GetFeatureChannelListResponseTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/action/GetFeatureChannelListResponseTests.kt index 149e966f..805f651e 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/action/GetFeatureChannelListResponseTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/action/GetFeatureChannelListResponseTests.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.action diff --git a/src/test/kotlin/org/opensearch/commons/notifications/action/GetNotificationConfigRequestTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/action/GetNotificationConfigRequestTests.kt index cf892209..8873202d 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/action/GetNotificationConfigRequestTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/action/GetNotificationConfigRequestTests.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.action diff --git a/src/test/kotlin/org/opensearch/commons/notifications/action/GetNotificationConfigResponseTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/action/GetNotificationConfigResponseTests.kt index 8cc66d80..7541acb2 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/action/GetNotificationConfigResponseTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/action/GetNotificationConfigResponseTests.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.action diff --git a/src/test/kotlin/org/opensearch/commons/notifications/action/GetNotificationEventRequestTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/action/GetNotificationEventRequestTests.kt index 5e12d5f1..53bb825a 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/action/GetNotificationEventRequestTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/action/GetNotificationEventRequestTests.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.action diff --git a/src/test/kotlin/org/opensearch/commons/notifications/action/GetNotificationEventResponseTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/action/GetNotificationEventResponseTests.kt index be6af960..16139bb1 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/action/GetNotificationEventResponseTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/action/GetNotificationEventResponseTests.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.action diff --git a/src/test/kotlin/org/opensearch/commons/notifications/action/GetPluginFeaturesRequestTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/action/GetPluginFeaturesRequestTests.kt index 3861fdd9..1c85ed70 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/action/GetPluginFeaturesRequestTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/action/GetPluginFeaturesRequestTests.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.action diff --git a/src/test/kotlin/org/opensearch/commons/notifications/action/GetPluginFeaturesResponseTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/action/GetPluginFeaturesResponseTests.kt index c9924269..72b9a49f 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/action/GetPluginFeaturesResponseTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/action/GetPluginFeaturesResponseTests.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.action diff --git a/src/test/kotlin/org/opensearch/commons/notifications/action/LegacyPublishNotificationRequestTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/action/LegacyPublishNotificationRequestTests.kt index 349a1c14..c323ec85 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/action/LegacyPublishNotificationRequestTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/action/LegacyPublishNotificationRequestTests.kt @@ -1,12 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. */ package org.opensearch.commons.notifications.action diff --git a/src/test/kotlin/org/opensearch/commons/notifications/action/LegacyPublishNotificationResponseTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/action/LegacyPublishNotificationResponseTests.kt index 4b6f8e0b..4a75a82e 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/action/LegacyPublishNotificationResponseTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/action/LegacyPublishNotificationResponseTests.kt @@ -1,12 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. */ package org.opensearch.commons.notifications.action diff --git a/src/test/kotlin/org/opensearch/commons/notifications/action/SendNotificationRequestTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/action/SendNotificationRequestTests.kt index 31f6f549..3874190c 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/action/SendNotificationRequestTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/action/SendNotificationRequestTests.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.action diff --git a/src/test/kotlin/org/opensearch/commons/notifications/action/SendNotificationResponseTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/action/SendNotificationResponseTests.kt index 511c5760..ca7f789c 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/action/SendNotificationResponseTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/action/SendNotificationResponseTests.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.action diff --git a/src/test/kotlin/org/opensearch/commons/notifications/action/UpdateNotificationConfigRequestTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/action/UpdateNotificationConfigRequestTests.kt index 9599d60e..725e3c59 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/action/UpdateNotificationConfigRequestTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/action/UpdateNotificationConfigRequestTests.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.action diff --git a/src/test/kotlin/org/opensearch/commons/notifications/action/UpdateNotificationConfigResponseTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/action/UpdateNotificationConfigResponseTests.kt index aa2839c3..ca0b18cc 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/action/UpdateNotificationConfigResponseTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/action/UpdateNotificationConfigResponseTests.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.action diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/AttachmentTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/AttachmentTests.kt index b0873cfe..5aa127fe 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/AttachmentTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/AttachmentTests.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.model diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/ChannelMessageTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/ChannelMessageTests.kt index 7cda9d66..0a9f3f87 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/ChannelMessageTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/ChannelMessageTests.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.model diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/ChimeTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/ChimeTests.kt index da404b28..8e7f434e 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/ChimeTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/ChimeTests.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.model diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/ConfigTypeTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/ConfigTypeTests.kt index 28b1ec7e..6be8d68b 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/ConfigTypeTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/ConfigTypeTests.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.model diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/DeliveryStatusTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/DeliveryStatusTests.kt index 377d2be9..33c42e99 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/DeliveryStatusTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/DeliveryStatusTests.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.model diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/EmailGroupTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/EmailGroupTests.kt index dbf2f77b..15ab3ade 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/EmailGroupTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/EmailGroupTests.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.model diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/EmailRecipientStatusTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/EmailRecipientStatusTests.kt index 31bb80bd..c9bd89af 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/EmailRecipientStatusTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/EmailRecipientStatusTests.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.model diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/EmailRecipientTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/EmailRecipientTests.kt index c2f2d36d..56a5f752 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/EmailRecipientTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/EmailRecipientTests.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.model diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/EmailTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/EmailTests.kt index 8e4772f5..8624b138 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/EmailTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/EmailTests.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.model diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/EventSourceTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/EventSourceTests.kt index 6a87ed3f..2244d0c4 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/EventSourceTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/EventSourceTests.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.model diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/EventStatusTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/EventStatusTests.kt index e9a1634f..65173cfe 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/EventStatusTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/EventStatusTests.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.model diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/FeatureChannelListTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/FeatureChannelListTests.kt index 5bd3db62..8a40aadd 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/FeatureChannelListTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/FeatureChannelListTests.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.model diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/FeatureChannelTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/FeatureChannelTests.kt index d2b8f009..3fa2e4ab 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/FeatureChannelTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/FeatureChannelTests.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.model diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/FilterConfigListTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/FilterConfigListTests.kt index f4ceee7f..9ac569f6 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/FilterConfigListTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/FilterConfigListTests.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.model diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/FilterConfigTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/FilterConfigTests.kt index b5dd66b6..234548a8 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/FilterConfigTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/FilterConfigTests.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.model diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/MethodTypeTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/MethodTypeTests.kt index 75685d53..f9982d7c 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/MethodTypeTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/MethodTypeTests.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.model diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationConfigInfoTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationConfigInfoTests.kt index 6f532fb0..d14b9f34 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationConfigInfoTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationConfigInfoTests.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.model diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationConfigSearchResultsTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationConfigSearchResultsTests.kt index dab33090..835af358 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationConfigSearchResultsTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationConfigSearchResultsTests.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.model diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationConfigTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationConfigTests.kt index 0a96c8ed..47614986 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationConfigTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationConfigTests.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.model diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationEventInfoTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationEventInfoTests.kt index 3937c252..a87e334a 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationEventInfoTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationEventInfoTests.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.model diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationEventSearchResultTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationEventSearchResultTests.kt index c0e9786d..ae3f01a9 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationEventSearchResultTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationEventSearchResultTests.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.model diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationEventTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationEventTests.kt index 92c53fd8..313ffca9 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationEventTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationEventTests.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.model diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/SesAccountTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/SesAccountTests.kt index e999e534..e5a52837 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/SesAccountTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/SesAccountTests.kt @@ -1,12 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. */ package org.opensearch.commons.notifications.model diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/SeverityTypeTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/SeverityTypeTests.kt index 71fe1460..35f7b218 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/SeverityTypeTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/SeverityTypeTests.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.model diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/SlackTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/SlackTests.kt index 98fbc0cd..5c64c6ae 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/SlackTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/SlackTests.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.model diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/SmtpAccountTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/SmtpAccountTests.kt index bc924681..ffdf26c7 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/SmtpAccountTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/SmtpAccountTests.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.model diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/SnsTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/SnsTests.kt index 03d494d2..494f09e9 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/SnsTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/SnsTests.kt @@ -1,12 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. */ package org.opensearch.commons.notifications.model diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/WebhookTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/WebhookTests.kt index 5a717669..3272203d 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/WebhookTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/WebhookTests.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.model diff --git a/src/test/kotlin/org/opensearch/commons/utils/TestHelpers.kt b/src/test/kotlin/org/opensearch/commons/utils/TestHelpers.kt index 35f5d3b9..81dc33e0 100644 --- a/src/test/kotlin/org/opensearch/commons/utils/TestHelpers.kt +++ b/src/test/kotlin/org/opensearch/commons/utils/TestHelpers.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.utils From 1da8807b7db32a997e7a9da5e7239b20fae00b80 Mon Sep 17 00:00:00 2001 From: Peter Nied Date: Thu, 24 Feb 2022 16:07:40 -0600 Subject: [PATCH 031/140] Remove jcenter repository missed on first pass (#118) Signed-off-by: Peter Nied --- build.gradle | 1 - 1 file changed, 1 deletion(-) diff --git a/build.gradle b/build.gradle index 07768d30..76a5c34e 100644 --- a/build.gradle +++ b/build.gradle @@ -35,7 +35,6 @@ repositories { mavenLocal() mavenCentral() maven { url "https://plugins.gradle.org/m2/" } - jcenter() maven { url "https://aws.oss.sonatype.org/content/repositories/snapshots" } } From 3919543651049284a877fdc0980aec76ced72a21 Mon Sep 17 00:00:00 2001 From: "Daniel Doubrovkine (dB.)" Date: Tue, 1 Mar 2022 17:09:12 -0500 Subject: [PATCH 032/140] Run CI/CD on Java 8, 11, 14 and 17. (#121) * Run CI/CD on Java 8, 11, 14 and 17. Signed-off-by: dblock * Add JDK 17. Signed-off-by: dblock --- .github/workflows/ci-17.yml | 40 +++++++++++++++++++ .github/workflows/ci.yml | 6 ++- DEVELOPER_GUIDE.md | 6 +-- .../commons/InjectSecurityTest.java | 14 +++++-- 4 files changed, 58 insertions(+), 8 deletions(-) create mode 100644 .github/workflows/ci-17.yml diff --git a/.github/workflows/ci-17.yml b/.github/workflows/ci-17.yml new file mode 100644 index 00000000..a6a8a1e2 --- /dev/null +++ b/.github/workflows/ci-17.yml @@ -0,0 +1,40 @@ +name: Build and Test +on: + push: + branches: + - "*" + pull_request: + branches: + - "*" + +jobs: + build: + + name: Build and Test (17) + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Setup Java 11 + uses: actions/setup-java@v2 + with: + distribution: 'temurin' + java-version: 11 + + - name: Build + run: | + ./gradlew build --build-cache + + - name: Setup Java 17 + uses: actions/setup-java@v2 + with: + distribution: 'temurin' + java-version: 17 + + - name: Test + run: | + ./gradlew test --build-cache + + diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c35e0c0a..e3e495c4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,7 +11,10 @@ jobs: build: strategy: matrix: - java: [14] + java: + - 8 + - 11 + - 14 name: Build and Test runs-on: ubuntu-latest @@ -25,7 +28,6 @@ jobs: with: java-version: ${{ matrix.java }} - # common-utils - name: Build and Test run: | ./gradlew build diff --git a/DEVELOPER_GUIDE.md b/DEVELOPER_GUIDE.md index d162eccb..27fc15b3 100644 --- a/DEVELOPER_GUIDE.md +++ b/DEVELOPER_GUIDE.md @@ -1,7 +1,7 @@ - [Developer Guide](#developer-guide) - [Forking and Cloning](#forking-and-cloning) - [Install Prerequisites](#install-prerequisites) - - [JDK 14](#jdk-14) + - [JDK 11](#jdk-11) - [Building](#building) - [Using IntelliJ IDEA](#using-intellij-idea) - [Submitting Changes](#submitting-changes) @@ -16,9 +16,9 @@ Fork this repository on GitHub, and clone locally with `git clone`. ### Install Prerequisites -#### JDK 14 +#### JDK 11 -OpenSearch components build using Java 14 at a minimum. This means you must have a JDK 14 installed with the environment variable `JAVA_HOME` referencing the path to Java home for your JDK 14 installation, e.g. `JAVA_HOME=/usr/lib/jvm/jdk-14`. +OpenSearch components build using Java 11 at a minimum. This means you must have a JDK 11 installed with the environment variable `JAVA_HOME` referencing the path to Java home for your JDK 11 installation, e.g. `JAVA_HOME=/usr/lib/jvm/jdk-11`. ### Building diff --git a/src/test/java/org/opensearch/commons/InjectSecurityTest.java b/src/test/java/org/opensearch/commons/InjectSecurityTest.java index 5a69de07..818aa9c7 100644 --- a/src/test/java/org/opensearch/commons/InjectSecurityTest.java +++ b/src/test/java/org/opensearch/commons/InjectSecurityTest.java @@ -15,7 +15,7 @@ import static org.opensearch.commons.ConfigConstants.OPENSEARCH_SECURITY_USE_INJECTED_USER_FOR_PLUGINS; import java.util.Arrays; -import java.util.Map; +import java.util.HashMap; import org.junit.jupiter.api.Test; import org.opensearch.common.settings.Settings; @@ -114,7 +114,11 @@ public void testInjectProperty() { assertTrue(helper.injectProperty("property1", true)); assertTrue(helper.injectProperty("property2", "some value")); assertTrue(helper.injectProperty("property3", "")); - assertTrue(helper.injectProperty("property4", Map.of("key", "value"))); + assertTrue(helper.injectProperty("property4", new HashMap() { + { + put("key", "value"); + } + })); // verify the set properties are not null and equal to what was set assertNull(threadContext.getTransient("property")); assertNotNull(threadContext.getTransient("property1")); @@ -124,7 +128,11 @@ public void testInjectProperty() { assertNotNull(threadContext.getTransient("property3")); assertEquals("", threadContext.getTransient("property3")); assertNotNull(threadContext.getTransient("property4")); - assertEquals(Map.of("key", "value"), threadContext.getTransient("property4")); + assertEquals(new HashMap() { + { + put("key", "value"); + } + }, threadContext.getTransient("property4")); } assertEquals("1", threadContext.getHeader("default")); assertEquals("opendistro", threadContext.getHeader("name")); From 710b1f9e337a3a07d65f88b1ec823f1cc4f8cbf4 Mon Sep 17 00:00:00 2001 From: "whitesource-for-github-com[bot]" <50673670+whitesource-for-github-com[bot]@users.noreply.github.com> Date: Tue, 1 Mar 2022 16:55:00 -0800 Subject: [PATCH 033/140] Add .whitesource configuration file (#109) Co-authored-by: whitesource-for-github-com[bot] <50673670+whitesource-for-github-com[bot]@users.noreply.github.com> --- .whitesource | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 .whitesource diff --git a/.whitesource b/.whitesource new file mode 100644 index 00000000..db4b0fec --- /dev/null +++ b/.whitesource @@ -0,0 +1,15 @@ +{ + "scanSettings": { + "configMode": "AUTO", + "configExternalURL": "", + "projectToken": "", + "baseBranches": [] + }, + "checkRunSettings": { + "vulnerableCheckRunConclusionLevel": "failure", + "displayMode": "diff" + }, + "issueSettings": { + "minSeverityLevel": "LOW" + } +} \ No newline at end of file From 361db4ce3933fe902773df1266fc32cf6b0098bb Mon Sep 17 00:00:00 2001 From: Ashish Agrawal Date: Wed, 2 Mar 2022 17:09:20 -0800 Subject: [PATCH 034/140] Upgrade to 2.0 (#122) Signed-off-by: Ashish Agrawal --- build.gradle | 2 +- gradle/wrapper/gradle-wrapper.properties | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 76a5c34e..d92e0acf 100644 --- a/build.gradle +++ b/build.gradle @@ -6,7 +6,7 @@ buildscript { ext { opensearch_group = "org.opensearch" - opensearch_version = System.getProperty("opensearch.version", "1.3.0-SNAPSHOT") + opensearch_version = System.getProperty("opensearch.version", "2.0.0-SNAPSHOT") kotlin_version = System.getProperty("kotlin.version", "1.4.32") } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 21a8fe40..f338a880 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -2,4 +2,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.4-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-all.zip From 1be69e5326c0434df08f37903bda3d782fa6bbca Mon Sep 17 00:00:00 2001 From: "Daniel Doubrovkine (dB.)" Date: Wed, 9 Mar 2022 14:32:56 -0500 Subject: [PATCH 035/140] Remove JDK8 support and fix JDK17 build. (#129) --- .github/workflows/ci-17.yml | 40 ------------------------------------- .github/workflows/ci.yml | 2 +- build.gradle | 19 +++++++++--------- 3 files changed, 11 insertions(+), 50 deletions(-) delete mode 100644 .github/workflows/ci-17.yml diff --git a/.github/workflows/ci-17.yml b/.github/workflows/ci-17.yml deleted file mode 100644 index a6a8a1e2..00000000 --- a/.github/workflows/ci-17.yml +++ /dev/null @@ -1,40 +0,0 @@ -name: Build and Test -on: - push: - branches: - - "*" - pull_request: - branches: - - "*" - -jobs: - build: - - name: Build and Test (17) - runs-on: ubuntu-latest - - steps: - - name: Checkout - uses: actions/checkout@v2 - - - name: Setup Java 11 - uses: actions/setup-java@v2 - with: - distribution: 'temurin' - java-version: 11 - - - name: Build - run: | - ./gradlew build --build-cache - - - name: Setup Java 17 - uses: actions/setup-java@v2 - with: - distribution: 'temurin' - java-version: 17 - - - name: Test - run: | - ./gradlew test --build-cache - - diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e3e495c4..69e7573d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -12,9 +12,9 @@ jobs: strategy: matrix: java: - - 8 - 11 - 14 + - 17 name: Build and Test runs-on: ubuntu-latest diff --git a/build.gradle b/build.gradle index d92e0acf..5ab47cb4 100644 --- a/build.gradle +++ b/build.gradle @@ -7,7 +7,7 @@ buildscript { ext { opensearch_group = "org.opensearch" opensearch_version = System.getProperty("opensearch.version", "2.0.0-SNAPSHOT") - kotlin_version = System.getProperty("kotlin.version", "1.4.32") + kotlin_version = System.getProperty("kotlin.version", "1.6.10") } repositories { @@ -21,7 +21,7 @@ buildscript { classpath "${opensearch_group}.gradle:build-tools:${opensearch_version}" classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${kotlin_version}" classpath "org.jetbrains.kotlin:kotlin-allopen:${kotlin_version}" - classpath "io.gitlab.arturbosch.detekt:detekt-gradle-plugin:1.17.1" + classpath "io.gitlab.arturbosch.detekt:detekt-gradle-plugin:1.20.0-RC1" } } @@ -50,7 +50,8 @@ allprojects { } } -sourceCompatibility = 1.8 +targetCompatibility = JavaVersion.VERSION_11 +sourceCompatibility = JavaVersion.VERSION_11 apply plugin: 'java' apply plugin: 'jacoco' @@ -70,15 +71,15 @@ dependencies { compileOnly "org.jetbrains.kotlin:kotlin-stdlib:${kotlin_version}" compileOnly "org.jetbrains.kotlin:kotlin-stdlib-common:${kotlin_version}" compileOnly "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.3" // ${kotlin_version} does not work for coroutines - testCompile "org.opensearch.test:framework:${opensearch_version}" - testCompile "org.jetbrains.kotlin:kotlin-test:${kotlin_version}" - testCompile "org.mockito:mockito-core:3.10.0" + testImplementation "org.opensearch.test:framework:${opensearch_version}" + testImplementation "org.jetbrains.kotlin:kotlin-test:${kotlin_version}" + testImplementation "org.mockito:mockito-core:3.10.0" testImplementation 'org.junit.jupiter:junit-jupiter-api:5.7.2' testImplementation 'org.mockito:mockito-junit-jupiter:3.10.0' testImplementation "com.nhaarman.mockitokotlin2:mockito-kotlin:2.2.0" testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.7.2' - ktlint "com.pinterest:ktlint:0.41.0" + ktlint "com.pinterest:ktlint:0.44.0" } test { @@ -126,13 +127,13 @@ task ktlintFormat(type: JavaExec, group: "formatting") { compileKotlin { kotlinOptions { freeCompilerArgs = ['-Xjsr305=strict'] - jvmTarget = "1.8" + jvmTarget = "11" } } compileTestKotlin { kotlinOptions { - jvmTarget = "1.8" + jvmTarget = "11" } } From fb43b2206fd869db075862afb93e5f62e68a29df Mon Sep 17 00:00:00 2001 From: "Daniel Doubrovkine (dB.)" Date: Wed, 9 Mar 2022 20:24:57 -0500 Subject: [PATCH 036/140] Add support for build version qualifier. (#128) Signed-off-by: dblock --- build.gradle | 6 +++++- scripts/build.sh | 12 ++++++++---- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/build.gradle b/build.gradle index 5ab47cb4..16c28922 100644 --- a/build.gradle +++ b/build.gradle @@ -40,11 +40,15 @@ repositories { ext { isSnapshot = "true" == System.getProperty("build.snapshot", "true") + buildVersionQualifier = System.getProperty("build.version_qualifier") } allprojects { group 'org.opensearch.commons' - version = opensearch_version - '-SNAPSHOT' + '.0' + version = opensearch_version.tokenize('-')[0] + '.0' + if (buildVersionQualifier) { + version += "-${buildVersionQualifier}" + } if (isSnapshot) { version += "-SNAPSHOT" } diff --git a/scripts/build.sh b/scripts/build.sh index f68dc52e..1f8b6d4d 100755 --- a/scripts/build.sh +++ b/scripts/build.sh @@ -10,6 +10,7 @@ function usage() { echo "" echo "Arguments:" echo -e "-v VERSION\t[Required] OpenSearch version." + echo -e "-q QUALIFIER\t[Optional] Build qualifier." echo -e "-s SNAPSHOT\t[Optional] Build a snapshot, default is 'false'." echo -e "-p PLATFORM\t[Optional] Platform, ignored." echo -e "-a ARCHITECTURE\t[Optional] Build architecture, ignored." @@ -17,7 +18,7 @@ function usage() { echo -e "-h help" } -while getopts ":h:v:s:o:p:a:" arg; do +while getopts ":h:v:q:s:o:p:a:" arg; do case $arg in h) usage @@ -26,6 +27,9 @@ while getopts ":h:v:s:o:p:a:" arg; do v) VERSION=$OPTARG ;; + q) + QUALIFIER=$OPTARG + ;; s) SNAPSHOT=$OPTARG ;; @@ -59,8 +63,8 @@ fi [[ "$SNAPSHOT" == "true" ]] && VERSION=$VERSION-SNAPSHOT [ -z "$OUTPUT" ] && OUTPUT=artifacts -./gradlew build -Dopensearch.version=$VERSION -Dbuild.snapshot=$SNAPSHOT -./gradlew publishShadowPublicationToMavenLocal -Dopensearch.version=$VERSION -Dbuild.snapshot=$SNAPSHOT -./gradlew publishShadowPublicationToStagingRepository -Dopensearch.version=$VERSION -Dbuild.snapshot=$SNAPSHOT +./gradlew build -Dopensearch.version=$VERSION -Dbuild.snapshot=$SNAPSHOT -Dbuild.version_qualifier=$QUALIFIER +./gradlew publishShadowPublicationToMavenLocal -Dopensearch.version=$VERSION -Dbuild.snapshot=$SNAPSHOT -Dbuild.version_qualifier=$QUALIFIER +./gradlew publishShadowPublicationToStagingRepository -Dopensearch.version=$VERSION -Dbuild.snapshot=$SNAPSHOT -Dbuild.version_qualifier=$QUALIFIER mkdir -p $OUTPUT/maven/org/opensearch cp -r ./build/local-staging-repo/org/opensearch/common-utils $OUTPUT/maven/org/opensearch/common-utils From bdd8a8135c86a34ae49f5153a17fd0cfb7ec4745 Mon Sep 17 00:00:00 2001 From: Annie Lee Date: Thu, 10 Mar 2022 10:50:04 -0800 Subject: [PATCH 037/140] Add backport and auto delete workflow (#130) Signed-off-by: Annie Lee --- .github/workflows/backport.yml | 29 ++++++++++++++++++++ .github/workflows/delete_backport_branch.yml | 15 ++++++++++ DEVELOPER_GUIDE.md | 6 +++- 3 files changed, 49 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/backport.yml create mode 100644 .github/workflows/delete_backport_branch.yml diff --git a/.github/workflows/backport.yml b/.github/workflows/backport.yml new file mode 100644 index 00000000..e3f96a44 --- /dev/null +++ b/.github/workflows/backport.yml @@ -0,0 +1,29 @@ + +name: Backport +on: + pull_request_target: + types: + - closed + - labeled + +jobs: + backport: + runs-on: ubuntu-latest + permissions: + contents: write + pull-requests: write + name: Backport + steps: + - name: GitHub App token + id: github_app_token + uses: tibdex/github-app-token@v1.5.0 + with: + app_id: ${{ secrets.APP_ID }} + private_key: ${{ secrets.APP_PRIVATE_KEY }} + installation_id: 22958780 + + - name: Backport + uses: VachaShah/backport@v1.1.4 + with: + github_token: ${{ steps.github_app_token.outputs.token }} + branch_name: backport/backport-${{ github.event.number }} diff --git a/.github/workflows/delete_backport_branch.yml b/.github/workflows/delete_backport_branch.yml new file mode 100644 index 00000000..f24f022b --- /dev/null +++ b/.github/workflows/delete_backport_branch.yml @@ -0,0 +1,15 @@ +name: Delete merged branch of the backport PRs +on: + pull_request: + types: + - closed + +jobs: + delete-branch: + runs-on: ubuntu-latest + if: startsWith(github.event.pull_request.head.ref,'backport/') + steps: + - name: Delete merged branch + uses: SvanBoxel/delete-merged-branch@main + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/DEVELOPER_GUIDE.md b/DEVELOPER_GUIDE.md index 27fc15b3..d4a44c46 100644 --- a/DEVELOPER_GUIDE.md +++ b/DEVELOPER_GUIDE.md @@ -36,4 +36,8 @@ Launch Intellij IDEA, choose **Import Project**, and select the `settings.gradle ### Submitting Changes -See [CONTRIBUTING](CONTRIBUTING.md). \ No newline at end of file +See [CONTRIBUTING](CONTRIBUTING.md). + +### Backport + +- [Link to backport documentation](https://github.com/opensearch-project/opensearch-plugins/blob/main/BACKPORT.md) From be72763aa9f94e594500c799dacbeb0e8dd3365d Mon Sep 17 00:00:00 2001 From: Saurabh Singh Date: Fri, 11 Mar 2022 14:40:13 -0800 Subject: [PATCH 038/140] Add release notes for version 1.3.0.0 (#132) Signed-off-by: Saurabh Singh Co-authored-by: Saurabh Singh --- ...pensearch-common-utils.release-notes-1.3.0.0.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 release-notes/opensearch-common-utils.release-notes-1.3.0.0.md diff --git a/release-notes/opensearch-common-utils.release-notes-1.3.0.0.md b/release-notes/opensearch-common-utils.release-notes-1.3.0.0.md new file mode 100644 index 00000000..4f210951 --- /dev/null +++ b/release-notes/opensearch-common-utils.release-notes-1.3.0.0.md @@ -0,0 +1,14 @@ +## Version 1.3.0.0 2022-03-11 + +Compatible with OpenSearch 1.3.0 + +### Infrastructure + + * Updates common-utils version to 1.3 ([#99](https://github.com/opensearch-project/common-utils/pull/99)) + * Update build.sh script to include optional platform param. ([#95](https://github.com/opensearch-project/common-utils/pull/95)) + * Update copyright notice and add DCO check workflow. ([#94](https://github.com/opensearch-project/common-utils/pull/94)) + +### Documentation + + * Update copyright headers ([#117](https://github.com/opensearch-project/common-utils/pull/117)) + * Add release notes for version 1.3.0.0 ([#132](https://github.com/opensearch-project/common-utils/pull/132)) \ No newline at end of file From fe3abb9aaac36f43b5721d4b167e9a535f5e5eee Mon Sep 17 00:00:00 2001 From: Ashish Agrawal Date: Mon, 14 Mar 2022 16:54:51 -0700 Subject: [PATCH 039/140] Upgrade gradle artifacts to 7.3.3 (#135) Signed-off-by: Ashish Agrawal --- gradle/wrapper/gradle-wrapper.jar | Bin 56172 -> 59536 bytes gradle/wrapper/gradle-wrapper.properties | 2 +- gradlew | 282 ++++++++++++++--------- gradlew.bat | 43 ++-- 4 files changed, 197 insertions(+), 130 deletions(-) diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 28861d273a5d270fd8f65dd74570c17c9c507736..7454180f2ae8848c63b8b4dea2cb829da983f2fa 100644 GIT binary patch delta 51437 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%0DCB$;CIxFT%Ws?oirIo$=Lq=nDPZE9YO&<7lE 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 BrV#)D delta 48172 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к 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 cc>h-)Mo|U| \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >/dev/null -APP_HOME="`pwd -P`" -cd "$SAVED" >/dev/null + +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit APP_NAME="Gradle" -APP_BASE_NAME=`basename "$0"` +APP_BASE_NAME=${0##*/} # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS="" +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' # Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" +MAX_FD=maximum warn () { echo "$*" -} +} >&2 die () { echo echo "$*" echo exit 1 -} +} >&2 # OS specific support (must be 'true' or 'false'). cygwin=false msys=false darwin=false nonstop=false -case "`uname`" in - CYGWIN* ) - cygwin=true - ;; - Darwin* ) - darwin=true - ;; - MINGW* ) - msys=true - ;; - NONSTOP* ) - nonstop=true - ;; +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; esac CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + # Determine the Java command to use to start the JVM. if [ -n "$JAVA_HOME" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" + JAVACMD=$JAVA_HOME/jre/sh/java else - JAVACMD="$JAVA_HOME/bin/java" + JAVACMD=$JAVA_HOME/bin/java fi if [ ! -x "$JAVACMD" ] ; then die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME @@ -81,7 +132,7 @@ Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi else - JAVACMD="java" + JAVACMD=java which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the @@ -89,84 +140,95 @@ location of your Java installation." fi # Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then - MAX_FD_LIMIT=`ulimit -H -n` - if [ $? -eq 0 ] ; then - if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then - MAX_FD="$MAX_FD_LIMIT" - fi - ulimit -n $MAX_FD - if [ $? -ne 0 ] ; then - warn "Could not set maximum file descriptor limit: $MAX_FD" - fi - else - warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" - fi +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac fi -# For Darwin, add options to specify how the application appears in the dock -if $darwin; then - GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" -fi +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) -# For Cygwin, switch paths to Windows format before running java -if $cygwin ; then - APP_HOME=`cygpath --path --mixed "$APP_HOME"` - CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - JAVACMD=`cygpath --unix "$JAVACMD"` - - # We build the pattern for arguments to be converted via cygpath - ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` - SEP="" - for dir in $ROOTDIRSRAW ; do - ROOTDIRS="$ROOTDIRS$SEP$dir" - SEP="|" - done - OURCYGPATTERN="(^($ROOTDIRS))" - # Add a user-defined pattern to the cygpath arguments - if [ "$GRADLE_CYGPATTERN" != "" ] ; then - OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" - fi # Now convert the arguments - kludge to limit ourselves to /bin/sh - i=0 - for arg in "$@" ; do - CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` - CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option - - if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition - eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` - else - eval `echo args$i`="\"$arg\"" + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) fi - i=$((i+1)) + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg done - case $i in - (0) set -- ;; - (1) set -- "$args0" ;; - (2) set -- "$args0" "$args1" ;; - (3) set -- "$args0" "$args1" "$args2" ;; - (4) set -- "$args0" "$args1" "$args2" "$args3" ;; - (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; - esac fi -# Escape application args -save () { - for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done - echo " " -} -APP_ARGS=$(save "$@") - -# Collect all arguments for the java command, following the shell quoting and substitution rules -eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" - -# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong -if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then - cd "$(dirname "$0")" -fi +# Collect all arguments for the java command; +# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of +# shell script including quotes and variable substitutions, so put them in +# double quotes to make sure that they get re-expanded; and +# * put everything else in single quotes, so that it's not re-expanded. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat index e95643d6..ac1b06f9 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -1,3 +1,19 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + @if "%DEBUG%" == "" @echo off @rem ########################################################################## @rem @@ -13,15 +29,18 @@ if "%DIRNAME%" == "" set DIRNAME=. set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS= +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" @rem Find java.exe if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto init +if "%ERRORLEVEL%" == "0" goto execute echo. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. @@ -35,7 +54,7 @@ goto fail set JAVA_HOME=%JAVA_HOME:"=% set JAVA_EXE=%JAVA_HOME%/bin/java.exe -if exist "%JAVA_EXE%" goto init +if exist "%JAVA_EXE%" goto execute echo. echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% @@ -45,28 +64,14 @@ echo location of your Java installation. goto fail -:init -@rem Get command-line arguments, handling Windows variants - -if not "%OS%" == "Windows_NT" goto win9xME_args - -:win9xME_args -@rem Slurp the command line arguments. -set CMD_LINE_ARGS= -set _SKIP=2 - -:win9xME_args_slurp -if "x%~1" == "x" goto execute - -set CMD_LINE_ARGS=%* - :execute @rem Setup the command line set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + @rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* :end @rem End local scope for the variables with windows NT shell From 05931c9cc2a88656aa9323b0319a5b7bc9b1a611 Mon Sep 17 00:00:00 2001 From: Mohammad Qureshi <47198598+qreshi@users.noreply.github.com> Date: Thu, 17 Mar 2022 12:44:15 -0700 Subject: [PATCH 040/140] Remove feature and feature_list usage for Notifications (#136) * Remove feature_list from NotificationConfig Signed-off-by: Mohammad Qureshi <47198598+qreshi@users.noreply.github.com> * Remove feature from FeatueChannelsListRequest Signed-off-by: Mohammad Qureshi <47198598+qreshi@users.noreply.github.com> * Remove 'feature' from EventSource Signed-off-by: Mohammad Qureshi <47198598+qreshi@users.noreply.github.com> * Remove feature from LegacyPublishNotification Signed-off-by: Mohammad Qureshi <47198598+qreshi@users.noreply.github.com> * Updated descriptions related to publishLegacyNotification Signed-off-by: Mohammad Qureshi <47198598+qreshi@users.noreply.github.com> --- .../message/LegacyDestinationType.java | 2 +- .../notifications/NotificationConstants.kt | 5 -- .../NotificationsPluginInterface.kt | 8 +- .../action/GetFeatureChannelListRequest.kt | 40 +++++----- .../LegacyPublishNotificationRequest.kt | 8 +- .../action/NotificationsActions.kt | 4 +- .../notifications/model/EventSource.kt | 9 --- .../notifications/model/NotificationConfig.kt | 12 --- .../NotificationsPluginInterfaceTests.kt | 10 --- .../CreateNotificationConfigRequestTests.kt | 74 +++++++------------ .../GetFeatureChannelListRequestTests.kt | 23 +----- .../GetNotificationConfigResponseTests.kt | 20 +---- .../GetNotificationEventResponseTests.kt | 12 --- .../LegacyPublishNotificationRequestTests.kt | 4 +- .../action/SendNotificationRequestTests.kt | 12 --- .../UpdateNotificationConfigRequestTests.kt | 66 +++++++---------- .../notifications/model/EventSourceTests.kt | 18 ++--- .../model/NotificationConfigInfoTests.kt | 10 +-- .../NotificationConfigSearchResultsTests.kt | 20 +---- .../model/NotificationConfigTests.kt | 25 +------ .../model/NotificationEventInfoTests.kt | 5 -- .../NotificationEventSearchResultTests.kt | 12 --- .../model/NotificationEventTests.kt | 9 +-- 23 files changed, 103 insertions(+), 305 deletions(-) diff --git a/src/main/java/org/opensearch/commons/destination/message/LegacyDestinationType.java b/src/main/java/org/opensearch/commons/destination/message/LegacyDestinationType.java index ab50649b..1bad1029 100644 --- a/src/main/java/org/opensearch/commons/destination/message/LegacyDestinationType.java +++ b/src/main/java/org/opensearch/commons/destination/message/LegacyDestinationType.java @@ -6,7 +6,7 @@ package org.opensearch.commons.destination.message; /** - * Supported legacy notification destinations for Index Management + * Supported legacy notification destinations for Alerting and Index Management */ public enum LegacyDestinationType { LEGACY_CHIME, diff --git a/src/main/kotlin/org/opensearch/commons/notifications/NotificationConstants.kt b/src/main/kotlin/org/opensearch/commons/notifications/NotificationConstants.kt index 7a958154..6ebf7889 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/NotificationConstants.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/NotificationConstants.kt @@ -36,7 +36,6 @@ object NotificationConstants { const val NAME_TAG = "name" const val DESCRIPTION_TAG = "description" const val IS_ENABLED_TAG = "is_enabled" - const val FEATURE_LIST_TAG = "feature_list" const val TITLE_TAG = "title" const val SEVERITY_TAG = "severity" const val TAGS_TAG = "tags" @@ -70,9 +69,5 @@ object NotificationConstants { const val ALLOWED_CONFIG_FEATURE_LIST_TAG = "allowed_config_feature_list" const val PLUGIN_FEATURES_TAG = "plugin_features" - const val FEATURE_ALERTING = "alerting" - const val FEATURE_INDEX_MANAGEMENT = "index_management" - const val FEATURE_REPORTS = "reports" - const val DEFAULT_MAX_ITEMS = 1000 } diff --git a/src/main/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterface.kt b/src/main/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterface.kt index d406bb00..b67ec282 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterface.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterface.kt @@ -9,7 +9,6 @@ import org.opensearch.action.ActionResponse import org.opensearch.client.node.NodeClient import org.opensearch.common.io.stream.Writeable import org.opensearch.commons.ConfigConstants.OPENSEARCH_SECURITY_USER_INFO_THREAD_CONTEXT -import org.opensearch.commons.notifications.NotificationConstants.FEATURE_INDEX_MANAGEMENT import org.opensearch.commons.notifications.action.BaseResponse import org.opensearch.commons.notifications.action.CreateNotificationConfigRequest import org.opensearch.commons.notifications.action.CreateNotificationConfigResponse @@ -201,7 +200,7 @@ object NotificationsPluginInterface { /** * Publishes a notification API using the legacy notification implementation. No REST API. - * Internal API only for the Index Management plugin. + * Internal API only for the Alerting and Index Management plugin, other consumers should use [sendNotification]. * @param client Node client for making transport action * @param request The legacy publish notification request * @param listener The listener for getting response @@ -211,11 +210,6 @@ object NotificationsPluginInterface { request: LegacyPublishNotificationRequest, listener: ActionListener ) { - if (request.feature != FEATURE_INDEX_MANAGEMENT) { - // Do not change this; do not pass in FEATURE_INDEX_MANAGEMENT if you are not the Index Management plugin. - throw IllegalArgumentException("The publish notification method only supports the Index Management feature.") - } - client.execute( LEGACY_PUBLISH_NOTIFICATION_ACTION_TYPE, request, diff --git a/src/main/kotlin/org/opensearch/commons/notifications/action/GetFeatureChannelListRequest.kt b/src/main/kotlin/org/opensearch/commons/notifications/action/GetFeatureChannelListRequest.kt index 901b4040..56a0b0fa 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/action/GetFeatureChannelListRequest.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/action/GetFeatureChannelListRequest.kt @@ -14,7 +14,7 @@ import org.opensearch.common.xcontent.ToXContentObject import org.opensearch.common.xcontent.XContentBuilder import org.opensearch.common.xcontent.XContentParser import org.opensearch.common.xcontent.XContentParserUtils -import org.opensearch.commons.notifications.NotificationConstants.FEATURE_TAG +import org.opensearch.commons.notifications.NotificationConstants.COMPACT_TAG import org.opensearch.commons.utils.logger import java.io.IOException @@ -22,7 +22,7 @@ import java.io.IOException * This request is plugin-only call. i.e. REST interface is not exposed. */ class GetFeatureChannelListRequest : ActionRequest, ToXContentObject { - val feature: String + val compact: Boolean // Dummy request parameter for transport request companion object { private val log by logger(GetFeatureChannelListRequest::class.java) @@ -39,7 +39,7 @@ class GetFeatureChannelListRequest : ActionRequest, ToXContentObject { @JvmStatic @Throws(IOException::class) fun parse(parser: XContentParser): GetFeatureChannelListRequest { - var feature: String? = null + var compact = false XContentParserUtils.ensureExpectedToken( XContentParser.Token.START_OBJECT, @@ -50,24 +50,32 @@ class GetFeatureChannelListRequest : ActionRequest, ToXContentObject { val fieldName = parser.currentName() parser.nextToken() when (fieldName) { - FEATURE_TAG -> feature = parser.text() + COMPACT_TAG -> compact = parser.booleanValue() else -> { parser.skipChildren() log.info("Unexpected field: $fieldName, while parsing GetFeatureChannelListRequest") } } } - feature ?: throw IllegalArgumentException("$FEATURE_TAG field absent") - return GetFeatureChannelListRequest(feature) + return GetFeatureChannelListRequest() } } + /** + * {@inheritDoc} + */ + override fun toXContent(builder: XContentBuilder?, params: ToXContent.Params?): XContentBuilder { + return builder!!.startObject() + .field(COMPACT_TAG, compact) + .endObject() + } + /** * constructor for creating the class - * @param feature the caller plugin feature + * @param compact Dummy request parameter for transport request */ - constructor(feature: String) { - this.feature = feature + constructor(compact: Boolean = false) { + this.compact = compact } /** @@ -75,7 +83,7 @@ class GetFeatureChannelListRequest : ActionRequest, ToXContentObject { */ @Throws(IOException::class) constructor(input: StreamInput) : super(input) { - feature = input.readString() + compact = input.readBoolean() } /** @@ -84,17 +92,7 @@ class GetFeatureChannelListRequest : ActionRequest, ToXContentObject { @Throws(IOException::class) override fun writeTo(output: StreamOutput) { super.writeTo(output) - output.writeString(feature) - } - - /** - * {@inheritDoc} - */ - override fun toXContent(builder: XContentBuilder?, params: ToXContent.Params?): XContentBuilder { - builder!! - return builder.startObject() - .field(FEATURE_TAG, feature) - .endObject() + output.writeBoolean(compact) } /** diff --git a/src/main/kotlin/org/opensearch/commons/notifications/action/LegacyPublishNotificationRequest.kt b/src/main/kotlin/org/opensearch/commons/notifications/action/LegacyPublishNotificationRequest.kt index eb5080cf..508815a8 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/action/LegacyPublishNotificationRequest.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/action/LegacyPublishNotificationRequest.kt @@ -23,7 +23,6 @@ import java.io.IOException */ class LegacyPublishNotificationRequest : ActionRequest { val baseMessage: LegacyBaseMessage - val feature: String companion object { /** @@ -35,14 +34,11 @@ class LegacyPublishNotificationRequest : ActionRequest { /** * constructor for creating the class * @param baseMessage the base message to send - * @param feature the feature that is trying to use this request */ constructor( - baseMessage: LegacyBaseMessage, - feature: String + baseMessage: LegacyBaseMessage ) { this.baseMessage = baseMessage - this.feature = feature } /** @@ -55,7 +51,6 @@ class LegacyPublishNotificationRequest : ActionRequest { LegacyDestinationType.LEGACY_CUSTOM_WEBHOOK -> LegacyCustomWebhookMessage(input) LegacyDestinationType.LEGACY_SLACK -> LegacySlackMessage(input) } - feature = input.readString() } /** @@ -66,7 +61,6 @@ class LegacyPublishNotificationRequest : ActionRequest { super.writeTo(output) output.writeEnum(baseMessage.channelType) baseMessage.writeTo(output) - output.writeString(feature) } /** diff --git a/src/main/kotlin/org/opensearch/commons/notifications/action/NotificationsActions.kt b/src/main/kotlin/org/opensearch/commons/notifications/action/NotificationsActions.kt index 10605cac..ca8dd2d7 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/action/NotificationsActions.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/action/NotificationsActions.kt @@ -52,7 +52,7 @@ object NotificationsActions { /** * Publish legacy notification message. Internal only - Inter plugin communication. - * Only for the Index Management plugin. + * Only for the Alerting and Index Management plugins. */ const val LEGACY_PUBLISH_NOTIFICATION_NAME = "cluster:admin/opensearch/notifications/feature/publish" @@ -106,7 +106,7 @@ object NotificationsActions { /** * Send legacy notification transport action type. Internal only - Inter plugin communication. - * Only for the Index Management plugin. + * Only for the Alerting and Index Management plugins. */ val LEGACY_PUBLISH_NOTIFICATION_ACTION_TYPE = ActionType(LEGACY_PUBLISH_NOTIFICATION_NAME, ::LegacyPublishNotificationResponse) diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/EventSource.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/EventSource.kt index 06b28bee..10bf04e3 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/EventSource.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/EventSource.kt @@ -12,7 +12,6 @@ import org.opensearch.common.xcontent.ToXContent import org.opensearch.common.xcontent.XContentBuilder import org.opensearch.common.xcontent.XContentParser import org.opensearch.common.xcontent.XContentParserUtils -import org.opensearch.commons.notifications.NotificationConstants.FEATURE_TAG import org.opensearch.commons.notifications.NotificationConstants.REFERENCE_ID_TAG import org.opensearch.commons.notifications.NotificationConstants.SEVERITY_TAG import org.opensearch.commons.notifications.NotificationConstants.TAGS_TAG @@ -27,7 +26,6 @@ import java.io.IOException data class EventSource( val title: String, val referenceId: String, - val feature: String, val severity: SeverityType = SeverityType.INFO, val tags: List = listOf() ) : BaseModel { @@ -53,7 +51,6 @@ data class EventSource( fun parse(parser: XContentParser): EventSource { var title: String? = null var referenceId: String? = null - var feature: String? = null var severity: SeverityType = SeverityType.INFO var tags: List = emptyList() @@ -68,7 +65,6 @@ data class EventSource( when (fieldName) { TITLE_TAG -> title = parser.text() REFERENCE_ID_TAG -> referenceId = parser.text() - FEATURE_TAG -> feature = parser.text() SEVERITY_TAG -> severity = SeverityType.fromTagOrDefault(parser.text()) TAGS_TAG -> tags = parser.stringList() else -> { @@ -79,12 +75,10 @@ data class EventSource( } title ?: throw IllegalArgumentException("$TITLE_TAG field absent") referenceId ?: throw IllegalArgumentException("$REFERENCE_ID_TAG field absent") - feature ?: throw IllegalArgumentException("$FEATURE_TAG field absent") return EventSource( title, referenceId, - feature, severity, tags ) @@ -99,7 +93,6 @@ data class EventSource( return builder.startObject() .field(TITLE_TAG, title) .field(REFERENCE_ID_TAG, referenceId) - .field(FEATURE_TAG, feature) .field(SEVERITY_TAG, severity.tag) .field(TAGS_TAG, tags) .endObject() @@ -112,7 +105,6 @@ data class EventSource( constructor(input: StreamInput) : this( title = input.readString(), referenceId = input.readString(), - feature = input.readString(), severity = input.readEnum(SeverityType::class.java), tags = input.readStringList() ) @@ -123,7 +115,6 @@ data class EventSource( override fun writeTo(output: StreamOutput) { output.writeString(title) output.writeString(referenceId) - output.writeString(feature) output.writeEnum(severity) output.writeStringCollection(tags) } diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationConfig.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationConfig.kt index e80a5497..f490e8b1 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationConfig.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationConfig.kt @@ -14,17 +14,13 @@ import org.opensearch.common.xcontent.XContentParser import org.opensearch.common.xcontent.XContentParserUtils import org.opensearch.commons.notifications.NotificationConstants.CONFIG_TYPE_TAG import org.opensearch.commons.notifications.NotificationConstants.DESCRIPTION_TAG -import org.opensearch.commons.notifications.NotificationConstants.FEATURE_LIST_TAG import org.opensearch.commons.notifications.NotificationConstants.IS_ENABLED_TAG import org.opensearch.commons.notifications.NotificationConstants.NAME_TAG import org.opensearch.commons.notifications.model.config.ConfigDataProperties.createConfigData import org.opensearch.commons.notifications.model.config.ConfigDataProperties.getReaderForConfigType import org.opensearch.commons.notifications.model.config.ConfigDataProperties.validateConfigData -import org.opensearch.commons.utils.STRING_READER -import org.opensearch.commons.utils.STRING_WRITER import org.opensearch.commons.utils.fieldIfNotNull import org.opensearch.commons.utils.logger -import org.opensearch.commons.utils.stringList import java.io.IOException /** @@ -34,7 +30,6 @@ data class NotificationConfig( val name: String, val description: String, val configType: ConfigType, - val features: Set, val configData: BaseConfigData?, val isEnabled: Boolean = true ) : BaseModel { @@ -68,7 +63,6 @@ data class NotificationConfig( var name: String? = null var description = "" var configType: ConfigType? = null - var features: Set? = null var isEnabled = true var configData: BaseConfigData? = null XContentParserUtils.ensureExpectedToken( @@ -83,7 +77,6 @@ data class NotificationConfig( NAME_TAG -> name = parser.text() DESCRIPTION_TAG -> description = parser.text() CONFIG_TYPE_TAG -> configType = ConfigType.fromTagOrDefault(parser.text()) - FEATURE_LIST_TAG -> features = parser.stringList().toSet() IS_ENABLED_TAG -> isEnabled = parser.booleanValue() else -> { val configTypeForTag = ConfigType.fromTagOrDefault(fieldName) @@ -98,12 +91,10 @@ data class NotificationConfig( } name ?: throw IllegalArgumentException("$NAME_TAG field absent") configType ?: throw IllegalArgumentException("$CONFIG_TYPE_TAG field absent") - features ?: throw IllegalArgumentException("$FEATURE_LIST_TAG field absent") return NotificationConfig( name, description, configType, - features, configData, isEnabled ) @@ -119,7 +110,6 @@ data class NotificationConfig( .field(NAME_TAG, name) .field(DESCRIPTION_TAG, description) .field(CONFIG_TYPE_TAG, configType.tag) - .field(FEATURE_LIST_TAG, features) .field(IS_ENABLED_TAG, isEnabled) .fieldIfNotNull(configType.tag, configData) .endObject() @@ -133,7 +123,6 @@ data class NotificationConfig( name = input.readString(), description = input.readString(), configType = input.readEnum(ConfigType::class.java), - features = input.readSet(STRING_READER), isEnabled = input.readBoolean(), configData = input.readOptionalWriteable(getReaderForConfigType(input.readEnum(ConfigType::class.java))) ) @@ -145,7 +134,6 @@ data class NotificationConfig( output.writeString(name) output.writeString(description) output.writeEnum(configType) - output.writeCollection(features, STRING_WRITER) output.writeBoolean(isEnabled) // Reading config types multiple times in constructor output.writeEnum(configType) diff --git a/src/test/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterfaceTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterfaceTests.kt index 8147650f..f6d3f9c1 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterfaceTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterfaceTests.kt @@ -21,9 +21,6 @@ import org.opensearch.action.ActionListener import org.opensearch.action.ActionType import org.opensearch.client.node.NodeClient import org.opensearch.commons.destination.response.LegacyDestinationResponse -import org.opensearch.commons.notifications.NotificationConstants.FEATURE_ALERTING -import org.opensearch.commons.notifications.NotificationConstants.FEATURE_INDEX_MANAGEMENT -import org.opensearch.commons.notifications.NotificationConstants.FEATURE_REPORTS import org.opensearch.commons.notifications.action.CreateNotificationConfigRequest import org.opensearch.commons.notifications.action.CreateNotificationConfigResponse import org.opensearch.commons.notifications.action.DeleteNotificationConfigRequest @@ -198,7 +195,6 @@ internal class NotificationsPluginInterfaceTests { val notificationInfo = EventSource( "title", "reference_id", - FEATURE_REPORTS, SeverityType.HIGH, listOf("tag1", "tag2") ) @@ -235,10 +231,6 @@ internal class NotificationsPluginInterfaceTests { .onResponse(res) }.whenever(client).execute(any(ActionType::class.java), any(), any()) - doAnswer { - FEATURE_INDEX_MANAGEMENT - }.whenever(request).feature - NotificationsPluginInterface.publishLegacyNotification(client, request, l) verify(l, times(1)).onResponse(eq(res)) } @@ -249,7 +241,6 @@ internal class NotificationsPluginInterfaceTests { "name", "description", ConfigType.SLACK, - setOf(FEATURE_REPORTS), configData = sampleSlack ) val configInfo = NotificationConfigInfo( @@ -265,7 +256,6 @@ internal class NotificationsPluginInterfaceTests { val sampleEventSource = EventSource( "title", "reference_id", - FEATURE_ALERTING, severity = SeverityType.INFO ) val sampleStatus = EventStatus( diff --git a/src/test/kotlin/org/opensearch/commons/notifications/action/CreateNotificationConfigRequestTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/action/CreateNotificationConfigRequestTests.kt index 9eb1de1f..24f389e2 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/action/CreateNotificationConfigRequestTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/action/CreateNotificationConfigRequestTests.kt @@ -9,7 +9,6 @@ import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Assertions.assertNull import org.junit.jupiter.api.Test import org.junit.jupiter.api.assertThrows -import org.opensearch.commons.notifications.NotificationConstants.FEATURE_INDEX_MANAGEMENT import org.opensearch.commons.notifications.model.Chime import org.opensearch.commons.notifications.model.ConfigType import org.opensearch.commons.notifications.model.Email @@ -32,9 +31,8 @@ internal class CreateNotificationConfigRequestTests { "name", "description", ConfigType.WEBHOOK, - setOf(FEATURE_INDEX_MANAGEMENT), - isEnabled = true, - configData = sampleWebhook + configData = sampleWebhook, + isEnabled = true ) } @@ -44,9 +42,8 @@ internal class CreateNotificationConfigRequestTests { "name", "description", ConfigType.SLACK, - setOf(FEATURE_INDEX_MANAGEMENT), - isEnabled = true, - configData = sampleSlack + configData = sampleSlack, + isEnabled = true ) } @@ -56,9 +53,8 @@ internal class CreateNotificationConfigRequestTests { "name", "description", ConfigType.CHIME, - setOf(FEATURE_INDEX_MANAGEMENT), - isEnabled = true, - configData = sampleChime + configData = sampleChime, + isEnabled = true ) } @@ -68,9 +64,8 @@ internal class CreateNotificationConfigRequestTests { "name", "description", ConfigType.EMAIL_GROUP, - setOf(FEATURE_INDEX_MANAGEMENT), - isEnabled = true, - configData = sampleEmailGroup + configData = sampleEmailGroup, + isEnabled = true ) } @@ -84,9 +79,8 @@ internal class CreateNotificationConfigRequestTests { "name", "description", ConfigType.EMAIL, - setOf(FEATURE_INDEX_MANAGEMENT), - isEnabled = true, - configData = sampleEmail + configData = sampleEmail, + isEnabled = true ) } @@ -101,9 +95,8 @@ internal class CreateNotificationConfigRequestTests { "name", "description", ConfigType.SMTP_ACCOUNT, - setOf(FEATURE_INDEX_MANAGEMENT), - isEnabled = true, - configData = sampleSmtpAccount + configData = sampleSmtpAccount, + isEnabled = true ) } @@ -264,9 +257,8 @@ internal class CreateNotificationConfigRequestTests { "name", "description", ConfigType.SLACK, - setOf(FEATURE_INDEX_MANAGEMENT), - isEnabled = true, - configData = sampleSlack + configData = sampleSlack, + isEnabled = true ) val jsonString = """ @@ -275,7 +267,6 @@ internal class CreateNotificationConfigRequestTests { "name":"name", "description":"description", "config_type":"slack", - "feature_list":["index_management"], "is_enabled":true, "slack":{"url":"https://domain.com/sample_slack_url#1234567890"} } @@ -292,9 +283,8 @@ internal class CreateNotificationConfigRequestTests { "name", "description", ConfigType.WEBHOOK, - setOf(FEATURE_INDEX_MANAGEMENT), - isEnabled = true, - configData = sampleWebhook + configData = sampleWebhook, + isEnabled = true ) val jsonString = """ @@ -303,7 +293,6 @@ internal class CreateNotificationConfigRequestTests { "name":"name", "description":"description", "config_type":"webhook", - "feature_list":["index_management"], "is_enabled":true, "webhook":{"url":"https://domain.com/sample_webhook_url#1234567890"} } @@ -320,9 +309,8 @@ internal class CreateNotificationConfigRequestTests { "name", "description", ConfigType.CHIME, - setOf(FEATURE_INDEX_MANAGEMENT), - isEnabled = true, - configData = sampleChime + configData = sampleChime, + isEnabled = true ) val jsonString = """ @@ -332,7 +320,6 @@ internal class CreateNotificationConfigRequestTests { "name":"name", "description":"description", "config_type":"chime", - "feature_list":["index_management"], "is_enabled":true, "chime":{"url":"https://domain.com/sample_chime_url#1234567890"} } @@ -349,9 +336,8 @@ internal class CreateNotificationConfigRequestTests { "name", "description", ConfigType.EMAIL_GROUP, - setOf(FEATURE_INDEX_MANAGEMENT), - isEnabled = true, - configData = sampleEmailGroup + configData = sampleEmailGroup, + isEnabled = true ) val jsonString = """ @@ -361,7 +347,6 @@ internal class CreateNotificationConfigRequestTests { "name":"name", "description":"description", "config_type":"email_group", - "feature_list":["index_management"], "is_enabled":true, "email_group":{"recipient_list":[{"recipient":"dummy@company.com"}]} } @@ -382,9 +367,8 @@ internal class CreateNotificationConfigRequestTests { "name", "description", ConfigType.EMAIL, - setOf(FEATURE_INDEX_MANAGEMENT), - isEnabled = true, - configData = sampleEmail + configData = sampleEmail, + isEnabled = true ) val jsonString = """ @@ -394,7 +378,6 @@ internal class CreateNotificationConfigRequestTests { "name":"name", "description":"description", "config_type":"email", - "feature_list":["index_management"], "is_enabled":true, "email":{ "email_account_id":"sample_1@dummy.com", @@ -420,9 +403,8 @@ internal class CreateNotificationConfigRequestTests { "name", "description", ConfigType.SMTP_ACCOUNT, - setOf(FEATURE_INDEX_MANAGEMENT), - isEnabled = true, - configData = sampleSmtpAccount + configData = sampleSmtpAccount, + isEnabled = true ) val jsonString = """ @@ -432,7 +414,6 @@ internal class CreateNotificationConfigRequestTests { "name":"name", "description":"description", "config_type":"smtp_account", - "feature_list":["index_management"], "is_enabled":true, "smtp_account":{"host":"http://dummy.com", "port":11,"method": "ssl", "from_address": "sample@dummy.com" } } @@ -463,7 +444,6 @@ internal class CreateNotificationConfigRequestTests { "name":"name", "description":"description", "config_type":"chime", - "feature_list":["index_management"], "is_enabled":true, "chime":{"url":"https://domain.com/sample_chime_url#1234567890"} } @@ -488,9 +468,8 @@ internal class CreateNotificationConfigRequestTests { "name", "description", ConfigType.SLACK, - setOf(FEATURE_INDEX_MANAGEMENT), - isEnabled = true, - configData = sampleSlack + configData = sampleSlack, + isEnabled = true ) val jsonString = """ @@ -499,7 +478,6 @@ internal class CreateNotificationConfigRequestTests { "name":"name", "description":"description", "config_type":"slack", - "feature_list":["index_management"], "is_enabled":true, "slack":{"url":"https://domain.com/sample_slack_url#1234567890"}, "extra_field_1":["extra", "value"], diff --git a/src/test/kotlin/org/opensearch/commons/notifications/action/GetFeatureChannelListRequestTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/action/GetFeatureChannelListRequestTests.kt index 98d577de..b9913ae2 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/action/GetFeatureChannelListRequestTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/action/GetFeatureChannelListRequestTests.kt @@ -8,9 +8,6 @@ import com.fasterxml.jackson.core.JsonParseException import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Test import org.junit.jupiter.api.assertThrows -import org.opensearch.commons.notifications.NotificationConstants.FEATURE_ALERTING -import org.opensearch.commons.notifications.NotificationConstants.FEATURE_INDEX_MANAGEMENT -import org.opensearch.commons.notifications.NotificationConstants.FEATURE_REPORTS import org.opensearch.commons.utils.createObjectFromJsonString import org.opensearch.commons.utils.getJsonString import org.opensearch.commons.utils.recreateObject @@ -21,19 +18,19 @@ internal class GetFeatureChannelListRequestTests { expected: GetFeatureChannelListRequest, actual: GetFeatureChannelListRequest ) { - assertEquals(expected.feature, actual.feature) + assertEquals(expected.compact, actual.compact) } @Test fun `Get request serialize and deserialize transport object should be equal`() { - val configRequest = GetFeatureChannelListRequest(FEATURE_REPORTS) + val configRequest = GetFeatureChannelListRequest() val recreatedObject = recreateObject(configRequest) { GetFeatureChannelListRequest(it) } assertGetRequestEquals(configRequest, recreatedObject) } @Test fun `Get request serialize and deserialize using json object should be equal`() { - val configRequest = GetFeatureChannelListRequest(FEATURE_INDEX_MANAGEMENT) + val configRequest = GetFeatureChannelListRequest() val jsonString = getJsonString(configRequest) val recreatedObject = createObjectFromJsonString(jsonString) { GetFeatureChannelListRequest.parse(it) } assertGetRequestEquals(configRequest, recreatedObject) @@ -49,10 +46,9 @@ internal class GetFeatureChannelListRequestTests { @Test fun `Get request should safely ignore extra field in json object`() { - val configRequest = GetFeatureChannelListRequest(FEATURE_ALERTING) + val configRequest = GetFeatureChannelListRequest() val jsonString = """ { - "feature":"${configRequest.feature}", "extra_field_1":["extra", "value"], "extra_field_2":{"extra":"value"}, "extra_field_3":"extra value 3" @@ -61,15 +57,4 @@ internal class GetFeatureChannelListRequestTests { val recreatedObject = createObjectFromJsonString(jsonString) { GetFeatureChannelListRequest.parse(it) } assertGetRequestEquals(configRequest, recreatedObject) } - - @Test - fun `Get request should throw exception if feature field is absent in json object`() { - val jsonString = """ - { - } - """.trimIndent() - assertThrows { - createObjectFromJsonString(jsonString) { GetFeatureChannelListRequest.parse(it) } - } - } } diff --git a/src/test/kotlin/org/opensearch/commons/notifications/action/GetNotificationConfigResponseTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/action/GetNotificationConfigResponseTests.kt index 7541acb2..3cfccfcb 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/action/GetNotificationConfigResponseTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/action/GetNotificationConfigResponseTests.kt @@ -8,8 +8,6 @@ import org.apache.lucene.search.TotalHits import org.junit.jupiter.api.Assertions import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Test -import org.opensearch.commons.notifications.NotificationConstants.FEATURE_INDEX_MANAGEMENT -import org.opensearch.commons.notifications.NotificationConstants.FEATURE_REPORTS import org.opensearch.commons.notifications.model.Chime import org.opensearch.commons.notifications.model.ConfigType import org.opensearch.commons.notifications.model.NotificationConfig @@ -41,7 +39,6 @@ internal class GetNotificationConfigResponseTests { "name", "description", ConfigType.SLACK, - setOf(FEATURE_REPORTS), configData = sampleSlack ) val configInfo = NotificationConfigInfo( @@ -62,7 +59,6 @@ internal class GetNotificationConfigResponseTests { "name", "description", ConfigType.SLACK, - setOf(FEATURE_REPORTS), configData = Slack("https://domain.com/sample_url#1234567890") ) val configInfo1 = NotificationConfigInfo( @@ -75,7 +71,6 @@ internal class GetNotificationConfigResponseTests { "name", "description", ConfigType.CHIME, - setOf(FEATURE_INDEX_MANAGEMENT), configData = Chime("https://domain.com/sample_url#1234567890") ) val configInfo2 = NotificationConfigInfo( @@ -104,7 +99,6 @@ internal class GetNotificationConfigResponseTests { "name", "description", ConfigType.SLACK, - setOf(FEATURE_REPORTS), configData = sampleSlack ) val configInfo = NotificationConfigInfo( @@ -128,7 +122,6 @@ internal class GetNotificationConfigResponseTests { "name", "description", ConfigType.SLACK, - setOf(FEATURE_REPORTS), configData = Slack("https://domain.com/sample_url#1234567890") ) val configInfo1 = NotificationConfigInfo( @@ -141,7 +134,6 @@ internal class GetNotificationConfigResponseTests { "name", "description", ConfigType.CHIME, - setOf(FEATURE_INDEX_MANAGEMENT), configData = Chime("https://domain.com/sample_url#1234567890") ) val configInfo2 = NotificationConfigInfo( @@ -171,9 +163,8 @@ internal class GetNotificationConfigResponseTests { "name", "description", ConfigType.SLACK, - setOf(FEATURE_INDEX_MANAGEMENT), - isEnabled = true, - configData = sampleSlack + configData = sampleSlack, + isEnabled = true ) val configInfo = NotificationConfigInfo( "config-Id", @@ -196,7 +187,6 @@ internal class GetNotificationConfigResponseTests { "name":"name", "description":"description", "config_type":"slack", - "feature_list":["index_management"], "is_enabled":true, "slack":{"url":"https://domain.com/sample_slack_url#1234567890"} } @@ -220,9 +210,8 @@ internal class GetNotificationConfigResponseTests { "name", "description", ConfigType.SLACK, - setOf(FEATURE_INDEX_MANAGEMENT), - isEnabled = true, - configData = sampleSlack + configData = sampleSlack, + isEnabled = true ) val configInfo = NotificationConfigInfo( "config-Id", @@ -242,7 +231,6 @@ internal class GetNotificationConfigResponseTests { "name":"name", "description":"description", "config_type":"slack", - "feature_list":["index_management"], "is_enabled":true, "slack":{"url":"https://domain.com/sample_slack_url#1234567890"} } diff --git a/src/test/kotlin/org/opensearch/commons/notifications/action/GetNotificationEventResponseTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/action/GetNotificationEventResponseTests.kt index 16139bb1..0de1c78b 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/action/GetNotificationEventResponseTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/action/GetNotificationEventResponseTests.kt @@ -8,8 +8,6 @@ import org.apache.lucene.search.TotalHits import org.junit.jupiter.api.Assertions import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Test -import org.opensearch.commons.notifications.NotificationConstants.FEATURE_ALERTING -import org.opensearch.commons.notifications.NotificationConstants.FEATURE_REPORTS import org.opensearch.commons.notifications.model.ConfigType import org.opensearch.commons.notifications.model.DeliveryStatus import org.opensearch.commons.notifications.model.EventSource @@ -41,7 +39,6 @@ internal class GetNotificationEventResponseTests { val sampleEventSource = EventSource( "title", "reference_id", - FEATURE_ALERTING, severity = SeverityType.INFO ) val sampleStatus = EventStatus( @@ -68,13 +65,11 @@ internal class GetNotificationEventResponseTests { val eventSource1 = EventSource( "title 1", "reference_id_1", - FEATURE_ALERTING, severity = SeverityType.INFO ) val eventSource2 = EventSource( "title 2", "reference_id_2", - FEATURE_REPORTS, severity = SeverityType.HIGH ) val status1 = EventStatus( @@ -131,7 +126,6 @@ internal class GetNotificationEventResponseTests { val sampleEventSource = EventSource( "title", "reference_id", - FEATURE_ALERTING, severity = SeverityType.INFO ) val sampleStatus = EventStatus( @@ -161,13 +155,11 @@ internal class GetNotificationEventResponseTests { val eventSource1 = EventSource( "title 1", "reference_id_1", - FEATURE_ALERTING, severity = SeverityType.INFO ) val eventSource2 = EventSource( "title 2", "reference_id_2", - FEATURE_REPORTS, severity = SeverityType.HIGH ) val status1 = EventStatus( @@ -213,7 +205,6 @@ internal class GetNotificationEventResponseTests { val sampleEventSource = EventSource( "title", "reference_id", - FEATURE_ALERTING, severity = SeverityType.INFO ) val sampleStatus = EventStatus( @@ -244,7 +235,6 @@ internal class GetNotificationEventResponseTests { "event_source":{ "title":"title", "reference_id":"reference_id", - "feature":"alerting", "severity":"info", "tags":[] }, @@ -279,7 +269,6 @@ internal class GetNotificationEventResponseTests { val sampleEventSource = EventSource( "title", "reference_id", - FEATURE_ALERTING, severity = SeverityType.INFO ) val sampleStatus = EventStatus( @@ -307,7 +296,6 @@ internal class GetNotificationEventResponseTests { "event_source":{ "title":"title", "reference_id":"reference_id", - "feature":"alerting", "severity":"info", "tags":[] }, diff --git a/src/test/kotlin/org/opensearch/commons/notifications/action/LegacyPublishNotificationRequestTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/action/LegacyPublishNotificationRequestTests.kt index c323ec85..e4b990a5 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/action/LegacyPublishNotificationRequestTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/action/LegacyPublishNotificationRequestTests.kt @@ -9,7 +9,6 @@ import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Assertions.assertNull import org.junit.jupiter.api.Test import org.opensearch.commons.destination.message.LegacyChimeMessage -import org.opensearch.commons.notifications.NotificationConstants.FEATURE_INDEX_MANAGEMENT import org.opensearch.commons.utils.recreateObject internal class LegacyPublishNotificationRequestTests { @@ -22,14 +21,13 @@ internal class LegacyPublishNotificationRequestTests { assertEquals(expected.baseMessage.channelType, actual.baseMessage.channelType) assertEquals(expected.baseMessage.messageContent, actual.baseMessage.messageContent) assertEquals(expected.baseMessage.url, actual.baseMessage.url) - assertEquals(expected.feature, actual.feature) assertNull(actual.validate()) } @Test fun `publish request serialize and deserialize transport object should be equal`() { val baseMessage = LegacyChimeMessage.Builder("chime_message").withMessage("Hello world").withUrl("https://amazon.com").build() - val request = LegacyPublishNotificationRequest(baseMessage, FEATURE_INDEX_MANAGEMENT) + val request = LegacyPublishNotificationRequest(baseMessage) val recreatedObject = recreateObject(request) { LegacyPublishNotificationRequest(it) } assertRequestEquals(request, recreatedObject) } diff --git a/src/test/kotlin/org/opensearch/commons/notifications/action/SendNotificationRequestTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/action/SendNotificationRequestTests.kt index 3874190c..70e0bd6c 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/action/SendNotificationRequestTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/action/SendNotificationRequestTests.kt @@ -10,9 +10,6 @@ import org.junit.jupiter.api.Assertions.assertNotNull import org.junit.jupiter.api.Assertions.assertNull import org.junit.jupiter.api.Test import org.junit.jupiter.api.assertThrows -import org.opensearch.commons.notifications.NotificationConstants.FEATURE_ALERTING -import org.opensearch.commons.notifications.NotificationConstants.FEATURE_INDEX_MANAGEMENT -import org.opensearch.commons.notifications.NotificationConstants.FEATURE_REPORTS import org.opensearch.commons.notifications.model.ChannelMessage import org.opensearch.commons.notifications.model.EventSource import org.opensearch.commons.notifications.model.SeverityType @@ -38,7 +35,6 @@ internal class SendNotificationRequestTests { val notificationInfo = EventSource( "title", "reference_id", - FEATURE_REPORTS, SeverityType.HIGH, listOf("tag1", "tag2") ) @@ -62,7 +58,6 @@ internal class SendNotificationRequestTests { val notificationInfo = EventSource( "title", "reference_id", - FEATURE_INDEX_MANAGEMENT, SeverityType.CRITICAL, listOf("tag1", "tag2") ) @@ -95,7 +90,6 @@ internal class SendNotificationRequestTests { val notificationInfo = EventSource( "title", "reference_id", - FEATURE_ALERTING, SeverityType.HIGH, listOf("tag1", "tag2") ) @@ -115,7 +109,6 @@ internal class SendNotificationRequestTests { "event_source":{ "title":"${notificationInfo.title}", "reference_id":"${notificationInfo.referenceId}", - "feature":"${notificationInfo.feature}", "severity":"${notificationInfo.severity}", "tags":["tag1", "tag2"] }, @@ -139,7 +132,6 @@ internal class SendNotificationRequestTests { val notificationInfo = EventSource( "title", "reference_id", - FEATURE_REPORTS, SeverityType.INFO, listOf("tag1", "tag2") ) @@ -159,7 +151,6 @@ internal class SendNotificationRequestTests { "event_source":{ "title":"${notificationInfo.title}", "reference_id":"${notificationInfo.referenceId}", - "feature":"${notificationInfo.feature}", "severity":"${notificationInfo.severity}", "tags":["tag1", "tag2"] }, @@ -196,7 +187,6 @@ internal class SendNotificationRequestTests { "event_source":{ "title":"title", "reference_id":"reference_id", - "feature":"feature", "severity":"High", "tags":["tag1", "tag2"] }, @@ -215,7 +205,6 @@ internal class SendNotificationRequestTests { "event_source":{ "title":"title", "reference_id":"reference_id", - "feature":"feature", "severity":"High", "tags":["tag1", "tag2"] }, @@ -236,7 +225,6 @@ internal class SendNotificationRequestTests { "event_source":{ "title":"title", "reference_id":"reference_id", - "feature":"feature", "severity":"High", "tags":["tag1", "tag2"] }, diff --git a/src/test/kotlin/org/opensearch/commons/notifications/action/UpdateNotificationConfigRequestTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/action/UpdateNotificationConfigRequestTests.kt index 725e3c59..a6e0077a 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/action/UpdateNotificationConfigRequestTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/action/UpdateNotificationConfigRequestTests.kt @@ -9,7 +9,6 @@ import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Assertions.assertNull import org.junit.jupiter.api.Test import org.junit.jupiter.api.assertThrows -import org.opensearch.commons.notifications.NotificationConstants.FEATURE_INDEX_MANAGEMENT import org.opensearch.commons.notifications.model.Chime import org.opensearch.commons.notifications.model.ConfigType import org.opensearch.commons.notifications.model.Email @@ -32,9 +31,8 @@ internal class UpdateNotificationConfigRequestTests { "name", "description", ConfigType.WEBHOOK, - setOf(FEATURE_INDEX_MANAGEMENT), - isEnabled = true, - configData = sampleWebhook + configData = sampleWebhook, + isEnabled = true ) } @@ -44,9 +42,8 @@ internal class UpdateNotificationConfigRequestTests { "name", "description", ConfigType.SLACK, - setOf(FEATURE_INDEX_MANAGEMENT), - isEnabled = true, - configData = sampleSlack + configData = sampleSlack, + isEnabled = true ) } @@ -56,9 +53,8 @@ internal class UpdateNotificationConfigRequestTests { "name", "description", ConfigType.CHIME, - setOf(FEATURE_INDEX_MANAGEMENT), - isEnabled = true, - configData = sampleChime + configData = sampleChime, + isEnabled = true ) } @@ -68,9 +64,8 @@ internal class UpdateNotificationConfigRequestTests { "name", "description", ConfigType.EMAIL_GROUP, - setOf(FEATURE_INDEX_MANAGEMENT), - isEnabled = true, - configData = sampleEmailGroup + configData = sampleEmailGroup, + isEnabled = true ) } @@ -84,9 +79,8 @@ internal class UpdateNotificationConfigRequestTests { "name", "description", ConfigType.EMAIL, - setOf(FEATURE_INDEX_MANAGEMENT), - isEnabled = true, - configData = sampleEmail + configData = sampleEmail, + isEnabled = true ) } @@ -101,9 +95,8 @@ internal class UpdateNotificationConfigRequestTests { "name", "description", ConfigType.SMTP_ACCOUNT, - setOf(FEATURE_INDEX_MANAGEMENT), - isEnabled = true, - configData = sampleSmtpAccount + configData = sampleSmtpAccount, + isEnabled = true ) } @@ -228,9 +221,8 @@ internal class UpdateNotificationConfigRequestTests { "name", "description", ConfigType.SLACK, - setOf(FEATURE_INDEX_MANAGEMENT), - isEnabled = true, - configData = sampleSlack + configData = sampleSlack, + isEnabled = true ) val jsonString = """ @@ -258,9 +250,8 @@ internal class UpdateNotificationConfigRequestTests { "name", "description", ConfigType.WEBHOOK, - setOf(FEATURE_INDEX_MANAGEMENT), - isEnabled = true, - configData = sampleWebhook + configData = sampleWebhook, + isEnabled = true ) val jsonString = """ @@ -288,9 +279,8 @@ internal class UpdateNotificationConfigRequestTests { "name", "description", ConfigType.CHIME, - setOf(FEATURE_INDEX_MANAGEMENT), - isEnabled = true, - configData = sampleChime + configData = sampleChime, + isEnabled = true ) val jsonString = """ @@ -318,9 +308,8 @@ internal class UpdateNotificationConfigRequestTests { "name", "description", ConfigType.EMAIL_GROUP, - setOf(FEATURE_INDEX_MANAGEMENT), - isEnabled = true, - configData = sampleEmailGroup + configData = sampleEmailGroup, + isEnabled = true ) val jsonString = """ @@ -352,9 +341,8 @@ internal class UpdateNotificationConfigRequestTests { "name", "description", ConfigType.EMAIL, - setOf(FEATURE_INDEX_MANAGEMENT), - isEnabled = true, - configData = sampleEmail + configData = sampleEmail, + isEnabled = true ) val jsonString = """ @@ -391,9 +379,8 @@ internal class UpdateNotificationConfigRequestTests { "name", "description", ConfigType.SMTP_ACCOUNT, - setOf(FEATURE_INDEX_MANAGEMENT), - isEnabled = true, - configData = sampleSmtpAccount + configData = sampleSmtpAccount, + isEnabled = true ) val jsonString = """ @@ -429,9 +416,8 @@ internal class UpdateNotificationConfigRequestTests { "name", "description", ConfigType.SLACK, - setOf(FEATURE_INDEX_MANAGEMENT), - isEnabled = true, - configData = sampleSlack + configData = sampleSlack, + isEnabled = true ) val jsonString = """ diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/EventSourceTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/EventSourceTests.kt index 2244d0c4..b36a2fc0 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/EventSourceTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/EventSourceTests.kt @@ -7,7 +7,6 @@ package org.opensearch.commons.notifications.model import org.junit.jupiter.api.Assertions import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Test -import org.opensearch.commons.notifications.NotificationConstants.FEATURE_ALERTING import org.opensearch.commons.utils.createObjectFromJsonString import org.opensearch.commons.utils.getJsonString import org.opensearch.commons.utils.recreateObject @@ -19,7 +18,6 @@ internal class EventSourceTests { val sampleEventSource = EventSource( "title", "reference_id", - FEATURE_ALERTING, severity = SeverityType.INFO ) val recreatedObject = recreateObject(sampleEventSource) { EventSource(it) } @@ -31,7 +29,6 @@ internal class EventSourceTests { val sampleEventSource = EventSource( "title", "reference_id", - FEATURE_ALERTING, severity = SeverityType.INFO ) @@ -45,9 +42,8 @@ internal class EventSourceTests { val sampleEventSource = EventSource( "title", "reference_id", - FEATURE_ALERTING, - tags = listOf("tag1", "tag2"), - severity = SeverityType.INFO + severity = SeverityType.INFO, + tags = listOf("tag1", "tag2") ) val jsonString = """ { @@ -70,9 +66,8 @@ internal class EventSourceTests { val sampleEventSource = EventSource( "title", "reference_id", - "NewFeature", - tags = listOf("tag1", "tag2"), - severity = SeverityType.INFO + severity = SeverityType.INFO, + tags = listOf("tag1", "tag2") ) val jsonString = """ { @@ -93,9 +88,8 @@ internal class EventSourceTests { EventSource( "", "reference_id", - FEATURE_ALERTING, - tags = listOf("tag1", "tag2"), - severity = SeverityType.INFO + severity = SeverityType.INFO, + tags = listOf("tag1", "tag2") ) } } diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationConfigInfoTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationConfigInfoTests.kt index d14b9f34..c4e28f33 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationConfigInfoTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationConfigInfoTests.kt @@ -7,8 +7,6 @@ package org.opensearch.commons.notifications.model import org.junit.jupiter.api.Assertions import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Test -import org.opensearch.commons.notifications.NotificationConstants.FEATURE_INDEX_MANAGEMENT -import org.opensearch.commons.notifications.NotificationConstants.FEATURE_REPORTS import org.opensearch.commons.utils.createObjectFromJsonString import org.opensearch.commons.utils.getJsonString import org.opensearch.commons.utils.recreateObject @@ -23,7 +21,6 @@ internal class NotificationConfigInfoTests { "name", "description", ConfigType.SLACK, - setOf(FEATURE_REPORTS), configData = sampleSlack ) val configInfo = NotificationConfigInfo( @@ -45,7 +42,6 @@ internal class NotificationConfigInfoTests { "name", "description", ConfigType.SLACK, - setOf(FEATURE_REPORTS), configData = sampleSlack ) val configInfo = NotificationConfigInfo( @@ -68,9 +64,8 @@ internal class NotificationConfigInfoTests { "name", "description", ConfigType.SLACK, - setOf(FEATURE_INDEX_MANAGEMENT), - isEnabled = true, - configData = sampleSlack + configData = sampleSlack, + isEnabled = true ) val configInfo = NotificationConfigInfo( "config-Id", @@ -107,7 +102,6 @@ internal class NotificationConfigInfoTests { "name", "description", ConfigType.SLACK, - setOf(FEATURE_REPORTS), configData = sampleSlack ) Assertions.assertThrows(IllegalArgumentException::class.java) { diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationConfigSearchResultsTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationConfigSearchResultsTests.kt index 835af358..06bb3557 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationConfigSearchResultsTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationConfigSearchResultsTests.kt @@ -8,8 +8,6 @@ import org.apache.lucene.search.TotalHits import org.junit.jupiter.api.Assertions import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Test -import org.opensearch.commons.notifications.NotificationConstants.FEATURE_INDEX_MANAGEMENT -import org.opensearch.commons.notifications.NotificationConstants.FEATURE_REPORTS import org.opensearch.commons.utils.createObjectFromJsonString import org.opensearch.commons.utils.getJsonString import org.opensearch.commons.utils.recreateObject @@ -35,7 +33,6 @@ internal class NotificationConfigSearchResultsTests { "name", "description", ConfigType.SLACK, - setOf(FEATURE_REPORTS), configData = sampleSlack ) val configInfo = NotificationConfigInfo( @@ -55,7 +52,6 @@ internal class NotificationConfigSearchResultsTests { "name", "description", ConfigType.SLACK, - setOf(FEATURE_REPORTS), configData = Slack("https://domain.com/sample_url#1234567890") ) val configInfo1 = NotificationConfigInfo( @@ -68,7 +64,6 @@ internal class NotificationConfigSearchResultsTests { "name", "description", ConfigType.CHIME, - setOf(FEATURE_INDEX_MANAGEMENT), configData = Chime("https://domain.com/sample_url#1234567890") ) val configInfo2 = NotificationConfigInfo( @@ -94,7 +89,6 @@ internal class NotificationConfigSearchResultsTests { "name", "description", ConfigType.SLACK, - setOf(FEATURE_REPORTS), configData = Slack("https://domain.com/sample_url#1234567890") ) val configInfo1 = NotificationConfigInfo( @@ -107,7 +101,6 @@ internal class NotificationConfigSearchResultsTests { "name", "description", ConfigType.CHIME, - setOf(FEATURE_INDEX_MANAGEMENT), configData = Chime("https://domain.com/sample_url#1234567890") ) val configInfo2 = NotificationConfigInfo( @@ -135,7 +128,6 @@ internal class NotificationConfigSearchResultsTests { "name", "description", ConfigType.SLACK, - setOf(FEATURE_REPORTS), configData = sampleSlack ) val configInfo = NotificationConfigInfo( @@ -158,7 +150,6 @@ internal class NotificationConfigSearchResultsTests { "name", "description", ConfigType.SLACK, - setOf(FEATURE_REPORTS), configData = Slack("https://domain.com/sample_url#1234567890") ) val configInfo1 = NotificationConfigInfo( @@ -171,7 +162,6 @@ internal class NotificationConfigSearchResultsTests { "name", "description", ConfigType.CHIME, - setOf(FEATURE_INDEX_MANAGEMENT), configData = Chime("https://domain.com/sample_url#1234567890") ) val configInfo2 = NotificationConfigInfo( @@ -200,9 +190,8 @@ internal class NotificationConfigSearchResultsTests { "name", "description", ConfigType.SLACK, - setOf(FEATURE_INDEX_MANAGEMENT), - isEnabled = true, - configData = sampleSlack + configData = sampleSlack, + isEnabled = true ) val configInfo = NotificationConfigInfo( "config-Id", @@ -249,9 +238,8 @@ internal class NotificationConfigSearchResultsTests { "name", "description", ConfigType.SLACK, - setOf(FEATURE_INDEX_MANAGEMENT), - isEnabled = true, - configData = sampleSlack + configData = sampleSlack, + isEnabled = true ) val configInfo = NotificationConfigInfo( "config-Id", diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationConfigTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationConfigTests.kt index 47614986..f8aa9e9d 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationConfigTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationConfigTests.kt @@ -6,9 +6,6 @@ package org.opensearch.commons.notifications.model import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Test -import org.opensearch.commons.notifications.NotificationConstants.FEATURE_ALERTING -import org.opensearch.commons.notifications.NotificationConstants.FEATURE_INDEX_MANAGEMENT -import org.opensearch.commons.notifications.NotificationConstants.FEATURE_REPORTS import org.opensearch.commons.utils.createObjectFromJsonString import org.opensearch.commons.utils.getJsonString import org.opensearch.commons.utils.recreateObject @@ -22,7 +19,6 @@ internal class NotificationConfigTests { "name", "description", ConfigType.SLACK, - setOf(FEATURE_REPORTS), configData = sampleSlack ) val recreatedObject = recreateObject(sampleConfig) { NotificationConfig(it) } @@ -36,7 +32,6 @@ internal class NotificationConfigTests { "name", "description", ConfigType.SLACK, - setOf(FEATURE_REPORTS), configData = sampleSlack ) val jsonString = getJsonString(sampleConfig) @@ -51,7 +46,6 @@ internal class NotificationConfigTests { "name", "description", ConfigType.CHIME, - setOf(FEATURE_ALERTING), configData = sampleChime ) val recreatedObject = recreateObject(sampleConfig) { NotificationConfig(it) } @@ -65,7 +59,6 @@ internal class NotificationConfigTests { "name", "description", ConfigType.CHIME, - setOf(FEATURE_ALERTING), configData = sampleChime ) val jsonString = getJsonString(sampleConfig) @@ -80,7 +73,6 @@ internal class NotificationConfigTests { "name", "description", ConfigType.WEBHOOK, - setOf(FEATURE_INDEX_MANAGEMENT), configData = sampleWebhook ) val recreatedObject = recreateObject(sampleConfig) { NotificationConfig(it) } @@ -94,7 +86,6 @@ internal class NotificationConfigTests { "name", "description", ConfigType.WEBHOOK, - setOf(FEATURE_INDEX_MANAGEMENT), configData = sampleWebhook ) val jsonString = getJsonString(sampleConfig) @@ -109,7 +100,6 @@ internal class NotificationConfigTests { "name", "description", ConfigType.EMAIL, - setOf(FEATURE_INDEX_MANAGEMENT), configData = sampleEmail ) val recreatedObject = recreateObject(sampleConfig) { NotificationConfig(it) } @@ -123,7 +113,6 @@ internal class NotificationConfigTests { "name", "description", ConfigType.EMAIL, - setOf(FEATURE_INDEX_MANAGEMENT), configData = sampleEmail ) val jsonString = getJsonString(sampleConfig) @@ -138,7 +127,6 @@ internal class NotificationConfigTests { "name", "description", ConfigType.SMTP_ACCOUNT, - setOf(FEATURE_INDEX_MANAGEMENT), configData = smtpAccount ) val jsonString = getJsonString(sampleConfig) @@ -153,7 +141,6 @@ internal class NotificationConfigTests { "name", "description", ConfigType.SMTP_ACCOUNT, - setOf(FEATURE_INDEX_MANAGEMENT), configData = sampleSmtpAccount ) val recreatedObject = recreateObject(sampleConfig) { NotificationConfig(it) } @@ -167,7 +154,6 @@ internal class NotificationConfigTests { "name", "description", ConfigType.EMAIL_GROUP, - setOf(FEATURE_INDEX_MANAGEMENT), configData = sampleEmailGroup ) val jsonString = getJsonString(sampleConfig) @@ -182,7 +168,6 @@ internal class NotificationConfigTests { "name", "description", ConfigType.EMAIL_GROUP, - setOf(FEATURE_INDEX_MANAGEMENT), configData = sampleEmailGroup ) val recreatedObject = recreateObject(sampleConfig) { NotificationConfig(it) } @@ -197,9 +182,8 @@ internal class NotificationConfigTests { "name", "description", ConfigType.NONE, - setOf(FEATURE_INDEX_MANAGEMENT), - isEnabled = true, - configData = sampleSlack + configData = sampleSlack, + isEnabled = true ) val jsonString = """ { @@ -226,9 +210,8 @@ internal class NotificationConfigTests { "name", "description", ConfigType.WEBHOOK, - setOf(FEATURE_INDEX_MANAGEMENT, "NewFeature1", "NewFeature2"), - isEnabled = true, - configData = sampleWebhook + configData = sampleWebhook, + isEnabled = true ) val jsonString = """ { diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationEventInfoTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationEventInfoTests.kt index a87e334a..85d2dee9 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationEventInfoTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationEventInfoTests.kt @@ -7,7 +7,6 @@ package org.opensearch.commons.notifications.model import org.junit.jupiter.api.Assertions import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Test -import org.opensearch.commons.notifications.NotificationConstants.FEATURE_ALERTING import org.opensearch.commons.utils.createObjectFromJsonString import org.opensearch.commons.utils.getJsonString import org.opensearch.commons.utils.recreateObject @@ -20,7 +19,6 @@ internal class NotificationEventInfoTests { val sampleEventSource = EventSource( "title", "reference_id", - FEATURE_ALERTING, severity = SeverityType.INFO ) val sampleStatus = EventStatus( @@ -47,7 +45,6 @@ internal class NotificationEventInfoTests { val sampleEventSource = EventSource( "title", "reference_id", - FEATURE_ALERTING, severity = SeverityType.INFO ) val sampleStatus = EventStatus( @@ -75,7 +72,6 @@ internal class NotificationEventInfoTests { val sampleEventSource = EventSource( "title", "reference_id", - FEATURE_ALERTING, severity = SeverityType.INFO ) val sampleStatus = EventStatus( @@ -133,7 +129,6 @@ internal class NotificationEventInfoTests { val sampleEventSource = EventSource( "title", "reference_id", - FEATURE_ALERTING, severity = SeverityType.INFO ) val sampleStatus = EventStatus( diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationEventSearchResultTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationEventSearchResultTests.kt index ae3f01a9..b65a0783 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationEventSearchResultTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationEventSearchResultTests.kt @@ -8,8 +8,6 @@ import org.apache.lucene.search.TotalHits import org.junit.jupiter.api.Assertions import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Test -import org.opensearch.commons.notifications.NotificationConstants.FEATURE_ALERTING -import org.opensearch.commons.notifications.NotificationConstants.FEATURE_REPORTS import org.opensearch.commons.utils.createObjectFromJsonString import org.opensearch.commons.utils.getJsonString import org.opensearch.commons.utils.recreateObject @@ -33,7 +31,6 @@ internal class NotificationEventSearchResultTests { val sampleEventSource = EventSource( "title", "reference_id", - FEATURE_ALERTING, severity = SeverityType.INFO ) val sampleStatus = EventStatus( @@ -59,13 +56,11 @@ internal class NotificationEventSearchResultTests { val eventSource1 = EventSource( "title 1", "reference_id_1", - FEATURE_ALERTING, severity = SeverityType.INFO ) val eventSource2 = EventSource( "title 2", "reference_id_2", - FEATURE_REPORTS, severity = SeverityType.HIGH ) val status1 = EventStatus( @@ -122,13 +117,11 @@ internal class NotificationEventSearchResultTests { val eventSource1 = EventSource( "title 1", "reference_id_1", - FEATURE_ALERTING, severity = SeverityType.INFO ) val eventSource2 = EventSource( "title 2", "reference_id_2", - FEATURE_REPORTS, severity = SeverityType.HIGH ) val status1 = EventStatus( @@ -184,7 +177,6 @@ internal class NotificationEventSearchResultTests { val sampleEventSource = EventSource( "title", "reference_id", - FEATURE_ALERTING, severity = SeverityType.INFO ) val sampleStatus = EventStatus( @@ -213,13 +205,11 @@ internal class NotificationEventSearchResultTests { val eventSource1 = EventSource( "title 1", "reference_id_1", - FEATURE_ALERTING, severity = SeverityType.INFO ) val eventSource2 = EventSource( "title 2", "reference_id_2", - FEATURE_REPORTS, severity = SeverityType.HIGH ) val status1 = EventStatus( @@ -264,7 +254,6 @@ internal class NotificationEventSearchResultTests { val sampleEventSource = EventSource( "title", "reference_id", - FEATURE_ALERTING, severity = SeverityType.INFO ) val sampleStatus = EventStatus( @@ -330,7 +319,6 @@ internal class NotificationEventSearchResultTests { val sampleEventSource = EventSource( "title", "reference_id", - FEATURE_ALERTING, severity = SeverityType.INFO ) val sampleStatus = EventStatus( diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationEventTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationEventTests.kt index 313ffca9..57df6066 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationEventTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationEventTests.kt @@ -7,8 +7,6 @@ package org.opensearch.commons.notifications.model import org.junit.jupiter.api.Assertions import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Test -import org.opensearch.commons.notifications.NotificationConstants.FEATURE_ALERTING -import org.opensearch.commons.notifications.NotificationConstants.FEATURE_REPORTS import org.opensearch.commons.utils.createObjectFromJsonString import org.opensearch.commons.utils.getJsonString import org.opensearch.commons.utils.recreateObject @@ -20,7 +18,6 @@ internal class NotificationEventTests { val sampleEventSource = EventSource( "title", "reference_id", - FEATURE_ALERTING, severity = SeverityType.INFO ) val sampleStatus = EventStatus( @@ -39,7 +36,6 @@ internal class NotificationEventTests { val sampleEventSource = EventSource( "title", "reference_id", - FEATURE_REPORTS, severity = SeverityType.INFO ) val sampleStatus = EventStatus( @@ -59,9 +55,8 @@ internal class NotificationEventTests { val sampleEventSource = EventSource( "title", "reference_id", - FEATURE_ALERTING, - tags = listOf("tag1", "tag2"), - severity = SeverityType.INFO + severity = SeverityType.INFO, + tags = listOf("tag1", "tag2") ) val status1 = EventStatus( "config_id1", From 7ab297e5f99be5a8cf1b3225f570587b10d301bc Mon Sep 17 00:00:00 2001 From: Marc Handalian Date: Fri, 18 Mar 2022 12:14:33 -0700 Subject: [PATCH 041/140] Add opensearch repositories plugin to resolve lucene snapshot dependencies. (#137) Signed-off-by: Marc Handalian --- build.gradle | 1 + 1 file changed, 1 insertion(+) diff --git a/build.gradle b/build.gradle index 16c28922..bc142d75 100644 --- a/build.gradle +++ b/build.gradle @@ -65,6 +65,7 @@ apply plugin: 'com.github.johnrengelman.shadow' apply plugin: 'io.gitlab.arturbosch.detekt' apply plugin: 'org.jetbrains.kotlin.jvm' apply plugin: 'org.jetbrains.kotlin.plugin.allopen' +apply plugin: 'opensearch.repositories' configurations { ktlint From a0868058fac2dbd1f109e0213ec030b569d02941 Mon Sep 17 00:00:00 2001 From: Saurabh Singh Date: Mon, 21 Mar 2022 15:22:54 -0700 Subject: [PATCH 042/140] Update MAINTAINERS.m to add new maintainer. (#127) Signed-off-by: Saurabh Singh Co-authored-by: Saurabh Singh --- MAINTAINERS.md | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/MAINTAINERS.md b/MAINTAINERS.md index c50082af..3802e32b 100644 --- a/MAINTAINERS.md +++ b/MAINTAINERS.md @@ -1,13 +1,14 @@ ## Maintainers -| Maintainer | GitHub ID | Affiliation | -| --------------- | --------- | ----------- | -| Ashish Agrawal | [lezzago](https://github.com/lezzago) | Amazon | -| Mohammad Qureshi | [qreshi](https://github.com/qreshi) | Amazon | -| Sriram Kosuri | [skkosuri-amzn](https://github.com/skkosuri-amzn) | Amazon | -| Bowen Lan | [bowenlan-amzn](https://github.com/bowenlan-amzn) | Amazon | -| Rishabh Maurya | [rishabhmaurya](https://github.com/rishabhmaurya) | Amazon | -| Tianli Feng | [tlfeng](https://github.com/tlfeng) | Amazon | -| Annie Lee | [leeyun-amzn](https://github.com/leeyun-amzn) | Amazon | +| Maintainer | GitHub ID | Affiliation | +|------------------|---------------------------------------------------| ----------- | +| Ashish Agrawal | [lezzago](https://github.com/lezzago) | Amazon | +| Mohammad Qureshi | [qreshi](https://github.com/qreshi) | Amazon | +| Sriram Kosuri | [skkosuri-amzn](https://github.com/skkosuri-amzn) | Amazon | +| Bowen Lan | [bowenlan-amzn](https://github.com/bowenlan-amzn) | Amazon | +| Rishabh Maurya | [rishabhmaurya](https://github.com/rishabhmaurya) | Amazon | +| Tianli Feng | [tlfeng](https://github.com/tlfeng) | Amazon | +| Annie Lee | [leeyun-amzn](https://github.com/leeyun-amzn) | Amazon | +| Saurabh Singh | [getsaurabh02](https://github.com/getsaurabh02) | Amazon | [This document](https://github.com/opensearch-project/.github/blob/main/MAINTAINERS.md) explains what maintainers do in this repo, and how they should be doing it. If you're interested in contributing, see [CONTRIBUTING](CONTRIBUTING.md). From d77dec5a69e9f99c2948a06d088b505e5fa1dd7e Mon Sep 17 00:00:00 2001 From: Mohammad Qureshi <47198598+qreshi@users.noreply.github.com> Date: Tue, 22 Mar 2022 10:19:41 -0700 Subject: [PATCH 043/140] Rename references for Get Channels API (#140) Signed-off-by: Mohammad Qureshi <47198598+qreshi@users.noreply.github.com> --- .../notifications/NotificationConstants.kt | 2 +- .../NotificationsPluginInterface.kt | 18 ++-- ...istRequest.kt => GetChannelListRequest.kt} | 12 +-- ...tResponse.kt => GetChannelListResponse.kt} | 16 ++-- .../action/NotificationsActions.kt | 8 +- .../model/{FeatureChannel.kt => Channel.kt} | 14 +-- .../{FeatureChannelList.kt => ChannelList.kt} | 26 +++--- .../NotificationsPluginInterfaceTests.kt | 24 +++--- ...Tests.kt => GetChannelListRequestTests.kt} | 20 ++--- ...ests.kt => GetChannelListResponseTests.kt} | 78 ++++++++--------- ...hannelListTests.kt => ChannelListTests.kt} | 86 +++++++++---------- ...FeatureChannelTests.kt => ChannelTests.kt} | 72 ++++++++-------- .../model/FilterConfigListTests.kt | 64 +++++++------- .../notifications/model/FilterConfigTests.kt | 28 +++--- 14 files changed, 234 insertions(+), 234 deletions(-) rename src/main/kotlin/org/opensearch/commons/notifications/action/{GetFeatureChannelListRequest.kt => GetChannelListRequest.kt} (88%) rename src/main/kotlin/org/opensearch/commons/notifications/action/{GetFeatureChannelListResponse.kt => GetChannelListResponse.kt} (75%) rename src/main/kotlin/org/opensearch/commons/notifications/model/{FeatureChannel.kt => Channel.kt} (92%) rename src/main/kotlin/org/opensearch/commons/notifications/model/{FeatureChannelList.kt => ChannelList.kt} (62%) rename src/test/kotlin/org/opensearch/commons/notifications/action/{GetFeatureChannelListRequestTests.kt => GetChannelListRequestTests.kt} (76%) rename src/test/kotlin/org/opensearch/commons/notifications/action/{GetFeatureChannelListResponseTests.kt => GetChannelListResponseTests.kt} (73%) rename src/test/kotlin/org/opensearch/commons/notifications/model/{FeatureChannelListTests.kt => ChannelListTests.kt} (66%) rename src/test/kotlin/org/opensearch/commons/notifications/model/{FeatureChannelTests.kt => ChannelTests.kt} (65%) diff --git a/src/main/kotlin/org/opensearch/commons/notifications/NotificationConstants.kt b/src/main/kotlin/org/opensearch/commons/notifications/NotificationConstants.kt index 6ebf7889..146c48de 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/NotificationConstants.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/NotificationConstants.kt @@ -52,7 +52,7 @@ object NotificationConstants { const val CREATED_TIME_TAG = "created_time_ms" const val CONFIG_LIST_TAG = "config_list" const val EVENT_LIST_TAG = "event_list" - const val FEATURE_CONFIG_LIST_TAG = "feature_channel_list" + const val CHANNEL_LIST_TAG = "channel_list" const val DELETE_RESPONSE_LIST_TAG = "delete_response_list" const val FROM_INDEX_TAG = "from_index" const val MAX_ITEMS_TAG = "max_items" diff --git a/src/main/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterface.kt b/src/main/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterface.kt index b67ec282..2da0562d 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterface.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterface.kt @@ -14,8 +14,8 @@ import org.opensearch.commons.notifications.action.CreateNotificationConfigReque import org.opensearch.commons.notifications.action.CreateNotificationConfigResponse import org.opensearch.commons.notifications.action.DeleteNotificationConfigRequest import org.opensearch.commons.notifications.action.DeleteNotificationConfigResponse -import org.opensearch.commons.notifications.action.GetFeatureChannelListRequest -import org.opensearch.commons.notifications.action.GetFeatureChannelListResponse +import org.opensearch.commons.notifications.action.GetChannelListRequest +import org.opensearch.commons.notifications.action.GetChannelListResponse import org.opensearch.commons.notifications.action.GetNotificationConfigRequest import org.opensearch.commons.notifications.action.GetNotificationConfigResponse import org.opensearch.commons.notifications.action.GetNotificationEventRequest @@ -26,7 +26,7 @@ import org.opensearch.commons.notifications.action.LegacyPublishNotificationRequ import org.opensearch.commons.notifications.action.LegacyPublishNotificationResponse import org.opensearch.commons.notifications.action.NotificationsActions.CREATE_NOTIFICATION_CONFIG_ACTION_TYPE import org.opensearch.commons.notifications.action.NotificationsActions.DELETE_NOTIFICATION_CONFIG_ACTION_TYPE -import org.opensearch.commons.notifications.action.NotificationsActions.GET_FEATURE_CHANNEL_LIST_ACTION_TYPE +import org.opensearch.commons.notifications.action.NotificationsActions.GET_CHANNEL_LIST_ACTION_TYPE import org.opensearch.commons.notifications.action.NotificationsActions.GET_NOTIFICATION_CONFIG_ACTION_TYPE import org.opensearch.commons.notifications.action.NotificationsActions.GET_NOTIFICATION_EVENT_ACTION_TYPE import org.opensearch.commons.notifications.action.NotificationsActions.GET_PLUGIN_FEATURES_ACTION_TYPE @@ -156,20 +156,20 @@ object NotificationsPluginInterface { } /** - * Get notification channel configuration enabled for a feature. + * Get notification channel configuration. * @param client Node client for making transport action * @param request The request object * @param listener The listener for getting response */ - fun getFeatureChannelList( + fun getChannelList( client: NodeClient, - request: GetFeatureChannelListRequest, - listener: ActionListener + request: GetChannelListRequest, + listener: ActionListener ) { client.execute( - GET_FEATURE_CHANNEL_LIST_ACTION_TYPE, + GET_CHANNEL_LIST_ACTION_TYPE, request, - wrapActionListener(listener) { response -> recreateObject(response) { GetFeatureChannelListResponse(it) } } + wrapActionListener(listener) { response -> recreateObject(response) { GetChannelListResponse(it) } } ) } diff --git a/src/main/kotlin/org/opensearch/commons/notifications/action/GetFeatureChannelListRequest.kt b/src/main/kotlin/org/opensearch/commons/notifications/action/GetChannelListRequest.kt similarity index 88% rename from src/main/kotlin/org/opensearch/commons/notifications/action/GetFeatureChannelListRequest.kt rename to src/main/kotlin/org/opensearch/commons/notifications/action/GetChannelListRequest.kt index 56a0b0fa..96a54eb2 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/action/GetFeatureChannelListRequest.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/action/GetChannelListRequest.kt @@ -21,16 +21,16 @@ import java.io.IOException /** * This request is plugin-only call. i.e. REST interface is not exposed. */ -class GetFeatureChannelListRequest : ActionRequest, ToXContentObject { +class GetChannelListRequest : ActionRequest, ToXContentObject { val compact: Boolean // Dummy request parameter for transport request companion object { - private val log by logger(GetFeatureChannelListRequest::class.java) + private val log by logger(GetChannelListRequest::class.java) /** * reader to create instance of class from writable. */ - val reader = Writeable.Reader { GetFeatureChannelListRequest(it) } + val reader = Writeable.Reader { GetChannelListRequest(it) } /** * Creator used in REST communication. @@ -38,7 +38,7 @@ class GetFeatureChannelListRequest : ActionRequest, ToXContentObject { */ @JvmStatic @Throws(IOException::class) - fun parse(parser: XContentParser): GetFeatureChannelListRequest { + fun parse(parser: XContentParser): GetChannelListRequest { var compact = false XContentParserUtils.ensureExpectedToken( @@ -53,11 +53,11 @@ class GetFeatureChannelListRequest : ActionRequest, ToXContentObject { COMPACT_TAG -> compact = parser.booleanValue() else -> { parser.skipChildren() - log.info("Unexpected field: $fieldName, while parsing GetFeatureChannelListRequest") + log.info("Unexpected field: $fieldName, while parsing GetChannelListRequest") } } } - return GetFeatureChannelListRequest() + return GetChannelListRequest() } } diff --git a/src/main/kotlin/org/opensearch/commons/notifications/action/GetFeatureChannelListResponse.kt b/src/main/kotlin/org/opensearch/commons/notifications/action/GetChannelListResponse.kt similarity index 75% rename from src/main/kotlin/org/opensearch/commons/notifications/action/GetFeatureChannelListResponse.kt rename to src/main/kotlin/org/opensearch/commons/notifications/action/GetChannelListResponse.kt index 79bf4435..89623ed0 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/action/GetFeatureChannelListResponse.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/action/GetChannelListResponse.kt @@ -10,21 +10,21 @@ import org.opensearch.common.io.stream.Writeable import org.opensearch.common.xcontent.ToXContent import org.opensearch.common.xcontent.XContentBuilder import org.opensearch.common.xcontent.XContentParser -import org.opensearch.commons.notifications.model.FeatureChannelList +import org.opensearch.commons.notifications.model.ChannelList import java.io.IOException /** * Action Response for creating new configuration. */ -class GetFeatureChannelListResponse : BaseResponse { - val searchResult: FeatureChannelList +class GetChannelListResponse : BaseResponse { + val searchResult: ChannelList companion object { /** * reader to create instance of class from writable. */ - val reader = Writeable.Reader { GetFeatureChannelListResponse(it) } + val reader = Writeable.Reader { GetChannelListResponse(it) } /** * Creator used in REST communication. @@ -32,8 +32,8 @@ class GetFeatureChannelListResponse : BaseResponse { */ @JvmStatic @Throws(IOException::class) - fun parse(parser: XContentParser): GetFeatureChannelListResponse { - return GetFeatureChannelListResponse(FeatureChannelList(parser)) + fun parse(parser: XContentParser): GetChannelListResponse { + return GetChannelListResponse(ChannelList(parser)) } } @@ -41,7 +41,7 @@ class GetFeatureChannelListResponse : BaseResponse { * constructor for creating the class * @param searchResult the notification configuration list */ - constructor(searchResult: FeatureChannelList) { + constructor(searchResult: ChannelList) { this.searchResult = searchResult } @@ -50,7 +50,7 @@ class GetFeatureChannelListResponse : BaseResponse { */ @Throws(IOException::class) constructor(input: StreamInput) : super(input) { - searchResult = FeatureChannelList(input) + searchResult = ChannelList(input) } /** diff --git a/src/main/kotlin/org/opensearch/commons/notifications/action/NotificationsActions.kt b/src/main/kotlin/org/opensearch/commons/notifications/action/NotificationsActions.kt index ca8dd2d7..204d9326 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/action/NotificationsActions.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/action/NotificationsActions.kt @@ -43,7 +43,7 @@ object NotificationsActions { /** * Get Config List for feature. Internal only - Inter plugin communication. */ - const val GET_FEATURE_CHANNEL_LIST_NAME = "cluster:admin/opensearch/notifications/feature/channels/get" + const val GET_CHANNEL_LIST_NAME = "cluster:admin/opensearch/notifications/channels/get" /** * Send notification message. Internal only - Inter plugin communication. @@ -93,10 +93,10 @@ object NotificationsActions { ActionType(GET_PLUGIN_FEATURES_NAME, ::GetPluginFeaturesResponse) /** - * Get Config List for feature transport action type. + * Get notification channel List transport action type. */ - val GET_FEATURE_CHANNEL_LIST_ACTION_TYPE = - ActionType(GET_FEATURE_CHANNEL_LIST_NAME, ::GetFeatureChannelListResponse) + val GET_CHANNEL_LIST_ACTION_TYPE = + ActionType(GET_CHANNEL_LIST_NAME, ::GetChannelListResponse) /** * Send notification transport action type. Internal only - Inter plugin communication. diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/FeatureChannel.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/Channel.kt similarity index 92% rename from src/main/kotlin/org/opensearch/commons/notifications/model/FeatureChannel.kt rename to src/main/kotlin/org/opensearch/commons/notifications/model/Channel.kt index c0e74c56..a235d974 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/FeatureChannel.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/Channel.kt @@ -21,9 +21,9 @@ import org.opensearch.commons.utils.logger import java.io.IOException /** - * Data class representing Notification config for exposed for other plugins. + * Data class representing Notification config exposed for other plugins. */ -data class FeatureChannel( +data class Channel( val configId: String, val name: String, val description: String, @@ -37,12 +37,12 @@ data class FeatureChannel( } companion object { - private val log by logger(FeatureChannel::class.java) + private val log by logger(Channel::class.java) /** * reader to create instance of class from writable. */ - val reader = Writeable.Reader { FeatureChannel(it) } + val reader = Writeable.Reader { Channel(it) } /** * Creator used in REST communication. @@ -51,7 +51,7 @@ data class FeatureChannel( @Suppress("ComplexMethod") @JvmStatic @Throws(IOException::class) - fun parse(parser: XContentParser): FeatureChannel { + fun parse(parser: XContentParser): Channel { var configId: String? = null var name: String? = null var description = "" @@ -74,14 +74,14 @@ data class FeatureChannel( IS_ENABLED_TAG -> isEnabled = parser.booleanValue() else -> { parser.skipChildren() - log.info("Unexpected field: $fieldName, while parsing FeatureChannel") + log.info("Unexpected field: $fieldName, while parsing Channel") } } } configId ?: throw IllegalArgumentException("$CONFIG_ID_TAG field absent") name ?: throw IllegalArgumentException("$NAME_TAG field absent") configType ?: throw IllegalArgumentException("$CONFIG_TYPE_TAG field absent") - return FeatureChannel( + return Channel( configId, name, description, diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/FeatureChannelList.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/ChannelList.kt similarity index 62% rename from src/main/kotlin/org/opensearch/commons/notifications/model/FeatureChannelList.kt rename to src/main/kotlin/org/opensearch/commons/notifications/model/ChannelList.kt index d5df20a1..7cb25c3a 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/FeatureChannelList.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/ChannelList.kt @@ -9,22 +9,22 @@ import org.apache.lucene.search.TotalHits import org.opensearch.action.search.SearchResponse import org.opensearch.common.io.stream.StreamInput import org.opensearch.common.xcontent.XContentParser -import org.opensearch.commons.notifications.NotificationConstants.FEATURE_CONFIG_LIST_TAG +import org.opensearch.commons.notifications.NotificationConstants.CHANNEL_LIST_TAG /** - * FeatureChannel search results + * Channel search results */ -class FeatureChannelList : SearchResults { +class ChannelList : SearchResults { /** * single item result constructor */ - constructor(objectItem: FeatureChannel) : super(FEATURE_CONFIG_LIST_TAG, objectItem) + constructor(objectItem: Channel) : super(CHANNEL_LIST_TAG, objectItem) /** * multiple items result constructor */ - constructor(objectList: List) : this( + constructor(objectList: List) : this( 0, objectList.size.toLong(), TotalHits.Relation.EQUAL_TO, @@ -38,34 +38,34 @@ class FeatureChannelList : SearchResults { startIndex: Long, totalHits: Long, totalHitRelation: TotalHits.Relation, - objectList: List - ) : super(startIndex, totalHits, totalHitRelation, FEATURE_CONFIG_LIST_TAG, objectList) + objectList: List + ) : super(startIndex, totalHits, totalHitRelation, CHANNEL_LIST_TAG, objectList) /** * Constructor used in transport action communication. * @param input StreamInput stream to deserialize data from. */ - constructor(input: StreamInput) : super(input, FeatureChannel.reader) + constructor(input: StreamInput) : super(input, Channel.reader) /** * Construct object from XContentParser */ - constructor(parser: XContentParser) : super(parser, FEATURE_CONFIG_LIST_TAG) + constructor(parser: XContentParser) : super(parser, CHANNEL_LIST_TAG) /** * Construct object from SearchResponse */ - constructor(from: Long, response: SearchResponse, searchHitParser: SearchHitParser) : super( + constructor(from: Long, response: SearchResponse, searchHitParser: SearchHitParser) : super( from, response, searchHitParser, - FEATURE_CONFIG_LIST_TAG + CHANNEL_LIST_TAG ) /** * {@inheritDoc} */ - override fun parseItem(parser: XContentParser): FeatureChannel { - return FeatureChannel.parse(parser) + override fun parseItem(parser: XContentParser): Channel { + return Channel.parse(parser) } } diff --git a/src/test/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterfaceTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterfaceTests.kt index f6d3f9c1..c71836eb 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterfaceTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterfaceTests.kt @@ -25,8 +25,8 @@ import org.opensearch.commons.notifications.action.CreateNotificationConfigReque import org.opensearch.commons.notifications.action.CreateNotificationConfigResponse import org.opensearch.commons.notifications.action.DeleteNotificationConfigRequest import org.opensearch.commons.notifications.action.DeleteNotificationConfigResponse -import org.opensearch.commons.notifications.action.GetFeatureChannelListRequest -import org.opensearch.commons.notifications.action.GetFeatureChannelListResponse +import org.opensearch.commons.notifications.action.GetChannelListRequest +import org.opensearch.commons.notifications.action.GetChannelListResponse import org.opensearch.commons.notifications.action.GetNotificationConfigRequest import org.opensearch.commons.notifications.action.GetNotificationConfigResponse import org.opensearch.commons.notifications.action.GetNotificationEventRequest @@ -38,13 +38,13 @@ import org.opensearch.commons.notifications.action.LegacyPublishNotificationResp import org.opensearch.commons.notifications.action.SendNotificationResponse import org.opensearch.commons.notifications.action.UpdateNotificationConfigRequest import org.opensearch.commons.notifications.action.UpdateNotificationConfigResponse +import org.opensearch.commons.notifications.model.Channel +import org.opensearch.commons.notifications.model.ChannelList import org.opensearch.commons.notifications.model.ChannelMessage import org.opensearch.commons.notifications.model.ConfigType import org.opensearch.commons.notifications.model.DeliveryStatus import org.opensearch.commons.notifications.model.EventSource import org.opensearch.commons.notifications.model.EventStatus -import org.opensearch.commons.notifications.model.FeatureChannel -import org.opensearch.commons.notifications.model.FeatureChannelList import org.opensearch.commons.notifications.model.NotificationConfig import org.opensearch.commons.notifications.model.NotificationConfigInfo import org.opensearch.commons.notifications.model.NotificationConfigSearchResult @@ -168,25 +168,25 @@ internal class NotificationsPluginInterfaceTests { } @Test - fun getFeatureChannelList() { - val sampleConfig = FeatureChannel( + fun getChannelList() { + val sampleConfig = Channel( "config_id", "name", "description", ConfigType.SLACK ) - val request = mock(GetFeatureChannelListRequest::class.java) - val response = GetFeatureChannelListResponse(FeatureChannelList(sampleConfig)) - val listener: ActionListener = - mock(ActionListener::class.java) as ActionListener + val request = mock(GetChannelListRequest::class.java) + val response = GetChannelListResponse(ChannelList(sampleConfig)) + val listener: ActionListener = + mock(ActionListener::class.java) as ActionListener doAnswer { - (it.getArgument(2) as ActionListener) + (it.getArgument(2) as ActionListener) .onResponse(response) }.whenever(client).execute(any(ActionType::class.java), any(), any()) - NotificationsPluginInterface.getFeatureChannelList(client, request, listener) + NotificationsPluginInterface.getChannelList(client, request, listener) verify(listener, times(1)).onResponse(eq(response)) } diff --git a/src/test/kotlin/org/opensearch/commons/notifications/action/GetFeatureChannelListRequestTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/action/GetChannelListRequestTests.kt similarity index 76% rename from src/test/kotlin/org/opensearch/commons/notifications/action/GetFeatureChannelListRequestTests.kt rename to src/test/kotlin/org/opensearch/commons/notifications/action/GetChannelListRequestTests.kt index b9913ae2..aaa29e21 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/action/GetFeatureChannelListRequestTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/action/GetChannelListRequestTests.kt @@ -12,27 +12,27 @@ import org.opensearch.commons.utils.createObjectFromJsonString import org.opensearch.commons.utils.getJsonString import org.opensearch.commons.utils.recreateObject -internal class GetFeatureChannelListRequestTests { +internal class GetChannelListRequestTests { private fun assertGetRequestEquals( - expected: GetFeatureChannelListRequest, - actual: GetFeatureChannelListRequest + expected: GetChannelListRequest, + actual: GetChannelListRequest ) { assertEquals(expected.compact, actual.compact) } @Test fun `Get request serialize and deserialize transport object should be equal`() { - val configRequest = GetFeatureChannelListRequest() - val recreatedObject = recreateObject(configRequest) { GetFeatureChannelListRequest(it) } + val configRequest = GetChannelListRequest() + val recreatedObject = recreateObject(configRequest) { GetChannelListRequest(it) } assertGetRequestEquals(configRequest, recreatedObject) } @Test fun `Get request serialize and deserialize using json object should be equal`() { - val configRequest = GetFeatureChannelListRequest() + val configRequest = GetChannelListRequest() val jsonString = getJsonString(configRequest) - val recreatedObject = createObjectFromJsonString(jsonString) { GetFeatureChannelListRequest.parse(it) } + val recreatedObject = createObjectFromJsonString(jsonString) { GetChannelListRequest.parse(it) } assertGetRequestEquals(configRequest, recreatedObject) } @@ -40,13 +40,13 @@ internal class GetFeatureChannelListRequestTests { fun `Get request should throw exception when invalid json object is passed`() { val jsonString = "sample message" assertThrows { - createObjectFromJsonString(jsonString) { GetFeatureChannelListRequest.parse(it) } + createObjectFromJsonString(jsonString) { GetChannelListRequest.parse(it) } } } @Test fun `Get request should safely ignore extra field in json object`() { - val configRequest = GetFeatureChannelListRequest() + val configRequest = GetChannelListRequest() val jsonString = """ { "extra_field_1":["extra", "value"], @@ -54,7 +54,7 @@ internal class GetFeatureChannelListRequestTests { "extra_field_3":"extra value 3" } """.trimIndent() - val recreatedObject = createObjectFromJsonString(jsonString) { GetFeatureChannelListRequest.parse(it) } + val recreatedObject = createObjectFromJsonString(jsonString) { GetChannelListRequest.parse(it) } assertGetRequestEquals(configRequest, recreatedObject) } } diff --git a/src/test/kotlin/org/opensearch/commons/notifications/action/GetFeatureChannelListResponseTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/action/GetChannelListResponseTests.kt similarity index 73% rename from src/test/kotlin/org/opensearch/commons/notifications/action/GetFeatureChannelListResponseTests.kt rename to src/test/kotlin/org/opensearch/commons/notifications/action/GetChannelListResponseTests.kt index 805f651e..eb4023dd 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/action/GetFeatureChannelListResponseTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/action/GetChannelListResponseTests.kt @@ -8,18 +8,18 @@ import org.apache.lucene.search.TotalHits import org.junit.jupiter.api.Assertions import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Test +import org.opensearch.commons.notifications.model.Channel +import org.opensearch.commons.notifications.model.ChannelList import org.opensearch.commons.notifications.model.ConfigType -import org.opensearch.commons.notifications.model.FeatureChannel -import org.opensearch.commons.notifications.model.FeatureChannelList import org.opensearch.commons.utils.createObjectFromJsonString import org.opensearch.commons.utils.getJsonString import org.opensearch.commons.utils.recreateObject -internal class GetFeatureChannelListResponseTests { +internal class GetChannelListResponseTests { private fun assertSearchResultEquals( - expected: FeatureChannelList, - actual: FeatureChannelList + expected: ChannelList, + actual: ChannelList ) { assertEquals(expected.startIndex, actual.startIndex) assertEquals(expected.totalHits, actual.totalHits) @@ -30,112 +30,112 @@ internal class GetFeatureChannelListResponseTests { @Test fun `Get Response serialize and deserialize with config object should be equal`() { - val sampleConfig = FeatureChannel( + val sampleConfig = Channel( "config_id", "name", "description", ConfigType.SLACK ) - val searchResult = FeatureChannelList(sampleConfig) - val getResponse = GetFeatureChannelListResponse(searchResult) - val recreatedObject = recreateObject(getResponse) { GetFeatureChannelListResponse(it) } + val searchResult = ChannelList(sampleConfig) + val getResponse = GetChannelListResponse(searchResult) + val recreatedObject = recreateObject(getResponse) { GetChannelListResponse(it) } assertSearchResultEquals(searchResult, recreatedObject.searchResult) } @Test fun `Get Response serialize and deserialize with multiple config object should be equal`() { - val sampleConfig1 = FeatureChannel( + val sampleConfig1 = Channel( "config_id1", "name1", "description1", ConfigType.SLACK ) - val sampleConfig2 = FeatureChannel( + val sampleConfig2 = Channel( "config_id2", "name2", "description2", ConfigType.CHIME ) - val sampleConfig3 = FeatureChannel( + val sampleConfig3 = Channel( "config_id3", "name3", "description3", ConfigType.WEBHOOK ) - val searchResult = FeatureChannelList( + val searchResult = ChannelList( 100, 1000, TotalHits.Relation.GREATER_THAN_OR_EQUAL_TO, listOf(sampleConfig1, sampleConfig2, sampleConfig3) ) - val getResponse = GetFeatureChannelListResponse(searchResult) - val recreatedObject = recreateObject(getResponse) { GetFeatureChannelListResponse(it) } + val getResponse = GetChannelListResponse(searchResult) + val recreatedObject = recreateObject(getResponse) { GetChannelListResponse(it) } assertSearchResultEquals(searchResult, recreatedObject.searchResult) } @Test fun `Get Response serialize and deserialize using json config object should be equal`() { - val sampleConfig = FeatureChannel( + val sampleConfig = Channel( "config_id", "name", "description", ConfigType.EMAIL_GROUP ) - val searchResult = FeatureChannelList(sampleConfig) - val getResponse = GetFeatureChannelListResponse(searchResult) + val searchResult = ChannelList(sampleConfig) + val getResponse = GetChannelListResponse(searchResult) val jsonString = getJsonString(getResponse) - val recreatedObject = createObjectFromJsonString(jsonString) { GetFeatureChannelListResponse.parse(it) } + val recreatedObject = createObjectFromJsonString(jsonString) { GetChannelListResponse.parse(it) } assertSearchResultEquals(searchResult, recreatedObject.searchResult) } @Test fun `Get Response serialize and deserialize using json with multiple config object should be equal`() { - val sampleConfig1 = FeatureChannel( + val sampleConfig1 = Channel( "config_id1", "name1", "description1", ConfigType.SLACK ) - val sampleConfig2 = FeatureChannel( + val sampleConfig2 = Channel( "config_id2", "name2", "description2", ConfigType.CHIME ) - val sampleConfig3 = FeatureChannel( + val sampleConfig3 = Channel( "config_id3", "name3", "description3", ConfigType.WEBHOOK ) - val searchResult = FeatureChannelList( + val searchResult = ChannelList( 100, 1000, TotalHits.Relation.GREATER_THAN_OR_EQUAL_TO, listOf(sampleConfig1, sampleConfig2, sampleConfig3) ) - val getResponse = GetFeatureChannelListResponse(searchResult) + val getResponse = GetChannelListResponse(searchResult) val jsonString = getJsonString(getResponse) - val recreatedObject = createObjectFromJsonString(jsonString) { GetFeatureChannelListResponse.parse(it) } + val recreatedObject = createObjectFromJsonString(jsonString) { GetChannelListResponse.parse(it) } assertSearchResultEquals(searchResult, recreatedObject.searchResult) } @Test fun `Get Response should use isEnabled=true if absent in json object`() { - val sampleConfig = FeatureChannel( + val sampleConfig = Channel( "config_id", "name", "description", ConfigType.EMAIL, true ) - val searchResult = FeatureChannelList(sampleConfig) + val searchResult = ChannelList(sampleConfig) val jsonString = """ { "start_index":"0", "total_hits":"1", "total_hit_relation":"eq", - "feature_channel_list":[ + "channel_list":[ { "config_id":"config_id", "name":"name", @@ -145,25 +145,25 @@ internal class GetFeatureChannelListResponseTests { ] } """.trimIndent() - val recreatedObject = createObjectFromJsonString(jsonString) { GetFeatureChannelListResponse.parse(it) } + val recreatedObject = createObjectFromJsonString(jsonString) { GetChannelListResponse.parse(it) } assertSearchResultEquals(searchResult, recreatedObject.searchResult) } @Test fun `Get Response should safely ignore extra field in json object`() { - val sampleConfig = FeatureChannel( + val sampleConfig = Channel( "config_id", "name", "description", ConfigType.EMAIL ) - val searchResult = FeatureChannelList(sampleConfig) + val searchResult = ChannelList(sampleConfig) val jsonString = """ { "start_index":"0", "total_hits":"1", "total_hit_relation":"eq", - "feature_channel_list":[ + "channel_list":[ { "config_id":"config_id", "name":"name", @@ -177,22 +177,22 @@ internal class GetFeatureChannelListResponseTests { "extra_field_3":"extra value 3" } """.trimIndent() - val recreatedObject = createObjectFromJsonString(jsonString) { GetFeatureChannelListResponse.parse(it) } + val recreatedObject = createObjectFromJsonString(jsonString) { GetChannelListResponse.parse(it) } assertSearchResultEquals(searchResult, recreatedObject.searchResult) } @Test fun `Get Response should safely fallback to default if startIndex, totalHits or totalHitRelation field absent in json object`() { - val sampleConfig = FeatureChannel( + val sampleConfig = Channel( "config_id", "name", "description", ConfigType.EMAIL ) - val searchResult = FeatureChannelList(sampleConfig) + val searchResult = ChannelList(sampleConfig) val jsonString = """ { - "feature_channel_list":[ + "channel_list":[ { "config_id":"config_id", "name":"name", @@ -203,12 +203,12 @@ internal class GetFeatureChannelListResponseTests { ] } """.trimIndent() - val recreatedObject = createObjectFromJsonString(jsonString) { GetFeatureChannelListResponse.parse(it) } + val recreatedObject = createObjectFromJsonString(jsonString) { GetChannelListResponse.parse(it) } assertSearchResultEquals(searchResult, recreatedObject.searchResult) } @Test - fun `Get Response should throw exception if featureChannelList is absent in json`() { + fun `Get Response should throw exception if channelList is absent in json`() { val jsonString = """ { "start_index":"0", @@ -217,7 +217,7 @@ internal class GetFeatureChannelListResponseTests { } """.trimIndent() Assertions.assertThrows(IllegalArgumentException::class.java) { - createObjectFromJsonString(jsonString) { GetFeatureChannelListResponse.parse(it) } + createObjectFromJsonString(jsonString) { GetChannelListResponse.parse(it) } } } } diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/FeatureChannelListTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/ChannelListTests.kt similarity index 66% rename from src/test/kotlin/org/opensearch/commons/notifications/model/FeatureChannelListTests.kt rename to src/test/kotlin/org/opensearch/commons/notifications/model/ChannelListTests.kt index 8a40aadd..06387d37 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/FeatureChannelListTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/ChannelListTests.kt @@ -12,11 +12,11 @@ import org.opensearch.commons.utils.createObjectFromJsonString import org.opensearch.commons.utils.getJsonString import org.opensearch.commons.utils.recreateObject -internal class FeatureChannelListTests { +internal class ChannelListTests { private fun assertSearchResultEquals( - expected: FeatureChannelList, - actual: FeatureChannelList + expected: ChannelList, + actual: ChannelList ) { assertEquals(expected.startIndex, actual.startIndex) assertEquals(expected.totalHits, actual.totalHits) @@ -27,129 +27,129 @@ internal class FeatureChannelListTests { @Test fun `Feature Channel List serialize and deserialize using transport should be equal`() { - val featureChannel = FeatureChannel( + val channel = Channel( "configId", "name", "description", ConfigType.SLACK, true ) - val featureChannelList = FeatureChannelList(featureChannel) - val recreatedObject = recreateObject(featureChannelList) { FeatureChannelList(it) } - assertSearchResultEquals(featureChannelList, recreatedObject) + val channelList = ChannelList(channel) + val recreatedObject = recreateObject(channelList) { ChannelList(it) } + assertSearchResultEquals(channelList, recreatedObject) } @Test fun `Feature Channel List serialize and deserialize multiple object with default values should be equal`() { - val featureChannel1 = FeatureChannel( + val channel1 = Channel( "configId1", "name1", "description1", ConfigType.SLACK, true ) - val featureChannel2 = FeatureChannel( + val channel2 = Channel( "configId2", "name2", "description2", ConfigType.CHIME, true ) - val featureChannelList = FeatureChannelList(listOf(featureChannel1, featureChannel2)) - val expectedResult = FeatureChannelList( + val channelList = ChannelList(listOf(channel1, channel2)) + val expectedResult = ChannelList( 0, 2, TotalHits.Relation.EQUAL_TO, - listOf(featureChannel1, featureChannel2) + listOf(channel1, channel2) ) - val recreatedObject = recreateObject(featureChannelList) { FeatureChannelList(it) } + val recreatedObject = recreateObject(channelList) { ChannelList(it) } assertSearchResultEquals(expectedResult, recreatedObject) } @Test fun `Feature Channel List serialize and deserialize with multiple object should be equal`() { - val featureChannel1 = FeatureChannel( + val channel1 = Channel( "configId1", "name1", "description1", ConfigType.SLACK, true ) - val featureChannel2 = FeatureChannel( + val channel2 = Channel( "configId2", "name2", "description2", ConfigType.CHIME, true ) - val featureChannelList = FeatureChannelList( + val channelList = ChannelList( 100, 1000, TotalHits.Relation.GREATER_THAN_OR_EQUAL_TO, - listOf(featureChannel1, featureChannel2) + listOf(channel1, channel2) ) - val recreatedObject = recreateObject(featureChannelList) { FeatureChannelList(it) } - assertSearchResultEquals(featureChannelList, recreatedObject) + val recreatedObject = recreateObject(channelList) { ChannelList(it) } + assertSearchResultEquals(channelList, recreatedObject) } @Test fun `Feature Channel List serialize and deserialize using json should be equal`() { - val featureChannel = FeatureChannel( + val channel = Channel( "configId", "name", "description", ConfigType.SLACK, true ) - val featureChannelList = FeatureChannelList(featureChannel) - val jsonString = getJsonString(featureChannelList) - val recreatedObject = createObjectFromJsonString(jsonString) { FeatureChannelList(it) } - assertSearchResultEquals(featureChannelList, recreatedObject) + val channelList = ChannelList(channel) + val jsonString = getJsonString(channelList) + val recreatedObject = createObjectFromJsonString(jsonString) { ChannelList(it) } + assertSearchResultEquals(channelList, recreatedObject) } @Test fun `Feature Channel List serialize and deserialize using json with multiple object should be equal`() { - val featureChannel1 = FeatureChannel( + val channel1 = Channel( "configId1", "name1", "description1", ConfigType.SLACK, true ) - val featureChannel2 = FeatureChannel( + val channel2 = Channel( "configId2", "name2", "description2", ConfigType.CHIME, true ) - val featureChannelList = FeatureChannelList( + val channelList = ChannelList( 100, 1000, TotalHits.Relation.GREATER_THAN_OR_EQUAL_TO, - listOf(featureChannel1, featureChannel2) + listOf(channel1, channel2) ) - val jsonString = getJsonString(featureChannelList) - val recreatedObject = createObjectFromJsonString(jsonString) { FeatureChannelList(it) } - assertSearchResultEquals(featureChannelList, recreatedObject) + val jsonString = getJsonString(channelList) + val recreatedObject = createObjectFromJsonString(jsonString) { ChannelList(it) } + assertSearchResultEquals(channelList, recreatedObject) } @Test fun `Feature Channel List should safely ignore extra field in json object`() { - val featureChannel = FeatureChannel( + val channel = Channel( "configId", "name", "description", ConfigType.SLACK, true ) - val featureChannelList = FeatureChannelList(featureChannel) + val channelList = ChannelList(channel) val jsonString = """ { "start_index":"0", "total_hits":"1", "total_hit_relation":"eq", - "feature_channel_list":[ + "channel_list":[ { "config_id":"configId", "name":"name", @@ -163,23 +163,23 @@ internal class FeatureChannelListTests { "extra_field_3":"extra value 3" } """.trimIndent() - val recreatedObject = createObjectFromJsonString(jsonString) { FeatureChannelList(it) } - assertSearchResultEquals(featureChannelList, recreatedObject) + val recreatedObject = createObjectFromJsonString(jsonString) { ChannelList(it) } + assertSearchResultEquals(channelList, recreatedObject) } @Test fun `Feature Channel List should safely fallback to default if startIndex, totalHits or totalHitRelation field absent in json object`() { - val featureChannel = FeatureChannel( + val channel = Channel( "configId", "name", "description", ConfigType.SLACK, true ) - val featureChannelList = FeatureChannelList(featureChannel) + val channelList = ChannelList(channel) val jsonString = """ { - "feature_channel_list":[ + "channel_list":[ { "config_id":"configId", "name":"name", @@ -190,12 +190,12 @@ internal class FeatureChannelListTests { ] } """.trimIndent() - val recreatedObject = createObjectFromJsonString(jsonString) { FeatureChannelList(it) } - assertSearchResultEquals(featureChannelList, recreatedObject) + val recreatedObject = createObjectFromJsonString(jsonString) { ChannelList(it) } + assertSearchResultEquals(channelList, recreatedObject) } @Test - fun `Feature Channel List should throw exception if feature_channel_list is absent in json`() { + fun `Channel List should throw exception if channel_list is absent in json`() { val jsonString = """ { "start_index":"0", @@ -204,7 +204,7 @@ internal class FeatureChannelListTests { } """.trimIndent() Assertions.assertThrows(IllegalArgumentException::class.java) { - createObjectFromJsonString(jsonString) { FeatureChannelList(it) } + createObjectFromJsonString(jsonString) { ChannelList(it) } } } } diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/FeatureChannelTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/ChannelTests.kt similarity index 65% rename from src/test/kotlin/org/opensearch/commons/notifications/model/FeatureChannelTests.kt rename to src/test/kotlin/org/opensearch/commons/notifications/model/ChannelTests.kt index 3fa2e4ab..3f64cc5a 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/FeatureChannelTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/ChannelTests.kt @@ -11,38 +11,38 @@ import org.opensearch.commons.utils.createObjectFromJsonString import org.opensearch.commons.utils.getJsonString import org.opensearch.commons.utils.recreateObject -internal class FeatureChannelTests { +internal class ChannelTests { @Test - fun `FeatureChannel Object serialize and deserialize using transport should be equal`() { - val featureChannel = FeatureChannel( + fun `Channel Object serialize and deserialize using transport should be equal`() { + val channel = Channel( "configId", "name", "description", ConfigType.SLACK, true ) - val recreatedObject = recreateObject(featureChannel) { FeatureChannel(it) } - assertEquals(featureChannel, recreatedObject) + val recreatedObject = recreateObject(channel) { Channel(it) } + assertEquals(channel, recreatedObject) } @Test - fun `FeatureChannel Object serialize and deserialize using json should be equal`() { - val featureChannel = FeatureChannel( + fun `Channel Object serialize and deserialize using json should be equal`() { + val channel = Channel( "configId", "name", "description", ConfigType.CHIME, false ) - val jsonString = getJsonString(featureChannel) - val recreatedObject = createObjectFromJsonString(jsonString) { FeatureChannel.parse(it) } - assertEquals(featureChannel, recreatedObject) + val jsonString = getJsonString(channel) + val recreatedObject = createObjectFromJsonString(jsonString) { Channel.parse(it) } + assertEquals(channel, recreatedObject) } @Test - fun `FeatureChannel Json parsing should safely ignore extra fields`() { - val featureChannel = FeatureChannel( + fun `Channel Json parsing should safely ignore extra fields`() { + val channel = Channel( "configId", "name", "description", @@ -61,13 +61,13 @@ internal class FeatureChannelTests { "extra_field_3":"extra value 3" } """.trimIndent() - val recreatedObject = createObjectFromJsonString(jsonString) { FeatureChannel.parse(it) } - assertEquals(featureChannel, recreatedObject) + val recreatedObject = createObjectFromJsonString(jsonString) { Channel.parse(it) } + assertEquals(channel, recreatedObject) } @Test - fun `FeatureChannel Json parsing should safely ignore unknown config type`() { - val featureChannel = FeatureChannel( + fun `Channel Json parsing should safely ignore unknown config type`() { + val channel = Channel( "configId", "name", "description", @@ -83,13 +83,13 @@ internal class FeatureChannelTests { "is_enabled":true } """.trimIndent() - val recreatedObject = createObjectFromJsonString(jsonString) { FeatureChannel.parse(it) } - assertEquals(featureChannel, recreatedObject) + val recreatedObject = createObjectFromJsonString(jsonString) { Channel.parse(it) } + assertEquals(channel, recreatedObject) } @Test - fun `FeatureChannel Json parsing should safely parse if description is absent`() { - val featureChannel = FeatureChannel( + fun `Channel Json parsing should safely parse if description is absent`() { + val channel = Channel( "configId", "name", "", @@ -104,13 +104,13 @@ internal class FeatureChannelTests { "is_enabled":true } """.trimIndent() - val recreatedObject = createObjectFromJsonString(jsonString) { FeatureChannel.parse(it) } - assertEquals(featureChannel, recreatedObject) + val recreatedObject = createObjectFromJsonString(jsonString) { Channel.parse(it) } + assertEquals(channel, recreatedObject) } @Test - fun `FeatureChannel Json parsing should safely parse if is_enabled is absent`() { - val featureChannel = FeatureChannel( + fun `Channel Json parsing should safely parse if is_enabled is absent`() { + val channel = Channel( "configId", "name", "description", @@ -125,12 +125,12 @@ internal class FeatureChannelTests { "config_type":"slack" } """.trimIndent() - val recreatedObject = createObjectFromJsonString(jsonString) { FeatureChannel.parse(it) } - assertEquals(featureChannel, recreatedObject) + val recreatedObject = createObjectFromJsonString(jsonString) { Channel.parse(it) } + assertEquals(channel, recreatedObject) } @Test - fun `FeatureChannel Json parsing should throw exception if config_id is absent`() { + fun `Channel Json parsing should throw exception if config_id is absent`() { val jsonString = """ { "name":"name", @@ -140,12 +140,12 @@ internal class FeatureChannelTests { } """.trimIndent() Assertions.assertThrows(IllegalArgumentException::class.java) { - createObjectFromJsonString(jsonString) { FeatureChannel.parse(it) } + createObjectFromJsonString(jsonString) { Channel.parse(it) } } } @Test - fun `FeatureChannel Json parsing should throw exception if config_id is empty`() { + fun `Channel Json parsing should throw exception if config_id is empty`() { val jsonString = """ { "config_id":"", @@ -156,12 +156,12 @@ internal class FeatureChannelTests { } """.trimIndent() Assertions.assertThrows(IllegalArgumentException::class.java) { - createObjectFromJsonString(jsonString) { FeatureChannel.parse(it) } + createObjectFromJsonString(jsonString) { Channel.parse(it) } } } @Test - fun `FeatureChannel Json parsing should throw exception if name is absent`() { + fun `Channel Json parsing should throw exception if name is absent`() { val jsonString = """ { "config_id":"configId", @@ -171,12 +171,12 @@ internal class FeatureChannelTests { } """.trimIndent() Assertions.assertThrows(IllegalArgumentException::class.java) { - createObjectFromJsonString(jsonString) { FeatureChannel.parse(it) } + createObjectFromJsonString(jsonString) { Channel.parse(it) } } } @Test - fun `FeatureChannel Json parsing should throw exception if name is empty`() { + fun `Channel Json parsing should throw exception if name is empty`() { val jsonString = """ { "config_id":"configId", @@ -187,12 +187,12 @@ internal class FeatureChannelTests { } """.trimIndent() Assertions.assertThrows(IllegalArgumentException::class.java) { - createObjectFromJsonString(jsonString) { FeatureChannel.parse(it) } + createObjectFromJsonString(jsonString) { Channel.parse(it) } } } @Test - fun `FeatureChannel Json parsing should throw exception if config_type is absent`() { + fun `Channel Json parsing should throw exception if config_type is absent`() { val jsonString = """ { "config_id":"configId", @@ -202,7 +202,7 @@ internal class FeatureChannelTests { } """.trimIndent() Assertions.assertThrows(IllegalArgumentException::class.java) { - createObjectFromJsonString(jsonString) { FeatureChannel.parse(it) } + createObjectFromJsonString(jsonString) { Channel.parse(it) } } } } diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/FilterConfigListTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/FilterConfigListTests.kt index 9ac569f6..de648bcd 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/FilterConfigListTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/FilterConfigListTests.kt @@ -15,8 +15,8 @@ import org.opensearch.commons.utils.recreateObject internal class FilterConfigListTests { private fun assertSearchResultEquals( - expected: FeatureChannelList, - actual: FeatureChannelList + expected: ChannelList, + actual: ChannelList ) { assertEquals(expected.startIndex, actual.startIndex) assertEquals(expected.totalHits, actual.totalHits) @@ -27,108 +27,108 @@ internal class FilterConfigListTests { @Test fun `Search result serialize and deserialize with config object should be equal`() { - val sampleConfig = FeatureChannel( + val sampleConfig = Channel( "config_id", "name", "description", ConfigType.SLACK ) - val searchResult = FeatureChannelList(sampleConfig) - val recreatedObject = recreateObject(searchResult) { FeatureChannelList(it) } + val searchResult = ChannelList(sampleConfig) + val recreatedObject = recreateObject(searchResult) { ChannelList(it) } assertSearchResultEquals(searchResult, recreatedObject) } @Test fun `Search result serialize and deserialize with multiple config object should be equal`() { - val sampleConfig1 = FeatureChannel( + val sampleConfig1 = Channel( "config_id1", "name1", "description1", ConfigType.SLACK ) - val sampleConfig2 = FeatureChannel( + val sampleConfig2 = Channel( "config_id2", "name2", "description2", ConfigType.CHIME ) - val sampleConfig3 = FeatureChannel( + val sampleConfig3 = Channel( "config_id3", "name3", "description3", ConfigType.WEBHOOK ) - val searchResult = FeatureChannelList( + val searchResult = ChannelList( 100, 1000, TotalHits.Relation.GREATER_THAN_OR_EQUAL_TO, listOf(sampleConfig1, sampleConfig2, sampleConfig3) ) - val recreatedObject = recreateObject(searchResult) { FeatureChannelList(it) } + val recreatedObject = recreateObject(searchResult) { ChannelList(it) } assertSearchResultEquals(searchResult, recreatedObject) } @Test fun `Search result serialize and deserialize using json config object should be equal`() { - val sampleConfig = FeatureChannel( + val sampleConfig = Channel( "config_id", "name", "description", ConfigType.EMAIL_GROUP ) - val searchResult = FeatureChannelList(sampleConfig) + val searchResult = ChannelList(sampleConfig) val jsonString = getJsonString(searchResult) - val recreatedObject = createObjectFromJsonString(jsonString) { FeatureChannelList(it) } + val recreatedObject = createObjectFromJsonString(jsonString) { ChannelList(it) } assertSearchResultEquals(searchResult, recreatedObject) } @Test fun `Search result serialize and deserialize using json with multiple config object should be equal`() { - val sampleConfig1 = FeatureChannel( + val sampleConfig1 = Channel( "config_id1", "name1", "description1", ConfigType.SLACK ) - val sampleConfig2 = FeatureChannel( + val sampleConfig2 = Channel( "config_id2", "name2", "description2", ConfigType.CHIME ) - val sampleConfig3 = FeatureChannel( + val sampleConfig3 = Channel( "config_id3", "name3", "description3", ConfigType.WEBHOOK ) - val searchResult = FeatureChannelList( + val searchResult = ChannelList( 100, 1000, TotalHits.Relation.GREATER_THAN_OR_EQUAL_TO, listOf(sampleConfig1, sampleConfig2, sampleConfig3) ) val jsonString = getJsonString(searchResult) - val recreatedObject = createObjectFromJsonString(jsonString) { FeatureChannelList(it) } + val recreatedObject = createObjectFromJsonString(jsonString) { ChannelList(it) } assertSearchResultEquals(searchResult, recreatedObject) } @Test fun `Search result should use isEnabled=true if absent in json object`() { - val sampleConfig = FeatureChannel( + val sampleConfig = Channel( "config_id", "name", "description", ConfigType.EMAIL, true ) - val searchResult = FeatureChannelList(sampleConfig) + val searchResult = ChannelList(sampleConfig) val jsonString = """ { "start_index":"0", "total_hits":"1", "total_hit_relation":"eq", - "feature_channel_list":[ + "channel_list":[ { "config_id":"config_id", "name":"name", @@ -138,25 +138,25 @@ internal class FilterConfigListTests { ] } """.trimIndent() - val recreatedObject = createObjectFromJsonString(jsonString) { FeatureChannelList(it) } + val recreatedObject = createObjectFromJsonString(jsonString) { ChannelList(it) } assertSearchResultEquals(searchResult, recreatedObject) } @Test fun `Search result should safely ignore extra field in json object`() { - val sampleConfig = FeatureChannel( + val sampleConfig = Channel( "config_id", "name", "description", ConfigType.EMAIL ) - val searchResult = FeatureChannelList(sampleConfig) + val searchResult = ChannelList(sampleConfig) val jsonString = """ { "start_index":"0", "total_hits":"1", "total_hit_relation":"eq", - "feature_channel_list":[ + "channel_list":[ { "config_id":"config_id", "name":"name", @@ -170,22 +170,22 @@ internal class FilterConfigListTests { "extra_field_3":"extra value 3" } """.trimIndent() - val recreatedObject = createObjectFromJsonString(jsonString) { FeatureChannelList(it) } + val recreatedObject = createObjectFromJsonString(jsonString) { ChannelList(it) } assertSearchResultEquals(searchResult, recreatedObject) } @Test fun `Search result should safely fallback to default if startIndex, totalHits or totalHitRelation field absent in json object`() { - val sampleConfig = FeatureChannel( + val sampleConfig = Channel( "config_id", "name", "description", ConfigType.EMAIL ) - val searchResult = FeatureChannelList(sampleConfig) + val searchResult = ChannelList(sampleConfig) val jsonString = """ { - "feature_channel_list":[ + "channel_list":[ { "config_id":"config_id", "name":"name", @@ -196,12 +196,12 @@ internal class FilterConfigListTests { ] } """.trimIndent() - val recreatedObject = createObjectFromJsonString(jsonString) { FeatureChannelList(it) } + val recreatedObject = createObjectFromJsonString(jsonString) { ChannelList(it) } assertSearchResultEquals(searchResult, recreatedObject) } @Test - fun `Search result should throw exception if featureChannelList is absent in json`() { + fun `Search result should throw exception if channelList is absent in json`() { val jsonString = """ { "start_index":"0", @@ -210,7 +210,7 @@ internal class FilterConfigListTests { } """.trimIndent() Assertions.assertThrows(IllegalArgumentException::class.java) { - createObjectFromJsonString(jsonString) { FeatureChannelList(it) } + createObjectFromJsonString(jsonString) { ChannelList(it) } } } } diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/FilterConfigTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/FilterConfigTests.kt index 234548a8..c3557e89 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/FilterConfigTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/FilterConfigTests.kt @@ -15,45 +15,45 @@ internal class FilterConfigTests { @Test fun `Config serialize and deserialize with default isEnabled flag should be equal`() { - val sampleConfig = FeatureChannel( + val sampleConfig = Channel( "config_id", "name", "description", ConfigType.SLACK ) - val recreatedObject = recreateObject(sampleConfig) { FeatureChannel(it) } + val recreatedObject = recreateObject(sampleConfig) { Channel(it) } assertEquals(sampleConfig, recreatedObject) } @Test fun `Config serialize and deserialize with isEnabled=false should be equal`() { - val sampleConfig = FeatureChannel( + val sampleConfig = Channel( "config_id", "name", "description", ConfigType.CHIME, false ) - val recreatedObject = recreateObject(sampleConfig) { FeatureChannel(it) } + val recreatedObject = recreateObject(sampleConfig) { Channel(it) } assertEquals(sampleConfig, recreatedObject) } @Test fun `Config serialize and deserialize using json object with default isEnabled flag should be equal`() { - val sampleConfig = FeatureChannel( + val sampleConfig = Channel( "config_id", "name", "description", ConfigType.WEBHOOK ) val jsonString = getJsonString(sampleConfig) - val recreatedObject = createObjectFromJsonString(jsonString) { FeatureChannel.parse(it) } + val recreatedObject = createObjectFromJsonString(jsonString) { Channel.parse(it) } assertEquals(sampleConfig, recreatedObject) } @Test fun `Config serialize and deserialize using json object with isEnabled=false should be equal`() { - val sampleConfig = FeatureChannel( + val sampleConfig = Channel( "config_id", "name", "description", @@ -61,13 +61,13 @@ internal class FilterConfigTests { false ) val jsonString = getJsonString(sampleConfig) - val recreatedObject = createObjectFromJsonString(jsonString) { FeatureChannel.parse(it) } + val recreatedObject = createObjectFromJsonString(jsonString) { Channel.parse(it) } assertEquals(sampleConfig, recreatedObject) } @Test fun `Config should safely ignore extra field in json object`() { - val sampleConfig = FeatureChannel( + val sampleConfig = Channel( "config_id", "name", "description", @@ -85,13 +85,13 @@ internal class FilterConfigTests { "extra_field_3":"extra value 3" } """.trimIndent() - val recreatedObject = createObjectFromJsonString(jsonString) { FeatureChannel.parse(it) } + val recreatedObject = createObjectFromJsonString(jsonString) { Channel.parse(it) } assertEquals(sampleConfig, recreatedObject) } @Test fun `Config should safely ignore unknown config type in json object`() { - val sampleConfig = FeatureChannel( + val sampleConfig = Channel( "config_id", "name", "description", @@ -105,14 +105,14 @@ internal class FilterConfigTests { "config_type":"NewConfig" } """.trimIndent() - val recreatedObject = createObjectFromJsonString(jsonString) { FeatureChannel.parse(it) } + val recreatedObject = createObjectFromJsonString(jsonString) { Channel.parse(it) } assertEquals(sampleConfig, recreatedObject) } @Test fun `Config throw exception if configId is empty`() { Assertions.assertThrows(IllegalArgumentException::class.java) { - FeatureChannel( + Channel( "", "name", "description", @@ -124,7 +124,7 @@ internal class FilterConfigTests { @Test fun `Config throw exception if name is empty`() { Assertions.assertThrows(IllegalArgumentException::class.java) { - FeatureChannel( + Channel( "config_id", "", "description", From 6e78f6995bfa3303a9aceb45af28530fcf0de34a Mon Sep 17 00:00:00 2001 From: Vacha Shah Date: Wed, 23 Mar 2022 12:54:51 -0700 Subject: [PATCH 044/140] Adding signoff option for version workflow PR (#143) Signed-off-by: Vacha Shah --- .github/workflows/version.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/version.yml b/.github/workflows/version.yml index 8ca31d8e..6c96199a 100644 --- a/.github/workflows/version.yml +++ b/.github/workflows/version.yml @@ -46,6 +46,7 @@ jobs: token: ${{ steps.github_app_token.outputs.token }} base: ${{ env.BASE }} commit-message: Incremented version to ${{ env.NEXT_VERSION }} + signoff: true delete-branch: true title: '[AUTO] Incremented version to ${{ env.NEXT_VERSION }}.' body: | From 43d6e6da45f15b9b8db21294362c24d0d1b8dfbd Mon Sep 17 00:00:00 2001 From: Mohammad Qureshi <47198598+qreshi@users.noreply.github.com> Date: Mon, 28 Mar 2022 10:28:01 -0700 Subject: [PATCH 045/140] Remove allowedConfigFeatureList from GetPluginFeaturesResponse (#144) Signed-off-by: Mohammad Qureshi <47198598+qreshi@users.noreply.github.com> --- .../notifications/NotificationConstants.kt | 1 - .../action/GetPluginFeaturesResponse.kt | 13 +--------- .../NotificationsPluginInterfaceTests.kt | 1 - .../action/GetPluginFeaturesResponseTests.kt | 26 +------------------ 4 files changed, 2 insertions(+), 39 deletions(-) diff --git a/src/main/kotlin/org/opensearch/commons/notifications/NotificationConstants.kt b/src/main/kotlin/org/opensearch/commons/notifications/NotificationConstants.kt index 146c48de..74fcc600 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/NotificationConstants.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/NotificationConstants.kt @@ -66,7 +66,6 @@ object NotificationConstants { const val QUERY_TAG = "query" const val COMPACT_TAG = "compact" const val ALLOWED_CONFIG_TYPE_LIST_TAG = "allowed_config_type_list" - const val ALLOWED_CONFIG_FEATURE_LIST_TAG = "allowed_config_feature_list" const val PLUGIN_FEATURES_TAG = "plugin_features" const val DEFAULT_MAX_ITEMS = 1000 diff --git a/src/main/kotlin/org/opensearch/commons/notifications/action/GetPluginFeaturesResponse.kt b/src/main/kotlin/org/opensearch/commons/notifications/action/GetPluginFeaturesResponse.kt index 1e6fa2b9..73db57a0 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/action/GetPluginFeaturesResponse.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/action/GetPluginFeaturesResponse.kt @@ -11,7 +11,6 @@ import org.opensearch.common.xcontent.ToXContent import org.opensearch.common.xcontent.XContentBuilder import org.opensearch.common.xcontent.XContentParser import org.opensearch.common.xcontent.XContentParserUtils -import org.opensearch.commons.notifications.NotificationConstants.ALLOWED_CONFIG_FEATURE_LIST_TAG import org.opensearch.commons.notifications.NotificationConstants.ALLOWED_CONFIG_TYPE_LIST_TAG import org.opensearch.commons.notifications.NotificationConstants.PLUGIN_FEATURES_TAG import org.opensearch.commons.utils.STRING_READER @@ -25,7 +24,6 @@ import java.io.IOException */ class GetPluginFeaturesResponse : BaseResponse { val allowedConfigTypeList: List - val allowedConfigFeatureList: List val pluginFeatures: Map companion object { @@ -44,7 +42,6 @@ class GetPluginFeaturesResponse : BaseResponse { @Throws(IOException::class) fun parse(parser: XContentParser): GetPluginFeaturesResponse { var allowedConfigTypeList: List? = null - var allowedConfigFeatureList: List? = null var pluginFeatures: Map? = null XContentParserUtils.ensureExpectedToken( @@ -57,7 +54,6 @@ class GetPluginFeaturesResponse : BaseResponse { parser.nextToken() when (fieldName) { ALLOWED_CONFIG_TYPE_LIST_TAG -> allowedConfigTypeList = parser.stringList() - ALLOWED_CONFIG_FEATURE_LIST_TAG -> allowedConfigFeatureList = parser.stringList() PLUGIN_FEATURES_TAG -> pluginFeatures = parser.mapStrings() else -> { parser.skipChildren() @@ -66,9 +62,8 @@ class GetPluginFeaturesResponse : BaseResponse { } } allowedConfigTypeList ?: throw IllegalArgumentException("$ALLOWED_CONFIG_TYPE_LIST_TAG field absent") - allowedConfigFeatureList ?: throw IllegalArgumentException("$ALLOWED_CONFIG_TYPE_LIST_TAG field absent") pluginFeatures ?: throw IllegalArgumentException("$PLUGIN_FEATURES_TAG field absent") - return GetPluginFeaturesResponse(allowedConfigTypeList, allowedConfigFeatureList, pluginFeatures) + return GetPluginFeaturesResponse(allowedConfigTypeList, pluginFeatures) } } @@ -78,7 +73,6 @@ class GetPluginFeaturesResponse : BaseResponse { override fun toXContent(builder: XContentBuilder?, params: ToXContent.Params?): XContentBuilder { return builder!!.startObject() .field(ALLOWED_CONFIG_TYPE_LIST_TAG, allowedConfigTypeList) - .field(ALLOWED_CONFIG_FEATURE_LIST_TAG, allowedConfigFeatureList) .field(PLUGIN_FEATURES_TAG, pluginFeatures) .endObject() } @@ -86,16 +80,13 @@ class GetPluginFeaturesResponse : BaseResponse { /** * constructor for creating the class * @param allowedConfigTypeList the list of config types supported by plugin - * @param allowedConfigFeatureList the list of config features supported by plugin * @param pluginFeatures the map of plugin features supported to its value */ constructor( allowedConfigTypeList: List, - allowedConfigFeatureList: List, pluginFeatures: Map ) { this.allowedConfigTypeList = allowedConfigTypeList - this.allowedConfigFeatureList = allowedConfigFeatureList this.pluginFeatures = pluginFeatures } @@ -105,7 +96,6 @@ class GetPluginFeaturesResponse : BaseResponse { @Throws(IOException::class) constructor(input: StreamInput) : super(input) { allowedConfigTypeList = input.readStringList() - allowedConfigFeatureList = input.readStringList() pluginFeatures = input.readMap(STRING_READER, STRING_READER) } @@ -115,7 +105,6 @@ class GetPluginFeaturesResponse : BaseResponse { @Throws(IOException::class) override fun writeTo(output: StreamOutput) { output.writeStringCollection(allowedConfigTypeList) - output.writeStringCollection(allowedConfigFeatureList) output.writeMap(pluginFeatures, STRING_WRITER, STRING_WRITER) } } diff --git a/src/test/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterfaceTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterfaceTests.kt index c71836eb..aaa831d1 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterfaceTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterfaceTests.kt @@ -148,7 +148,6 @@ internal class NotificationsPluginInterfaceTests { val request = mock(GetPluginFeaturesRequest::class.java) val response = GetPluginFeaturesResponse( listOf("config_type_1", "config_type_2", "config_type_3"), - listOf("config_feature_1", "config_feature_2", "config_feature_3"), mapOf( Pair("FeatureKey1", "FeatureValue1"), Pair("FeatureKey2", "FeatureValue2"), diff --git a/src/test/kotlin/org/opensearch/commons/notifications/action/GetPluginFeaturesResponseTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/action/GetPluginFeaturesResponseTests.kt index 72b9a49f..1aa065a2 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/action/GetPluginFeaturesResponseTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/action/GetPluginFeaturesResponseTests.kt @@ -18,7 +18,6 @@ internal class GetPluginFeaturesResponseTests { actual: GetPluginFeaturesResponse ) { assertEquals(expected.allowedConfigTypeList, actual.allowedConfigTypeList) - assertEquals(expected.allowedConfigFeatureList, actual.allowedConfigFeatureList) assertEquals(expected.pluginFeatures, actual.pluginFeatures) } @@ -26,7 +25,6 @@ internal class GetPluginFeaturesResponseTests { fun `Get Response serialize and deserialize transport object should be equal`() { val response = GetPluginFeaturesResponse( listOf("config_type_1", "config_type_2", "config_type_3"), - listOf("config_feature_1", "config_feature_2", "config_feature_3"), mapOf( Pair("FeatureKey1", "FeatureValue1"), Pair("FeatureKey2", "FeatureValue2"), @@ -41,7 +39,6 @@ internal class GetPluginFeaturesResponseTests { fun `Get Response serialize and deserialize using json config object should be equal`() { val response = GetPluginFeaturesResponse( listOf("config_type_1", "config_type_2", "config_type_3"), - listOf("config_feature_1", "config_feature_2", "config_feature_3"), mapOf( Pair("FeatureKey1", "FeatureValue1"), Pair("FeatureKey2", "FeatureValue2"), @@ -57,7 +54,6 @@ internal class GetPluginFeaturesResponseTests { fun `Get Response should safely ignore extra field in json object`() { val response = GetPluginFeaturesResponse( listOf("config_type_1", "config_type_2", "config_type_3"), - listOf("config_feature_1", "config_feature_2", "config_feature_3"), mapOf( Pair("FeatureKey1", "FeatureValue1"), Pair("FeatureKey2", "FeatureValue2"), @@ -67,7 +63,6 @@ internal class GetPluginFeaturesResponseTests { val jsonString = """ { "allowed_config_type_list":["config_type_1", "config_type_2", "config_type_3"], - "allowed_config_feature_list":["config_feature_1", "config_feature_2", "config_feature_3"], "plugin_features":{ "FeatureKey1":"FeatureValue1", "FeatureKey2":"FeatureValue2", @@ -86,24 +81,6 @@ internal class GetPluginFeaturesResponseTests { fun `Get Response should throw exception if allowed_config_type_list is absent in json`() { val jsonString = """ { - "allowed_config_feature_list":["config_feature_1", "config_feature_2", "config_feature_3"], - "plugin_features":{ - "FeatureKey1":"FeatureValue1", - "FeatureKey2":"FeatureValue2", - "FeatureKey3":"FeatureValue3" - } - } - """.trimIndent() - Assertions.assertThrows(IllegalArgumentException::class.java) { - createObjectFromJsonString(jsonString) { GetPluginFeaturesResponse.parse(it) } - } - } - - @Test - fun `Get Response should throw exception if allowed_config_feature_list is absent in json`() { - val jsonString = """ - { - "allowed_config_type_list":["config_type_1", "config_type_2", "config_type_3"], "plugin_features":{ "FeatureKey1":"FeatureValue1", "FeatureKey2":"FeatureValue2", @@ -120,8 +97,7 @@ internal class GetPluginFeaturesResponseTests { fun `Get Response should throw exception if plugin_features is absent in json`() { val jsonString = """ { - "config_type_list":["config_type_1", "config_type_2", "config_type_3"], - "allowed_config_feature_list":["config_feature_1", "config_feature_2", "config_feature_3"] + "config_type_list":["config_type_1", "config_type_2", "config_type_3"] } """.trimIndent() Assertions.assertThrows(IllegalArgumentException::class.java) { From f2f57e59351973916d6fcb5a8ec5e958060c6593 Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Mon, 28 Mar 2022 16:56:39 -0400 Subject: [PATCH 046/140] change default opensearch version to 2.0.0-alpha1-SNAPSHOT (#146) Signed-off-by: Peter Zhu --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index bc142d75..f11f252e 100644 --- a/build.gradle +++ b/build.gradle @@ -6,7 +6,7 @@ buildscript { ext { opensearch_group = "org.opensearch" - opensearch_version = System.getProperty("opensearch.version", "2.0.0-SNAPSHOT") + opensearch_version = System.getProperty("opensearch.version", "2.0.0-alpha1-SNAPSHOT") kotlin_version = System.getProperty("kotlin.version", "1.6.10") } From a6c2da895cfd585fa48aeb1454f5584cbb331876 Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Thu, 31 Mar 2022 16:44:08 -0400 Subject: [PATCH 047/140] Add qualifier default to alpha1 in build.gradle (#151) Signed-off-by: Peter Zhu --- build.gradle | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/build.gradle b/build.gradle index f11f252e..cf3ca5b9 100644 --- a/build.gradle +++ b/build.gradle @@ -7,6 +7,8 @@ buildscript { ext { opensearch_group = "org.opensearch" opensearch_version = System.getProperty("opensearch.version", "2.0.0-alpha1-SNAPSHOT") + isSnapshot = "true" == System.getProperty("build.snapshot", "true") + buildVersionQualifier = System.getProperty("build.version_qualifier", "alpha1") kotlin_version = System.getProperty("kotlin.version", "1.6.10") } @@ -38,11 +40,6 @@ repositories { maven { url "https://aws.oss.sonatype.org/content/repositories/snapshots" } } -ext { - isSnapshot = "true" == System.getProperty("build.snapshot", "true") - buildVersionQualifier = System.getProperty("build.version_qualifier") -} - allprojects { group 'org.opensearch.commons' version = opensearch_version.tokenize('-')[0] + '.0' From 58cd7ccf3179a3003f60486d061ece08b81e7b08 Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Thu, 31 Mar 2022 22:18:55 -0400 Subject: [PATCH 048/140] Make CU hosts its own script before delete the one on build repo (#152) Signed-off-by: Peter Zhu --- scripts/build.sh | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/scripts/build.sh b/scripts/build.sh index 1f8b6d4d..e0495d4a 100755 --- a/scripts/build.sh +++ b/scripts/build.sh @@ -10,7 +10,7 @@ function usage() { echo "" echo "Arguments:" echo -e "-v VERSION\t[Required] OpenSearch version." - echo -e "-q QUALIFIER\t[Optional] Build qualifier." + echo -e "-q QUALIFIER\t[Optional] Version qualifier." echo -e "-s SNAPSHOT\t[Optional] Build a snapshot, default is 'false'." echo -e "-p PLATFORM\t[Optional] Platform, ignored." echo -e "-a ARCHITECTURE\t[Optional] Build architecture, ignored." @@ -60,11 +60,12 @@ if [ -z "$VERSION" ]; then exit 1 fi +[[ ! -z "$QUALIFIER" ]] && VERSION=$VERSION-$QUALIFIER [[ "$SNAPSHOT" == "true" ]] && VERSION=$VERSION-SNAPSHOT [ -z "$OUTPUT" ] && OUTPUT=artifacts -./gradlew build -Dopensearch.version=$VERSION -Dbuild.snapshot=$SNAPSHOT -Dbuild.version_qualifier=$QUALIFIER +./gradlew build -x test -Dopensearch.version=$VERSION -Dbuild.snapshot=$SNAPSHOT -Dbuild.version_qualifier=$QUALIFIER ./gradlew publishShadowPublicationToMavenLocal -Dopensearch.version=$VERSION -Dbuild.snapshot=$SNAPSHOT -Dbuild.version_qualifier=$QUALIFIER ./gradlew publishShadowPublicationToStagingRepository -Dopensearch.version=$VERSION -Dbuild.snapshot=$SNAPSHOT -Dbuild.version_qualifier=$QUALIFIER mkdir -p $OUTPUT/maven/org/opensearch -cp -r ./build/local-staging-repo/org/opensearch/common-utils $OUTPUT/maven/org/opensearch/common-utils +cp -r ./build/local-staging-repo/org/opensearch/. $OUTPUT/maven/org/opensearch From f62e734c323bd5148600c040f919634eb00e485e Mon Sep 17 00:00:00 2001 From: Aditya Jindal <13850971+aditjind@users.noreply.github.com> Date: Tue, 5 Apr 2022 13:43:56 -0700 Subject: [PATCH 049/140] Removal of NotificationEvent Request, Response and SearchResults (#153) * Removal of NotificationEvent Request, Response , Search Results Addition of NotificationEventDoc and Removal of NotificationEventInfo Addition of NotificationEventDocTests Signed-off-by: Jindal * Removing NotificationEventDoc and NotificationEventDocTests Signed-off-by: Jindal Co-authored-by: Jindal --- .../NotificationsPluginInterface.kt | 21 - .../action/GetNotificationEventRequest.kt | 171 -------- .../action/GetNotificationEventResponse.kt | 70 ---- .../action/NotificationsActions.kt | 11 - .../model/NotificationEventInfo.kt | 122 ------ .../model/NotificationEventSearchResult.kt | 71 ---- .../NotificationsPluginInterfaceTests.kt | 45 -- .../GetNotificationEventRequestTests.kt | 258 ------------ .../GetNotificationEventResponseTests.kt | 345 --------------- .../model/NotificationEventInfoTests.kt | 273 ------------ .../NotificationEventSearchResultTests.kt | 396 ------------------ 11 files changed, 1783 deletions(-) delete mode 100644 src/main/kotlin/org/opensearch/commons/notifications/action/GetNotificationEventRequest.kt delete mode 100644 src/main/kotlin/org/opensearch/commons/notifications/action/GetNotificationEventResponse.kt delete mode 100644 src/main/kotlin/org/opensearch/commons/notifications/model/NotificationEventInfo.kt delete mode 100644 src/main/kotlin/org/opensearch/commons/notifications/model/NotificationEventSearchResult.kt delete mode 100644 src/test/kotlin/org/opensearch/commons/notifications/action/GetNotificationEventRequestTests.kt delete mode 100644 src/test/kotlin/org/opensearch/commons/notifications/action/GetNotificationEventResponseTests.kt delete mode 100644 src/test/kotlin/org/opensearch/commons/notifications/model/NotificationEventInfoTests.kt delete mode 100644 src/test/kotlin/org/opensearch/commons/notifications/model/NotificationEventSearchResultTests.kt diff --git a/src/main/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterface.kt b/src/main/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterface.kt index 2da0562d..c3baa938 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterface.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterface.kt @@ -18,8 +18,6 @@ import org.opensearch.commons.notifications.action.GetChannelListRequest import org.opensearch.commons.notifications.action.GetChannelListResponse import org.opensearch.commons.notifications.action.GetNotificationConfigRequest import org.opensearch.commons.notifications.action.GetNotificationConfigResponse -import org.opensearch.commons.notifications.action.GetNotificationEventRequest -import org.opensearch.commons.notifications.action.GetNotificationEventResponse import org.opensearch.commons.notifications.action.GetPluginFeaturesRequest import org.opensearch.commons.notifications.action.GetPluginFeaturesResponse import org.opensearch.commons.notifications.action.LegacyPublishNotificationRequest @@ -28,7 +26,6 @@ import org.opensearch.commons.notifications.action.NotificationsActions.CREATE_N import org.opensearch.commons.notifications.action.NotificationsActions.DELETE_NOTIFICATION_CONFIG_ACTION_TYPE import org.opensearch.commons.notifications.action.NotificationsActions.GET_CHANNEL_LIST_ACTION_TYPE import org.opensearch.commons.notifications.action.NotificationsActions.GET_NOTIFICATION_CONFIG_ACTION_TYPE -import org.opensearch.commons.notifications.action.NotificationsActions.GET_NOTIFICATION_EVENT_ACTION_TYPE import org.opensearch.commons.notifications.action.NotificationsActions.GET_PLUGIN_FEATURES_ACTION_TYPE import org.opensearch.commons.notifications.action.NotificationsActions.LEGACY_PUBLISH_NOTIFICATION_ACTION_TYPE import org.opensearch.commons.notifications.action.NotificationsActions.SEND_NOTIFICATION_ACTION_TYPE @@ -119,24 +116,6 @@ object NotificationsPluginInterface { ) } - /** - * Get notification events. - * @param client Node client for making transport action - * @param request The request object - * @param listener The listener for getting response - */ - fun getNotificationEvent( - client: NodeClient, - request: GetNotificationEventRequest, - listener: ActionListener - ) { - client.execute( - GET_NOTIFICATION_EVENT_ACTION_TYPE, - request, - wrapActionListener(listener) { response -> recreateObject(response) { GetNotificationEventResponse(it) } } - ) - } - /** * Get notification plugin features. * @param client Node client for making transport action diff --git a/src/main/kotlin/org/opensearch/commons/notifications/action/GetNotificationEventRequest.kt b/src/main/kotlin/org/opensearch/commons/notifications/action/GetNotificationEventRequest.kt deleted file mode 100644 index 66bfba6a..00000000 --- a/src/main/kotlin/org/opensearch/commons/notifications/action/GetNotificationEventRequest.kt +++ /dev/null @@ -1,171 +0,0 @@ -/* - * Copyright OpenSearch Contributors - * SPDX-License-Identifier: Apache-2.0 - */ -package org.opensearch.commons.notifications.action - -import org.opensearch.action.ActionRequest -import org.opensearch.action.ActionRequestValidationException -import org.opensearch.action.ValidateActions -import org.opensearch.common.io.stream.StreamInput -import org.opensearch.common.io.stream.StreamOutput -import org.opensearch.common.io.stream.Writeable -import org.opensearch.common.xcontent.ToXContent -import org.opensearch.common.xcontent.ToXContentObject -import org.opensearch.common.xcontent.XContentBuilder -import org.opensearch.common.xcontent.XContentParser -import org.opensearch.common.xcontent.XContentParserUtils -import org.opensearch.commons.notifications.NotificationConstants.DEFAULT_MAX_ITEMS -import org.opensearch.commons.notifications.NotificationConstants.EVENT_ID_LIST_TAG -import org.opensearch.commons.notifications.NotificationConstants.FILTER_PARAM_LIST_TAG -import org.opensearch.commons.notifications.NotificationConstants.FROM_INDEX_TAG -import org.opensearch.commons.notifications.NotificationConstants.MAX_ITEMS_TAG -import org.opensearch.commons.notifications.NotificationConstants.SORT_FIELD_TAG -import org.opensearch.commons.notifications.NotificationConstants.SORT_ORDER_TAG -import org.opensearch.commons.utils.STRING_READER -import org.opensearch.commons.utils.STRING_WRITER -import org.opensearch.commons.utils.enumReader -import org.opensearch.commons.utils.fieldIfNotNull -import org.opensearch.commons.utils.logger -import org.opensearch.commons.utils.stringList -import org.opensearch.search.sort.SortOrder -import java.io.IOException - -/** - * Action Request for getting notification event. - */ -class GetNotificationEventRequest : ActionRequest, ToXContentObject { - val eventIds: Set - val fromIndex: Int - val maxItems: Int - val sortField: String? - val sortOrder: SortOrder? - val filterParams: Map - - companion object { - private val log by logger(GetNotificationEventRequest::class.java) - - /** - * reader to create instance of class from writable. - */ - val reader = Writeable.Reader { GetNotificationEventRequest(it) } - - /** - * Creator used in REST communication. - * @param parser XContentParser to deserialize data from. - */ - @JvmStatic - @Throws(IOException::class) - fun parse(parser: XContentParser): GetNotificationEventRequest { - var eventIds: Set = setOf() - var fromIndex = 0 - var maxItems = DEFAULT_MAX_ITEMS - var sortField: String? = null - var sortOrder: SortOrder? = null - var filterParams: Map = mapOf() - - XContentParserUtils.ensureExpectedToken( - XContentParser.Token.START_OBJECT, - parser.currentToken(), - parser - ) - while (parser.nextToken() != XContentParser.Token.END_OBJECT) { - val fieldName = parser.currentName() - parser.nextToken() - when (fieldName) { - EVENT_ID_LIST_TAG -> eventIds = parser.stringList().toSet() - FROM_INDEX_TAG -> fromIndex = parser.intValue() - MAX_ITEMS_TAG -> maxItems = parser.intValue() - SORT_FIELD_TAG -> sortField = parser.textOrNull() - SORT_ORDER_TAG -> sortOrder = SortOrder.fromString(parser.text()) - FILTER_PARAM_LIST_TAG -> filterParams = parser.mapStrings() - else -> { - parser.skipChildren() - log.info("Unexpected field: $fieldName, while parsing GetNotificationEventRequest") - } - } - } - return GetNotificationEventRequest(eventIds, fromIndex, maxItems, sortField, sortOrder, filterParams) - } - } - - /** - * {@inheritDoc} - */ - override fun toXContent(builder: XContentBuilder?, params: ToXContent.Params?): XContentBuilder { - return builder!!.startObject() - .field(EVENT_ID_LIST_TAG, eventIds) - .field(FROM_INDEX_TAG, fromIndex) - .field(MAX_ITEMS_TAG, maxItems) - .fieldIfNotNull(SORT_FIELD_TAG, sortField) - .fieldIfNotNull(SORT_ORDER_TAG, sortOrder) - .field(FILTER_PARAM_LIST_TAG, filterParams) - .endObject() - } - - /** - * constructor for creating the class - * @param eventIds the ids of the notification events (other parameters are not relevant if ids are present) - * @param fromIndex the starting index for paginated response - * @param maxItems the maximum number of items to return for paginated response - * @param sortField the sort field if response has many items - * @param sortOrder the sort order if response has many items - * @param filterParams the filter parameters - */ - constructor( - eventIds: Set = setOf(), - fromIndex: Int = 0, - maxItems: Int = DEFAULT_MAX_ITEMS, - sortField: String? = null, - sortOrder: SortOrder? = null, - filterParams: Map = mapOf() - ) { - this.eventIds = eventIds - this.fromIndex = fromIndex - this.maxItems = maxItems - this.sortField = sortField - this.sortOrder = sortOrder - this.filterParams = filterParams - } - - /** - * {@inheritDoc} - */ - @Throws(IOException::class) - constructor(input: StreamInput) : super(input) { - eventIds = input.readStringList().toSet() - fromIndex = input.readInt() - maxItems = input.readInt() - sortField = input.readOptionalString() - sortOrder = input.readOptionalWriteable(enumReader(SortOrder::class.java)) - filterParams = input.readMap(STRING_READER, STRING_READER) - } - - /** - * {@inheritDoc} - */ - @Throws(IOException::class) - override fun writeTo(output: StreamOutput) { - super.writeTo(output) - output.writeStringCollection(eventIds) - output.writeInt(fromIndex) - output.writeInt(maxItems) - output.writeOptionalString(sortField) - output.writeOptionalWriteable(sortOrder) - output.writeMap(filterParams, STRING_WRITER, STRING_WRITER) - } - - /** - * {@inheritDoc} - */ - override fun validate(): ActionRequestValidationException? { - var validationException: ActionRequestValidationException? = null - if (fromIndex < 0) { - validationException = ValidateActions.addValidationError("fromIndex is -ve", validationException) - } - if (maxItems <= 0) { - validationException = ValidateActions.addValidationError("maxItems is not +ve", validationException) - } - return validationException - } -} diff --git a/src/main/kotlin/org/opensearch/commons/notifications/action/GetNotificationEventResponse.kt b/src/main/kotlin/org/opensearch/commons/notifications/action/GetNotificationEventResponse.kt deleted file mode 100644 index c512aa48..00000000 --- a/src/main/kotlin/org/opensearch/commons/notifications/action/GetNotificationEventResponse.kt +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright OpenSearch Contributors - * SPDX-License-Identifier: Apache-2.0 - */ -package org.opensearch.commons.notifications.action - -import org.opensearch.common.io.stream.StreamInput -import org.opensearch.common.io.stream.StreamOutput -import org.opensearch.common.io.stream.Writeable -import org.opensearch.common.xcontent.ToXContent -import org.opensearch.common.xcontent.XContentBuilder -import org.opensearch.common.xcontent.XContentParser -import org.opensearch.commons.notifications.model.NotificationEventSearchResult -import java.io.IOException - -/** - * Action Response for getting notification event. - */ -class GetNotificationEventResponse : BaseResponse { - val searchResult: NotificationEventSearchResult - - companion object { - - /** - * reader to create instance of class from writable. - */ - val reader = Writeable.Reader { GetNotificationEventResponse(it) } - - /** - * Creator used in REST communication. - * @param parser XContentParser to deserialize data from. - */ - @JvmStatic - @Throws(IOException::class) - fun parse(parser: XContentParser): GetNotificationEventResponse { - return GetNotificationEventResponse(NotificationEventSearchResult(parser)) - } - } - - /** - * constructor for creating the class - * @param searchResult the notification event list - */ - constructor(searchResult: NotificationEventSearchResult) { - this.searchResult = searchResult - } - - /** - * {@inheritDoc} - */ - @Throws(IOException::class) - constructor(input: StreamInput) : super(input) { - searchResult = NotificationEventSearchResult(input) - } - - /** - * {@inheritDoc} - */ - @Throws(IOException::class) - override fun writeTo(output: StreamOutput) { - searchResult.writeTo(output) - } - - /** - * {@inheritDoc} - */ - override fun toXContent(builder: XContentBuilder?, params: ToXContent.Params?): XContentBuilder { - return searchResult.toXContent(builder, params) - } -} diff --git a/src/main/kotlin/org/opensearch/commons/notifications/action/NotificationsActions.kt b/src/main/kotlin/org/opensearch/commons/notifications/action/NotificationsActions.kt index 204d9326..e4a8cfe5 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/action/NotificationsActions.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/action/NotificationsActions.kt @@ -30,11 +30,6 @@ object NotificationsActions { */ const val GET_NOTIFICATION_CONFIG_NAME = "cluster:admin/opensearch/notifications/configs/get" - /** - * Get notification events transport action name. - */ - const val GET_NOTIFICATION_EVENT_NAME = "cluster:admin/opensearch/notifications/events/get" - /** * Get notification plugin features transport action name. */ @@ -80,12 +75,6 @@ object NotificationsActions { val GET_NOTIFICATION_CONFIG_ACTION_TYPE = ActionType(GET_NOTIFICATION_CONFIG_NAME, ::GetNotificationConfigResponse) - /** - * Get notification events transport action type. - */ - val GET_NOTIFICATION_EVENT_ACTION_TYPE = - ActionType(GET_NOTIFICATION_EVENT_NAME, ::GetNotificationEventResponse) - /** * Get notification plugin features transport action type. */ diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationEventInfo.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationEventInfo.kt deleted file mode 100644 index 51921fc8..00000000 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationEventInfo.kt +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright OpenSearch Contributors - * SPDX-License-Identifier: Apache-2.0 - */ -package org.opensearch.commons.notifications.model - -import org.opensearch.common.Strings -import org.opensearch.common.io.stream.StreamInput -import org.opensearch.common.io.stream.StreamOutput -import org.opensearch.common.io.stream.Writeable -import org.opensearch.common.xcontent.ToXContent -import org.opensearch.common.xcontent.XContentBuilder -import org.opensearch.common.xcontent.XContentParser -import org.opensearch.common.xcontent.XContentParserUtils -import org.opensearch.commons.notifications.NotificationConstants.CREATED_TIME_TAG -import org.opensearch.commons.notifications.NotificationConstants.EVENT_ID_TAG -import org.opensearch.commons.notifications.NotificationConstants.EVENT_TAG -import org.opensearch.commons.notifications.NotificationConstants.UPDATED_TIME_TAG -import org.opensearch.commons.utils.logger -import java.io.IOException -import java.time.Instant - -/** - * Data class representing Notification event with information. - */ -data class NotificationEventInfo( - val eventId: String, - val lastUpdatedTime: Instant, - val createdTime: Instant, - val notificationEvent: NotificationEvent -) : BaseModel { - - init { - require(!Strings.isNullOrEmpty(eventId)) { "event id is null or empty" } - } - - companion object { - private val log by logger(NotificationEventInfo::class.java) - - /** - * reader to create instance of class from writable. - */ - val reader = Writeable.Reader { NotificationEventInfo(it) } - - /** - * Creator used in REST communication. - * @param parser XContentParser to deserialize data from. - */ - @JvmStatic - @Throws(IOException::class) - fun parse(parser: XContentParser): NotificationEventInfo { - var eventId: String? = null - var lastUpdatedTime: Instant? = null - var createdTime: Instant? = null - var notificationEvent: NotificationEvent? = null - - XContentParserUtils.ensureExpectedToken( - XContentParser.Token.START_OBJECT, - parser.currentToken(), - parser - ) - while (parser.nextToken() != XContentParser.Token.END_OBJECT) { - val fieldName = parser.currentName() - parser.nextToken() - when (fieldName) { - EVENT_ID_TAG -> eventId = parser.text() - UPDATED_TIME_TAG -> lastUpdatedTime = Instant.ofEpochMilli(parser.longValue()) - CREATED_TIME_TAG -> createdTime = Instant.ofEpochMilli(parser.longValue()) - EVENT_TAG -> notificationEvent = NotificationEvent.parse(parser) - else -> { - parser.skipChildren() - log.info("Unexpected field: $fieldName, while parsing event info") - } - } - } - eventId ?: throw IllegalArgumentException("$EVENT_ID_TAG field absent") - lastUpdatedTime ?: throw IllegalArgumentException("$UPDATED_TIME_TAG field absent") - createdTime ?: throw IllegalArgumentException("$CREATED_TIME_TAG field absent") - notificationEvent ?: throw IllegalArgumentException("$EVENT_TAG field absent") - return NotificationEventInfo( - eventId, - lastUpdatedTime, - createdTime, - notificationEvent - ) - } - } - - /** - * {@inheritDoc} - */ - override fun toXContent(builder: XContentBuilder?, params: ToXContent.Params?): XContentBuilder { - builder!! - return builder.startObject() - .field(EVENT_ID_TAG, eventId) - .field(UPDATED_TIME_TAG, lastUpdatedTime.toEpochMilli()) - .field(CREATED_TIME_TAG, createdTime.toEpochMilli()) - .field(EVENT_TAG, notificationEvent) - .endObject() - } - - /** - * Constructor used in transport action communication. - * @param input StreamInput stream to deserialize data from. - */ - constructor(input: StreamInput) : this( - eventId = input.readString(), - lastUpdatedTime = input.readInstant(), - createdTime = input.readInstant(), - notificationEvent = NotificationEvent.reader.read(input) - ) - - /** - * {@inheritDoc} - */ - override fun writeTo(output: StreamOutput) { - output.writeString(eventId) - output.writeInstant(lastUpdatedTime) - output.writeInstant(createdTime) - notificationEvent.writeTo(output) - } -} diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationEventSearchResult.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationEventSearchResult.kt deleted file mode 100644 index e9b68406..00000000 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationEventSearchResult.kt +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright OpenSearch Contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -package org.opensearch.commons.notifications.model - -import org.apache.lucene.search.TotalHits -import org.opensearch.action.search.SearchResponse -import org.opensearch.common.io.stream.StreamInput -import org.opensearch.common.xcontent.XContentParser -import org.opensearch.commons.notifications.NotificationConstants.EVENT_LIST_TAG - -/** - * Notification Event search results - */ -class NotificationEventSearchResult : SearchResults { - - /** - * single item result constructor - */ - constructor(objectItem: NotificationEventInfo) : super(EVENT_LIST_TAG, objectItem) - - /** - * multiple items result constructor - */ - constructor(objectList: List) : this( - 0, - objectList.size.toLong(), - TotalHits.Relation.EQUAL_TO, - objectList - ) - - /** - * all param constructor - */ - constructor( - startIndex: Long, - totalHits: Long, - totalHitRelation: TotalHits.Relation, - objectList: List - ) : super(startIndex, totalHits, totalHitRelation, EVENT_LIST_TAG, objectList) - - /** - * Constructor used in transport action communication. - * @param input StreamInput stream to deserialize data from. - */ - constructor(input: StreamInput) : super(input, NotificationEventInfo.reader) - - /** - * Construct object from XContentParser - */ - constructor(parser: XContentParser) : super(parser, EVENT_LIST_TAG) - - /** - * Construct object from SearchResponse - */ - constructor(from: Long, response: SearchResponse, searchHitParser: SearchHitParser) : super( - from, - response, - searchHitParser, - EVENT_LIST_TAG - ) - - /** - * {@inheritDoc} - */ - override fun parseItem(parser: XContentParser): NotificationEventInfo { - return NotificationEventInfo.parse(parser) - } -} diff --git a/src/test/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterfaceTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterfaceTests.kt index aaa831d1..556c35b6 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterfaceTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterfaceTests.kt @@ -29,8 +29,6 @@ import org.opensearch.commons.notifications.action.GetChannelListRequest import org.opensearch.commons.notifications.action.GetChannelListResponse import org.opensearch.commons.notifications.action.GetNotificationConfigRequest import org.opensearch.commons.notifications.action.GetNotificationConfigResponse -import org.opensearch.commons.notifications.action.GetNotificationEventRequest -import org.opensearch.commons.notifications.action.GetNotificationEventResponse import org.opensearch.commons.notifications.action.GetPluginFeaturesRequest import org.opensearch.commons.notifications.action.GetPluginFeaturesResponse import org.opensearch.commons.notifications.action.LegacyPublishNotificationRequest @@ -42,15 +40,10 @@ import org.opensearch.commons.notifications.model.Channel import org.opensearch.commons.notifications.model.ChannelList import org.opensearch.commons.notifications.model.ChannelMessage import org.opensearch.commons.notifications.model.ConfigType -import org.opensearch.commons.notifications.model.DeliveryStatus import org.opensearch.commons.notifications.model.EventSource -import org.opensearch.commons.notifications.model.EventStatus import org.opensearch.commons.notifications.model.NotificationConfig import org.opensearch.commons.notifications.model.NotificationConfigInfo import org.opensearch.commons.notifications.model.NotificationConfigSearchResult -import org.opensearch.commons.notifications.model.NotificationEvent -import org.opensearch.commons.notifications.model.NotificationEventInfo -import org.opensearch.commons.notifications.model.NotificationEventSearchResult import org.opensearch.commons.notifications.model.SeverityType import org.opensearch.commons.notifications.model.Slack import org.opensearch.rest.RestStatus @@ -127,22 +120,6 @@ internal class NotificationsPluginInterfaceTests { verify(listener, times(1)).onResponse(eq(response)) } - @Test - fun getNotificationEvent() { - val request = mock(GetNotificationEventRequest::class.java) - val response = mockGetNotificationEventResponse() - val listener: ActionListener = - mock(ActionListener::class.java) as ActionListener - - doAnswer { - (it.getArgument(2) as ActionListener) - .onResponse(response) - }.whenever(client).execute(any(ActionType::class.java), any(), any()) - - NotificationsPluginInterface.getNotificationEvent(client, request, listener) - verify(listener, times(1)).onResponse(eq(response)) - } - @Test fun getPluginFeatures() { val request = mock(GetPluginFeaturesRequest::class.java) @@ -250,26 +227,4 @@ internal class NotificationsPluginInterfaceTests { ) return GetNotificationConfigResponse(NotificationConfigSearchResult(configInfo)) } - - private fun mockGetNotificationEventResponse(): GetNotificationEventResponse { - val sampleEventSource = EventSource( - "title", - "reference_id", - severity = SeverityType.INFO - ) - val sampleStatus = EventStatus( - "config_id", - "name", - ConfigType.SLACK, - deliveryStatus = DeliveryStatus("404", "invalid recipient") - ) - val sampleEvent = NotificationEvent(sampleEventSource, listOf(sampleStatus)) - val eventInfo = NotificationEventInfo( - "event_id", - Instant.now(), - Instant.now(), - sampleEvent - ) - return GetNotificationEventResponse(NotificationEventSearchResult(eventInfo)) - } } diff --git a/src/test/kotlin/org/opensearch/commons/notifications/action/GetNotificationEventRequestTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/action/GetNotificationEventRequestTests.kt deleted file mode 100644 index 53bb825a..00000000 --- a/src/test/kotlin/org/opensearch/commons/notifications/action/GetNotificationEventRequestTests.kt +++ /dev/null @@ -1,258 +0,0 @@ -/* - * Copyright OpenSearch Contributors - * SPDX-License-Identifier: Apache-2.0 - */ -package org.opensearch.commons.notifications.action - -import com.fasterxml.jackson.core.JsonParseException -import org.junit.jupiter.api.Assertions.assertEquals -import org.junit.jupiter.api.Test -import org.junit.jupiter.api.assertThrows -import org.opensearch.commons.utils.createObjectFromJsonString -import org.opensearch.commons.utils.getJsonString -import org.opensearch.commons.utils.recreateObject -import org.opensearch.search.sort.SortOrder - -internal class GetNotificationEventRequestTests { - - private fun assertGetRequestEquals( - expected: GetNotificationEventRequest, - actual: GetNotificationEventRequest - ) { - assertEquals(expected.eventIds, actual.eventIds) - assertEquals(expected.fromIndex, actual.fromIndex) - assertEquals(expected.maxItems, actual.maxItems) - assertEquals(expected.sortField, actual.sortField) - assertEquals(expected.sortOrder, actual.sortOrder) - assertEquals(expected.filterParams, actual.filterParams) - } - - @Test - fun `Get request serialize and deserialize transport object should be equal`() { - val configRequest = GetNotificationEventRequest( - setOf("sample_event_id"), - 0, - 10, - "sortField", - SortOrder.DESC, - mapOf(Pair("filterKey", "filterValue")) - ) - val recreatedObject = recreateObject(configRequest) { GetNotificationEventRequest(it) } - assertGetRequestEquals(configRequest, recreatedObject) - } - - @Test - fun `Get request serialize and deserialize using json object should be equal`() { - val configRequest = GetNotificationEventRequest( - setOf("sample_event_id"), - 0, - 10, - "sortField", - SortOrder.ASC, - mapOf(Pair("filterKey", "filterValue")) - ) - val jsonString = getJsonString(configRequest) - val recreatedObject = createObjectFromJsonString(jsonString) { GetNotificationEventRequest.parse(it) } - assertGetRequestEquals(configRequest, recreatedObject) - } - - @Test - fun `Get request with all field should deserialize json object using parser`() { - val configRequest = GetNotificationEventRequest( - setOf("sample_event_id"), - 10, - 100, - "sortField", - SortOrder.DESC, - mapOf( - Pair("filterKey1", "filterValue1"), - Pair("filterKey2", "true"), - Pair("filterKey3", "filter,Value,3"), - Pair("filterKey4", "4") - ) - ) - val jsonString = """ - { - "event_id_list":["${configRequest.eventIds.first()}"], - "from_index":"10", - "max_items":"100", - "sort_field":"sortField", - "sort_order":"desc", - "filter_param_list": { - "filterKey1":"filterValue1", - "filterKey2":"true", - "filterKey3":"filter,Value,3", - "filterKey4":"4" - } - } - """.trimIndent() - val recreatedObject = createObjectFromJsonString(jsonString) { GetNotificationEventRequest.parse(it) } - assertGetRequestEquals(configRequest, recreatedObject) - } - - @Test - fun `Get request with only event_id field should deserialize json object using parser`() { - val configRequest = GetNotificationEventRequest(eventIds = setOf("sample_event_id")) - val jsonString = """ - { - "event_id_list":["${configRequest.eventIds.first()}"] - } - """.trimIndent() - val recreatedObject = createObjectFromJsonString(jsonString) { GetNotificationEventRequest.parse(it) } - assertGetRequestEquals(configRequest, recreatedObject) - } - - @Test - fun `Get request with only from_index field should deserialize json object using parser`() { - val configRequest = GetNotificationEventRequest(fromIndex = 20) - val jsonString = """ - { - "from_index":"20" - } - """.trimIndent() - val recreatedObject = createObjectFromJsonString(jsonString) { GetNotificationEventRequest.parse(it) } - assertGetRequestEquals(configRequest, recreatedObject) - } - - @Test - fun `Get request with only max_items field should deserialize json object using parser`() { - val configRequest = GetNotificationEventRequest(maxItems = 100) - val jsonString = """ - { - "max_items":"100" - } - """.trimIndent() - val recreatedObject = createObjectFromJsonString(jsonString) { GetNotificationEventRequest.parse(it) } - assertGetRequestEquals(configRequest, recreatedObject) - } - - @Test - fun `Get request with only sort_field field should deserialize json object using parser`() { - val configRequest = GetNotificationEventRequest(sortField = "sample_sort_field") - val jsonString = """ - { - "sort_field":"sample_sort_field" - } - """.trimIndent() - val recreatedObject = createObjectFromJsonString(jsonString) { GetNotificationEventRequest.parse(it) } - assertGetRequestEquals(configRequest, recreatedObject) - } - - @Test - fun `Get request with only sort_order=asc field should deserialize json object using parser`() { - val configRequest = GetNotificationEventRequest(sortOrder = SortOrder.ASC) - val jsonString = """ - { - "sort_order":"asc" - } - """.trimIndent() - val recreatedObject = createObjectFromJsonString(jsonString) { GetNotificationEventRequest.parse(it) } - assertGetRequestEquals(configRequest, recreatedObject) - } - - @Test - fun `Get request with only sort_order=ASC field should deserialize json object using parser`() { - val configRequest = GetNotificationEventRequest(sortOrder = SortOrder.ASC) - val jsonString = """ - { - "sort_order":"ASC" - } - """.trimIndent() - val recreatedObject = createObjectFromJsonString(jsonString) { GetNotificationEventRequest.parse(it) } - assertGetRequestEquals(configRequest, recreatedObject) - } - - @Test - fun `Get request with only sort_order=desc field should deserialize json object using parser`() { - val configRequest = GetNotificationEventRequest(sortOrder = SortOrder.DESC) - val jsonString = """ - { - "sort_order":"desc" - } - """.trimIndent() - val recreatedObject = createObjectFromJsonString(jsonString) { GetNotificationEventRequest.parse(it) } - assertGetRequestEquals(configRequest, recreatedObject) - } - - @Test - fun `Get request with only sort_order=DESC field should deserialize json object using parser`() { - val configRequest = GetNotificationEventRequest(sortOrder = SortOrder.DESC) - val jsonString = """ - { - "sort_order":"DESC" - } - """.trimIndent() - val recreatedObject = createObjectFromJsonString(jsonString) { GetNotificationEventRequest.parse(it) } - assertGetRequestEquals(configRequest, recreatedObject) - } - - @Test - fun `Get request with invalid sort_order should throw exception`() { - val jsonString = """ - { - "sort_order":"descending" - } - """.trimIndent() - assertThrows { - createObjectFromJsonString(jsonString) { GetNotificationEventRequest.parse(it) } - } - } - - @Test - fun `Get request with only filter_param_list field should deserialize json object using parser`() { - val configRequest = GetNotificationEventRequest( - filterParams = mapOf( - Pair("filterKey1", "filterValue1"), - Pair("filterKey2", "true"), - Pair("filterKey3", "filter,Value,3"), - Pair("filterKey4", "4") - ) - ) - val jsonString = """ - { - "filter_param_list": { - "filterKey1":"filterValue1", - "filterKey2":"true", - "filterKey3":"filter,Value,3", - "filterKey4":"4" - } - } - """.trimIndent() - val recreatedObject = createObjectFromJsonString(jsonString) { GetNotificationEventRequest.parse(it) } - assertGetRequestEquals(configRequest, recreatedObject) - } - - @Test - fun `Get request no field should deserialize json object using parser`() { - val configRequest = GetNotificationEventRequest() - val jsonString = """ - { - } - """.trimIndent() - val recreatedObject = createObjectFromJsonString(jsonString) { GetNotificationEventRequest.parse(it) } - assertGetRequestEquals(configRequest, recreatedObject) - } - - @Test - fun `Get request should throw exception when invalid json object is passed`() { - val jsonString = "sample message" - assertThrows { - createObjectFromJsonString(jsonString) { GetNotificationEventRequest.parse(it) } - } - } - - @Test - fun `Get request should safely ignore extra field in json object`() { - val configRequest = GetNotificationEventRequest(eventIds = setOf("sample_event_id")) - val jsonString = """ - { - "event_id_list":["${configRequest.eventIds.first()}"], - "extra_field_1":["extra", "value"], - "extra_field_2":{"extra":"value"}, - "extra_field_3":"extra value 3" - } - """.trimIndent() - val recreatedObject = createObjectFromJsonString(jsonString) { GetNotificationEventRequest.parse(it) } - assertGetRequestEquals(configRequest, recreatedObject) - } -} diff --git a/src/test/kotlin/org/opensearch/commons/notifications/action/GetNotificationEventResponseTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/action/GetNotificationEventResponseTests.kt deleted file mode 100644 index 0de1c78b..00000000 --- a/src/test/kotlin/org/opensearch/commons/notifications/action/GetNotificationEventResponseTests.kt +++ /dev/null @@ -1,345 +0,0 @@ -/* - * Copyright OpenSearch Contributors - * SPDX-License-Identifier: Apache-2.0 - */ -package org.opensearch.commons.notifications.action - -import org.apache.lucene.search.TotalHits -import org.junit.jupiter.api.Assertions -import org.junit.jupiter.api.Assertions.assertEquals -import org.junit.jupiter.api.Test -import org.opensearch.commons.notifications.model.ConfigType -import org.opensearch.commons.notifications.model.DeliveryStatus -import org.opensearch.commons.notifications.model.EventSource -import org.opensearch.commons.notifications.model.EventStatus -import org.opensearch.commons.notifications.model.NotificationEvent -import org.opensearch.commons.notifications.model.NotificationEventInfo -import org.opensearch.commons.notifications.model.NotificationEventSearchResult -import org.opensearch.commons.notifications.model.SeverityType -import org.opensearch.commons.utils.createObjectFromJsonString -import org.opensearch.commons.utils.getJsonString -import org.opensearch.commons.utils.recreateObject -import java.time.Instant - -internal class GetNotificationEventResponseTests { - - private fun assertSearchResultEquals( - expected: NotificationEventSearchResult, - actual: NotificationEventSearchResult - ) { - assertEquals(expected.startIndex, actual.startIndex) - assertEquals(expected.totalHits, actual.totalHits) - assertEquals(expected.totalHitRelation, actual.totalHitRelation) - assertEquals(expected.objectListFieldName, actual.objectListFieldName) - assertEquals(expected.objectList, actual.objectList) - } - - @Test - fun `Search result serialize and deserialize with event object should be equal`() { - val sampleEventSource = EventSource( - "title", - "reference_id", - severity = SeverityType.INFO - ) - val sampleStatus = EventStatus( - "config_id", - "name", - ConfigType.SLACK, - deliveryStatus = DeliveryStatus("404", "invalid recipient") - ) - val sampleEvent = NotificationEvent(sampleEventSource, listOf(sampleStatus)) - val eventInfo = NotificationEventInfo( - "event_id", - Instant.now(), - Instant.now(), - sampleEvent - ) - val searchResult = NotificationEventSearchResult(eventInfo) - val searchResponse = GetNotificationEventResponse(searchResult) - val recreatedObject = recreateObject(searchResponse) { GetNotificationEventResponse(it) } - assertSearchResultEquals(searchResult, recreatedObject.searchResult) - } - - @Test - fun `Search result serialize and deserialize with multiple event status object should be equal`() { - val eventSource1 = EventSource( - "title 1", - "reference_id_1", - severity = SeverityType.INFO - ) - val eventSource2 = EventSource( - "title 2", - "reference_id_2", - severity = SeverityType.HIGH - ) - val status1 = EventStatus( - "config_id1", - "name", - ConfigType.SLACK, - deliveryStatus = DeliveryStatus("200", "success") - ) - val status2 = EventStatus( - "config_id2", - "name", - ConfigType.CHIME, - deliveryStatus = DeliveryStatus("404", "invalid recipient") - ) - val eventInfo1 = NotificationEventInfo( - "event_id1", - Instant.now(), - Instant.now(), - NotificationEvent(eventSource1, listOf(status1)) - ) - val eventInfo2 = NotificationEventInfo( - "event_id2", - Instant.now(), - Instant.now(), - NotificationEvent(eventSource2, listOf(status2)) - ) - val eventInfo3 = NotificationEventInfo( - "event_id3", - Instant.now(), - Instant.now(), - NotificationEvent(eventSource1, listOf(status1, status2)) - ) - val eventInfo4 = NotificationEventInfo( - "event_id4", - Instant.now(), - Instant.now(), - NotificationEvent(eventSource2, listOf(status1, status2)) - ) - val searchResult = NotificationEventSearchResult( - 100, - 1000, - TotalHits.Relation.GREATER_THAN_OR_EQUAL_TO, - listOf(eventInfo1, eventInfo2, eventInfo3, eventInfo4) - ) - val searchResponse = GetNotificationEventResponse(searchResult) - val recreatedObject = recreateObject(searchResponse) { GetNotificationEventResponse(it) } - assertSearchResultEquals(searchResult, recreatedObject.searchResult) - } - - @Test - fun `Search result serialize and deserialize using json event object should be equal`() { - val lastUpdatedTimeMs = Instant.ofEpochMilli(Instant.now().toEpochMilli()) - val createdTimeMs = lastUpdatedTimeMs.minusSeconds(1000) - val sampleEventSource = EventSource( - "title", - "reference_id", - severity = SeverityType.INFO - ) - val sampleStatus = EventStatus( - "config_id", - "name", - ConfigType.SLACK, - deliveryStatus = DeliveryStatus("404", "invalid recipient") - ) - val sampleEvent = NotificationEvent(sampleEventSource, listOf(sampleStatus)) - val eventInfo = NotificationEventInfo( - "event_id", - lastUpdatedTimeMs, - createdTimeMs, - sampleEvent - ) - val searchResult = NotificationEventSearchResult(eventInfo) - val searchResponse = GetNotificationEventResponse(searchResult) - val jsonString = getJsonString(searchResponse) - val recreatedObject = createObjectFromJsonString(jsonString) { GetNotificationEventResponse.parse(it) } - assertSearchResultEquals(searchResult, recreatedObject.searchResult) - } - - @Test - fun `Search result serialize and deserialize using json with multiple event object should be equal`() { - val lastUpdatedTimeMs = Instant.ofEpochMilli(Instant.now().toEpochMilli()) - val createdTimeMs = lastUpdatedTimeMs.minusSeconds(1000) - val eventSource1 = EventSource( - "title 1", - "reference_id_1", - severity = SeverityType.INFO - ) - val eventSource2 = EventSource( - "title 2", - "reference_id_2", - severity = SeverityType.HIGH - ) - val status1 = EventStatus( - "config_id1", - "name", - ConfigType.SLACK, - deliveryStatus = DeliveryStatus("200", "success") - ) - val status2 = EventStatus( - "config_id2", - "name", - ConfigType.CHIME, - deliveryStatus = DeliveryStatus("404", "invalid recipient") - ) - val eventInfo1 = NotificationEventInfo( - "event_id1", - lastUpdatedTimeMs, - createdTimeMs, - NotificationEvent(eventSource1, listOf(status1)) - ) - val eventInfo2 = NotificationEventInfo( - "event_id2", - lastUpdatedTimeMs, - createdTimeMs, - NotificationEvent(eventSource2, listOf(status2)) - ) - val searchResult = NotificationEventSearchResult( - 100, - 1000, - TotalHits.Relation.GREATER_THAN_OR_EQUAL_TO, - listOf(eventInfo1, eventInfo2) - ) - val searchResponse = GetNotificationEventResponse(searchResult) - val jsonString = getJsonString(searchResponse) - val recreatedObject = createObjectFromJsonString(jsonString) { GetNotificationEventResponse.parse(it) } - assertSearchResultEquals(searchResult, recreatedObject.searchResult) - } - - @Test - fun `Search result should safely ignore extra field in json object`() { - val lastUpdatedTimeMs = Instant.ofEpochMilli(Instant.now().toEpochMilli()) - val createdTimeMs = lastUpdatedTimeMs.minusSeconds(1000) - val sampleEventSource = EventSource( - "title", - "reference_id", - severity = SeverityType.INFO - ) - val sampleStatus = EventStatus( - "config_id", - "name", - ConfigType.SLACK, - deliveryStatus = DeliveryStatus("200", "success") - ) - val sampleEvent = NotificationEvent(sampleEventSource, listOf(sampleStatus)) - val eventInfo = NotificationEventInfo( - "event_id", - lastUpdatedTimeMs, - createdTimeMs, - sampleEvent - ) - val searchResult = NotificationEventSearchResult(eventInfo) - val jsonString = """ - { - "start_index":"0", - "total_hits":"1", - "total_hit_relation":"eq", - "event_list":[ - { - "event_id":"event_id", - "last_updated_time_ms":"${lastUpdatedTimeMs.toEpochMilli()}", - "created_time_ms":"${createdTimeMs.toEpochMilli()}", - "event":{ - "event_source":{ - "title":"title", - "reference_id":"reference_id", - "severity":"info", - "tags":[] - }, - "status_list":[ - { - "config_id":"config_id", - "config_type":"slack", - "config_name":"name", - "delivery_status": - { - "status_code":"200", - "status_text":"success" - } - } - ] - } - } - ], - "extra_field_1":["extra", "value"], - "extra_field_2":{"extra":"value"}, - "extra_field_3":"extra value 3" - } - """.trimIndent() - val recreatedObject = createObjectFromJsonString(jsonString) { GetNotificationEventResponse.parse(it) } - assertSearchResultEquals(searchResult, recreatedObject.searchResult) - } - - @Test - fun `Search result should safely fallback to default if startIndex, totalHits or totalHitRelation field absent in json object`() { - val lastUpdatedTimeMs = Instant.ofEpochMilli(Instant.now().toEpochMilli()) - val createdTimeMs = lastUpdatedTimeMs.minusSeconds(1000) - val sampleEventSource = EventSource( - "title", - "reference_id", - severity = SeverityType.INFO - ) - val sampleStatus = EventStatus( - "config_id", - "name", - ConfigType.SLACK, - deliveryStatus = DeliveryStatus("200", "success") - ) - val sampleEvent = NotificationEvent(sampleEventSource, listOf(sampleStatus)) - val eventInfo = NotificationEventInfo( - "event_id", - lastUpdatedTimeMs, - createdTimeMs, - sampleEvent - ) - val searchResult = NotificationEventSearchResult(eventInfo) - val jsonString = """ - { - "event_list":[ - { - "event_id":"event_id", - "last_updated_time_ms":"${lastUpdatedTimeMs.toEpochMilli()}", - "created_time_ms":"${createdTimeMs.toEpochMilli()}", - "event":{ - "event_source":{ - "title":"title", - "reference_id":"reference_id", - "severity":"info", - "tags":[] - }, - "status_list":[ - { - "config_id":"config_id", - "config_type":"slack", - "config_name":"name", - "delivery_status": - { - "status_code":"200", - "status_text":"success" - } - } - ] - } - } - ] - } - """.trimIndent() - val recreatedObject = createObjectFromJsonString(jsonString) { GetNotificationEventResponse.parse(it) } - assertSearchResultEquals(searchResult, recreatedObject.searchResult) - } - - @Test - fun `Search result should throw exception if event is absent in json`() { - val lastUpdatedTimeMs = Instant.ofEpochMilli(Instant.now().toEpochMilli()) - val createdTimeMs = lastUpdatedTimeMs.minusSeconds(1000) - val jsonString = """ - { - "start_index":"0", - "total_hits":"1", - "total_hit_relation":"eq", - "event_list":[ - { - "event_id":"event_id", - "last_updated_time_ms":"${lastUpdatedTimeMs.toEpochMilli()}", - "created_time_ms":"${createdTimeMs.toEpochMilli()}" - } - ] - } - """.trimIndent() - Assertions.assertThrows(IllegalArgumentException::class.java) { - createObjectFromJsonString(jsonString) { GetNotificationEventResponse.parse(it) } - } - } -} diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationEventInfoTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationEventInfoTests.kt deleted file mode 100644 index 85d2dee9..00000000 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationEventInfoTests.kt +++ /dev/null @@ -1,273 +0,0 @@ -/* - * Copyright OpenSearch Contributors - * SPDX-License-Identifier: Apache-2.0 - */ -package org.opensearch.commons.notifications.model - -import org.junit.jupiter.api.Assertions -import org.junit.jupiter.api.Assertions.assertEquals -import org.junit.jupiter.api.Test -import org.opensearch.commons.utils.createObjectFromJsonString -import org.opensearch.commons.utils.getJsonString -import org.opensearch.commons.utils.recreateObject -import java.time.Instant - -internal class NotificationEventInfoTests { - - @Test - fun `Event info serialize and deserialize with event object should be equal`() { - val sampleEventSource = EventSource( - "title", - "reference_id", - severity = SeverityType.INFO - ) - val sampleStatus = EventStatus( - "config_id", - "name", - ConfigType.SLACK, - deliveryStatus = DeliveryStatus("404", "invalid recipient") - ) - val sampleEvent = NotificationEvent(sampleEventSource, listOf(sampleStatus)) - val eventInfo = NotificationEventInfo( - "event_id", - Instant.now(), - Instant.now(), - sampleEvent - ) - val recreatedObject = recreateObject(eventInfo) { NotificationEventInfo(it) } - assertEquals(eventInfo, recreatedObject) - } - - @Test - fun `Event info serialize and deserialize using json event object should be equal`() { - val lastUpdatedTimeMs = Instant.ofEpochMilli(Instant.now().toEpochMilli()) - val createdTimeMs = lastUpdatedTimeMs.minusSeconds(1000) - val sampleEventSource = EventSource( - "title", - "reference_id", - severity = SeverityType.INFO - ) - val sampleStatus = EventStatus( - "config_id", - "name", - ConfigType.SLACK, - deliveryStatus = DeliveryStatus("200", "success") - ) - val sampleEvent = NotificationEvent(sampleEventSource, listOf(sampleStatus)) - val eventInfo = NotificationEventInfo( - "event_id", - lastUpdatedTimeMs, - createdTimeMs, - sampleEvent - ) - val jsonString = getJsonString(eventInfo) - val recreatedObject = createObjectFromJsonString(jsonString) { NotificationEventInfo.parse(it) } - assertEquals(eventInfo, recreatedObject) - } - - @Test - fun `Event info should safely ignore extra field in json object`() { - val lastUpdatedTimeMs = Instant.ofEpochMilli(Instant.now().toEpochMilli()) - val createdTimeMs = lastUpdatedTimeMs.minusSeconds(1000) - val sampleEventSource = EventSource( - "title", - "reference_id", - severity = SeverityType.INFO - ) - val sampleStatus = EventStatus( - "config_id", - "name", - ConfigType.SLACK, - deliveryStatus = DeliveryStatus("200", "success") - ) - val sampleEvent = NotificationEvent(sampleEventSource, listOf(sampleStatus)) - val eventInfo = NotificationEventInfo( - "event_id", - lastUpdatedTimeMs, - createdTimeMs, - sampleEvent - ) - val jsonString = """ - { - "event_id":"event_id", - "last_updated_time_ms":"${lastUpdatedTimeMs.toEpochMilli()}", - "created_time_ms":"${createdTimeMs.toEpochMilli()}", - "event":{ - "event_source":{ - "title":"title", - "reference_id":"reference_id", - "feature":"alerting", - "severity":"info", - "tags":[] - }, - "status_list":[ - { - "config_id":"config_id", - "config_type":"slack", - "config_name":"name", - "delivery_status": - { - "status_code":"200", - "status_text":"success" - } - } - ] - }, - "extra_field_1":["extra", "value"], - "extra_field_2":{"extra":"value"}, - "extra_field_3":"extra value 3" - } - """.trimIndent() - val recreatedObject = createObjectFromJsonString(jsonString) { NotificationEventInfo.parse(it) } - assertEquals(eventInfo, recreatedObject) - } - - @Test - fun `Event info should throw exception if event_id is empty`() { - val lastUpdatedTimeMs = Instant.ofEpochMilli(Instant.now().toEpochMilli()) - val createdTimeMs = lastUpdatedTimeMs.minusSeconds(1000) - val sampleEventSource = EventSource( - "title", - "reference_id", - severity = SeverityType.INFO - ) - val sampleStatus = EventStatus( - "event_id", - "name", - ConfigType.SLACK, - deliveryStatus = DeliveryStatus("200", "success") - ) - val sampleEvent = NotificationEvent(sampleEventSource, listOf(sampleStatus)) - Assertions.assertThrows(IllegalArgumentException::class.java) { - NotificationEventInfo( - "", - lastUpdatedTimeMs, - createdTimeMs, - sampleEvent - ) - } - } - - @Test - fun `Event info should throw exception if event_id is absent in json`() { - val lastUpdatedTimeMs = Instant.ofEpochMilli(Instant.now().toEpochMilli()) - val createdTimeMs = lastUpdatedTimeMs.minusSeconds(1000) - val jsonString = """ - { - "last_updated_time_ms":"${lastUpdatedTimeMs.toEpochMilli()}", - "created_time_ms":"${createdTimeMs.toEpochMilli()}", - "event":{ - "event_source":{ - "title":"title", - "reference_id":"reference_id", - "feature":"alerting", - "severity":"info", - "tags":["tag1", "tag2"] - }, - "status_list":[ - { - "event_id":"event_id", - "config_type":"slack", - "config_name":"name", - "delivery_status": - { - "status_code":"200", - "status_text":"success" - } - } - ] - } - } - """.trimIndent() - Assertions.assertThrows(IllegalArgumentException::class.java) { - createObjectFromJsonString(jsonString) { NotificationEventInfo.parse(it) } - } - } - - @Test - fun `Event info should throw exception if lastUpdatedTimeMs is absent in json`() { - val lastUpdatedTimeMs = Instant.ofEpochMilli(Instant.now().toEpochMilli()) - val createdTimeMs = lastUpdatedTimeMs.minusSeconds(1000) - val jsonString = """ - { - "event_id":"event_id", - "created_time_ms":"${createdTimeMs.toEpochMilli()}", - "event":{ - "event_source":{ - "title":"title", - "reference_id":"reference_id", - "feature":"alerting", - "severity":"info", - "tags":["tag1", "tag2"] - }, - "status_list":[ - { - "event_id":"event_id", - "config_type":"slack", - "config_name":"name", - "delivery_status": - { - "status_code":"200", - "status_text":"success" - } - } - ] - } - } - """.trimIndent() - Assertions.assertThrows(IllegalArgumentException::class.java) { - createObjectFromJsonString(jsonString) { NotificationEventInfo.parse(it) } - } - } - - @Test - fun `Event info should throw exception if createdTimeMs is absent in json`() { - val lastUpdatedTimeMs = Instant.ofEpochMilli(Instant.now().toEpochMilli()) - val jsonString = """ - { - "event_id":"event_id", - "last_updated_time_ms":"${lastUpdatedTimeMs.toEpochMilli()}", - "event":{ - "event_source":{ - "title":"title", - "reference_id":"reference_id", - "feature":"alerting", - "severity":"info", - "tags":["tag1", "tag2"] - }, - "status_list":[ - { - "event_id":"event_id", - "config_type":"slack", - "config_name":"name", - "delivery_status": - { - "status_code":"200", - "status_text":"success" - } - } - ] - } - } - """.trimIndent() - Assertions.assertThrows(IllegalArgumentException::class.java) { - createObjectFromJsonString(jsonString) { NotificationEventInfo.parse(it) } - } - } - - @Test - fun `Event info should throw exception if event is absent in json`() { - val lastUpdatedTimeMs = Instant.ofEpochMilli(Instant.now().toEpochMilli()) - val createdTimeMs = lastUpdatedTimeMs.minusSeconds(1000) - val jsonString = """ - { - "event_id":"event_id", - "last_updated_time_ms":"${lastUpdatedTimeMs.toEpochMilli()}", - "created_time_ms":"${createdTimeMs.toEpochMilli()}" - } - """.trimIndent() - Assertions.assertThrows(IllegalArgumentException::class.java) { - createObjectFromJsonString(jsonString) { NotificationEventInfo.parse(it) } - } - } -} diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationEventSearchResultTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationEventSearchResultTests.kt deleted file mode 100644 index b65a0783..00000000 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationEventSearchResultTests.kt +++ /dev/null @@ -1,396 +0,0 @@ -/* - * Copyright OpenSearch Contributors - * SPDX-License-Identifier: Apache-2.0 - */ -package org.opensearch.commons.notifications.model - -import org.apache.lucene.search.TotalHits -import org.junit.jupiter.api.Assertions -import org.junit.jupiter.api.Assertions.assertEquals -import org.junit.jupiter.api.Test -import org.opensearch.commons.utils.createObjectFromJsonString -import org.opensearch.commons.utils.getJsonString -import org.opensearch.commons.utils.recreateObject -import java.time.Instant - -internal class NotificationEventSearchResultTests { - - private fun assertSearchResultEquals( - expected: NotificationEventSearchResult, - actual: NotificationEventSearchResult - ) { - assertEquals(expected.startIndex, actual.startIndex) - assertEquals(expected.totalHits, actual.totalHits) - assertEquals(expected.totalHitRelation, actual.totalHitRelation) - assertEquals(expected.objectListFieldName, actual.objectListFieldName) - assertEquals(expected.objectList, actual.objectList) - } - - @Test - fun `Search result serialize and deserialize with event object should be equal`() { - val sampleEventSource = EventSource( - "title", - "reference_id", - severity = SeverityType.INFO - ) - val sampleStatus = EventStatus( - "config_id", - "name", - ConfigType.SLACK, - deliveryStatus = DeliveryStatus("404", "invalid recipient") - ) - val sampleEvent = NotificationEvent(sampleEventSource, listOf(sampleStatus)) - val eventInfo = NotificationEventInfo( - "event_id", - Instant.now(), - Instant.now(), - sampleEvent - ) - val searchResult = NotificationEventSearchResult(eventInfo) - val recreatedObject = recreateObject(searchResult) { NotificationEventSearchResult(it) } - assertSearchResultEquals(searchResult, recreatedObject) - } - - @Test - fun `Search result serialize and deserialize with multiple event default values should be equal`() { - val eventSource1 = EventSource( - "title 1", - "reference_id_1", - severity = SeverityType.INFO - ) - val eventSource2 = EventSource( - "title 2", - "reference_id_2", - severity = SeverityType.HIGH - ) - val status1 = EventStatus( - "config_id1", - "name", - ConfigType.SLACK, - deliveryStatus = DeliveryStatus("200", "success") - ) - val status2 = EventStatus( - "config_id2", - "name", - ConfigType.CHIME, - deliveryStatus = DeliveryStatus("404", "invalid recipient") - ) - val eventInfo1 = NotificationEventInfo( - "event_id1", - Instant.now(), - Instant.now(), - NotificationEvent(eventSource1, listOf(status1)) - ) - val eventInfo2 = NotificationEventInfo( - "event_id2", - Instant.now(), - Instant.now(), - NotificationEvent(eventSource2, listOf(status2)) - ) - val eventInfo3 = NotificationEventInfo( - "event_id3", - Instant.now(), - Instant.now(), - NotificationEvent(eventSource1, listOf(status1, status2)) - ) - val eventInfo4 = NotificationEventInfo( - "event_id4", - Instant.now(), - Instant.now(), - NotificationEvent(eventSource2, listOf(status1, status2)) - ) - val searchResult = NotificationEventSearchResult( - listOf(eventInfo1, eventInfo2, eventInfo3, eventInfo4) - ) - val expectedResult = NotificationEventSearchResult( - 0, - 4, - TotalHits.Relation.EQUAL_TO, - listOf(eventInfo1, eventInfo2, eventInfo3, eventInfo4) - ) - val recreatedObject = recreateObject(searchResult) { NotificationEventSearchResult(it) } - assertSearchResultEquals(expectedResult, recreatedObject) - } - - @Test - fun `Search result serialize and deserialize with multiple event status object should be equal`() { - val eventSource1 = EventSource( - "title 1", - "reference_id_1", - severity = SeverityType.INFO - ) - val eventSource2 = EventSource( - "title 2", - "reference_id_2", - severity = SeverityType.HIGH - ) - val status1 = EventStatus( - "config_id1", - "name", - ConfigType.SLACK, - deliveryStatus = DeliveryStatus("200", "success") - ) - val status2 = EventStatus( - "config_id2", - "name", - ConfigType.CHIME, - deliveryStatus = DeliveryStatus("404", "invalid recipient") - ) - val eventInfo1 = NotificationEventInfo( - "event_id1", - Instant.now(), - Instant.now(), - NotificationEvent(eventSource1, listOf(status1)) - ) - val eventInfo2 = NotificationEventInfo( - "event_id2", - Instant.now(), - Instant.now(), - NotificationEvent(eventSource2, listOf(status2)) - ) - val eventInfo3 = NotificationEventInfo( - "event_id3", - Instant.now(), - Instant.now(), - NotificationEvent(eventSource1, listOf(status1, status2)) - ) - val eventInfo4 = NotificationEventInfo( - "event_id4", - Instant.now(), - Instant.now(), - NotificationEvent(eventSource2, listOf(status1, status2)) - ) - val searchResult = NotificationEventSearchResult( - 100, - 1000, - TotalHits.Relation.GREATER_THAN_OR_EQUAL_TO, - listOf(eventInfo1, eventInfo2, eventInfo3, eventInfo4) - ) - val recreatedObject = recreateObject(searchResult) { NotificationEventSearchResult(it) } - assertSearchResultEquals(searchResult, recreatedObject) - } - - @Test - fun `Search result serialize and deserialize using json event object should be equal`() { - val lastUpdatedTimeMs = Instant.ofEpochMilli(Instant.now().toEpochMilli()) - val createdTimeMs = lastUpdatedTimeMs.minusSeconds(1000) - val sampleEventSource = EventSource( - "title", - "reference_id", - severity = SeverityType.INFO - ) - val sampleStatus = EventStatus( - "config_id", - "name", - ConfigType.SLACK, - deliveryStatus = DeliveryStatus("404", "invalid recipient") - ) - val sampleEvent = NotificationEvent(sampleEventSource, listOf(sampleStatus)) - val eventInfo = NotificationEventInfo( - "event_id", - lastUpdatedTimeMs, - createdTimeMs, - sampleEvent - ) - val searchResult = NotificationEventSearchResult(eventInfo) - val jsonString = getJsonString(searchResult) - val recreatedObject = createObjectFromJsonString(jsonString) { NotificationEventSearchResult(it) } - assertSearchResultEquals(searchResult, recreatedObject) - } - - @Test - fun `Search result serialize and deserialize using json with multiple event object should be equal`() { - val lastUpdatedTimeMs = Instant.ofEpochMilli(Instant.now().toEpochMilli()) - val createdTimeMs = lastUpdatedTimeMs.minusSeconds(1000) - val eventSource1 = EventSource( - "title 1", - "reference_id_1", - severity = SeverityType.INFO - ) - val eventSource2 = EventSource( - "title 2", - "reference_id_2", - severity = SeverityType.HIGH - ) - val status1 = EventStatus( - "config_id1", - "name", - ConfigType.SLACK, - deliveryStatus = DeliveryStatus("200", "success") - ) - val status2 = EventStatus( - "config_id2", - "name", - ConfigType.CHIME, - deliveryStatus = DeliveryStatus("404", "invalid recipient") - ) - val eventInfo1 = NotificationEventInfo( - "event_id1", - lastUpdatedTimeMs, - createdTimeMs, - NotificationEvent(eventSource1, listOf(status1)) - ) - val eventInfo2 = NotificationEventInfo( - "event_id2", - lastUpdatedTimeMs, - createdTimeMs, - NotificationEvent(eventSource2, listOf(status2)) - ) - val searchResult = NotificationEventSearchResult( - 100, - 1000, - TotalHits.Relation.GREATER_THAN_OR_EQUAL_TO, - listOf(eventInfo1, eventInfo2) - ) - val jsonString = getJsonString(searchResult) - val recreatedObject = createObjectFromJsonString(jsonString) { NotificationEventSearchResult(it) } - assertSearchResultEquals(searchResult, recreatedObject) - } - - @Test - fun `Search result should safely ignore extra field in json object`() { - val lastUpdatedTimeMs = Instant.ofEpochMilli(Instant.now().toEpochMilli()) - val createdTimeMs = lastUpdatedTimeMs.minusSeconds(1000) - val sampleEventSource = EventSource( - "title", - "reference_id", - severity = SeverityType.INFO - ) - val sampleStatus = EventStatus( - "config_id", - "name", - ConfigType.SLACK, - deliveryStatus = DeliveryStatus("200", "success") - ) - val sampleEvent = NotificationEvent(sampleEventSource, listOf(sampleStatus)) - val eventInfo = NotificationEventInfo( - "event_id", - lastUpdatedTimeMs, - createdTimeMs, - sampleEvent - ) - val searchResult = NotificationEventSearchResult(eventInfo) - val jsonString = """ - { - "start_index":"0", - "total_hits":"1", - "total_hit_relation":"eq", - "event_list":[ - { - "event_id":"event_id", - "last_updated_time_ms":"${lastUpdatedTimeMs.toEpochMilli()}", - "created_time_ms":"${createdTimeMs.toEpochMilli()}", - "event":{ - "event_source":{ - "title":"title", - "reference_id":"reference_id", - "feature":"alerting", - "severity":"info", - "tags":[] - }, - "status_list":[ - { - "config_id":"config_id", - "config_type":"slack", - "config_name":"name", - "delivery_status": - { - "status_code":"200", - "status_text":"success" - } - } - ] - } - } - ], - "extra_field_1":["extra", "value"], - "extra_field_2":{"extra":"value"}, - "extra_field_3":"extra value 3" - } - """.trimIndent() - val recreatedObject = createObjectFromJsonString(jsonString) { NotificationEventSearchResult(it) } - assertSearchResultEquals(searchResult, recreatedObject) - } - - @Test - fun `Search result should safely fallback to default if startIndex, totalHits or totalHitRelation field absent in json object`() { - val lastUpdatedTimeMs = Instant.ofEpochMilli(Instant.now().toEpochMilli()) - val createdTimeMs = lastUpdatedTimeMs.minusSeconds(1000) - val sampleEventSource = EventSource( - "title", - "reference_id", - severity = SeverityType.INFO - ) - val sampleStatus = EventStatus( - "config_id", - "name", - ConfigType.SLACK, - deliveryStatus = DeliveryStatus("200", "success") - ) - val sampleEvent = NotificationEvent(sampleEventSource, listOf(sampleStatus)) - val eventInfo = NotificationEventInfo( - "event_id", - lastUpdatedTimeMs, - createdTimeMs, - sampleEvent - ) - val searchResult = NotificationEventSearchResult(eventInfo) - val jsonString = """ - { - "event_list":[ - { - "event_id":"event_id", - "last_updated_time_ms":"${lastUpdatedTimeMs.toEpochMilli()}", - "created_time_ms":"${createdTimeMs.toEpochMilli()}", - "event":{ - "event_source":{ - "title":"title", - "reference_id":"reference_id", - "feature":"alerting", - "severity":"info", - "tags":[] - }, - "status_list":[ - { - "config_id":"config_id", - "config_type":"slack", - "config_name":"name", - "delivery_status": - { - "status_code":"200", - "status_text":"success" - } - } - ] - } - } - ] - } - """.trimIndent() - val recreatedObject = createObjectFromJsonString(jsonString) { NotificationEventSearchResult(it) } - assertSearchResultEquals(searchResult, recreatedObject) - } - - @Test - fun `Search result should throw exception if event is absent in json`() { - val lastUpdatedTimeMs = Instant.ofEpochMilli(Instant.now().toEpochMilli()) - val createdTimeMs = lastUpdatedTimeMs.minusSeconds(1000) - val jsonString = """ - { - "start_index":"0", - "total_hits":"1", - "total_hit_relation":"eq", - "event_list":[ - { - "event_id":"event_id", - "last_updated_time_ms":"${lastUpdatedTimeMs.toEpochMilli()}", - "created_time_ms":"${createdTimeMs.toEpochMilli()}" - } - ] - } - """.trimIndent() - Assertions.assertThrows(IllegalArgumentException::class.java) { - createObjectFromJsonString(jsonString) { NotificationEventSearchResult(it) } - } - } -} From 4553617bac3ec10ec9c8880b6efbad06fd972f9c Mon Sep 17 00:00:00 2001 From: "Daniel Doubrovkine (dB.)" Date: Wed, 6 Apr 2022 16:41:59 -0400 Subject: [PATCH 050/140] Updated issue templates from .github. (#154) Signed-off-by: dblock --- .github/ISSUE_TEMPLATE/bug_report.md | 28 +++++++++++------------ .github/ISSUE_TEMPLATE/config.yml | 7 ++++++ .github/ISSUE_TEMPLATE/feature_request.md | 17 +++++++------- 3 files changed, 28 insertions(+), 24 deletions(-) create mode 100644 .github/ISSUE_TEMPLATE/config.yml diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 8af6ebb5..29eddb95 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -1,33 +1,31 @@ --- name: 🐛 Bug report about: Create a report to help us improve -title: "[BUG]" -labels: 'bug, untriaged, Beta' +title: '[BUG]' +labels: 'bug, untriaged' assignees: '' --- -**Describe the bug** -A clear and concise description of what the bug is. +**What is the bug?** +A clear and concise description of the bug. -**To Reproduce** +**How can one reproduce the bug?** Steps to reproduce the behavior: 1. Go to '...' 2. Click on '....' 3. Scroll down to '....' 4. See error -**Expected behavior** +**What is the expected behavior?** A clear and concise description of what you expected to happen. -**Plugins** -Please list all plugins currently enabled. - -**Screenshots** -If applicable, add screenshots to help explain your problem. - -**Host/Environment (please complete the following information):** +**What is your host/environment?** - OS: [e.g. iOS] - Version [e.g. 22] + - Plugins + +**Do you have any screenshots?** +If applicable, add screenshots to help explain your problem. -**Additional context** -Add any other context about the problem here. \ No newline at end of file +**Do you have any additional context?** +Add any other context about the problem. diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 00000000..a8199a10 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,7 @@ +contact_links: + - name: OpenSearch Community Support + url: https://discuss.opendistrocommunity.dev/ + about: Please ask and answer questions here. + - name: AWS/Amazon Security + url: https://aws.amazon.com/security/vulnerability-reporting/ + about: Please report security vulnerabilities here. \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md index 2791b808..6198f338 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -1,19 +1,18 @@ --- name: 🎆 Feature request -about: Suggest an idea for this project -title: '' -labels: enhancement +about: Request a feature in this project +title: '[FEATURE]' +labels: 'enhancement, untriaged' assignees: '' --- +**Is your feature request related to a problem?** +A clear and concise description of what the problem is, e.g. _I'm always frustrated when [...]_ -**Is your feature request related to a problem? Please describe.** -A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] - -**Describe the solution you'd like** +**What solution would you like?** A clear and concise description of what you want to happen. -**Describe alternatives you've considered** +**What alternatives have you considered?** A clear and concise description of any alternative solutions or features you've considered. -**Additional context** +**Do you have any additional context?** Add any other context or screenshots about the feature request here. \ No newline at end of file From c3794c4768669d649f7a185163be7b85c6593c3c Mon Sep 17 00:00:00 2001 From: Aditya Jindal <13850971+aditjind@users.noreply.github.com> Date: Thu, 7 Apr 2022 15:51:50 -0700 Subject: [PATCH 051/140] Addition of NotificationEvent to SendNotificationResponse and Removal of NotificationID (#156) * Removal of NotificationEvent Request, Response , Search Results Addition of NotificationEventDoc and Removal of NotificationEventInfo Addition of NotificationEventDocTests Signed-off-by: Jindal * Removing NotificationEventDoc and NotificationEventDocTests Signed-off-by: Jindal Co-authored-by: Jindal --- .../action/SendNotificationResponse.kt | 43 ++++----------- .../NotificationsPluginInterfaceTests.kt | 14 ++++- .../action/SendNotificationResponseTests.kt | 52 ++++++++++++++----- 3 files changed, 61 insertions(+), 48 deletions(-) diff --git a/src/main/kotlin/org/opensearch/commons/notifications/action/SendNotificationResponse.kt b/src/main/kotlin/org/opensearch/commons/notifications/action/SendNotificationResponse.kt index 96599b3a..8967bdd9 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/action/SendNotificationResponse.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/action/SendNotificationResponse.kt @@ -10,19 +10,16 @@ import org.opensearch.common.io.stream.Writeable import org.opensearch.common.xcontent.ToXContent import org.opensearch.common.xcontent.XContentBuilder import org.opensearch.common.xcontent.XContentParser -import org.opensearch.common.xcontent.XContentParserUtils -import org.opensearch.commons.notifications.NotificationConstants.EVENT_ID_TAG -import org.opensearch.commons.utils.logger +import org.opensearch.commons.notifications.model.NotificationEvent import java.io.IOException /** * Action Response for send notification. */ class SendNotificationResponse : BaseResponse { - val notificationId: String + val notificationEvent: NotificationEvent companion object { - private val log by logger(SendNotificationResponse::class.java) /** * reader to create instance of class from writable. @@ -36,35 +33,16 @@ class SendNotificationResponse : BaseResponse { @JvmStatic @Throws(IOException::class) fun parse(parser: XContentParser): SendNotificationResponse { - var notificationId: String? = null - - XContentParserUtils.ensureExpectedToken( - XContentParser.Token.START_OBJECT, - parser.currentToken(), - parser - ) - while (parser.nextToken() != XContentParser.Token.END_OBJECT) { - val fieldName = parser.currentName() - parser.nextToken() - when (fieldName) { - EVENT_ID_TAG -> notificationId = parser.text() - else -> { - parser.skipChildren() - log.info("Unexpected field: $fieldName, while parsing SendNotificationResponse") - } - } - } - notificationId ?: throw IllegalArgumentException("$EVENT_ID_TAG field absent") - return SendNotificationResponse(notificationId) + return SendNotificationResponse(NotificationEvent.parse(parser)) } } /** * constructor for creating the class - * @param configId the id of the created notification configuration + * @param notificationEvent the id of the created notification configuration */ - constructor(configId: String) { - this.notificationId = configId + constructor(notificationEvent: NotificationEvent) { + this.notificationEvent = notificationEvent } /** @@ -72,7 +50,7 @@ class SendNotificationResponse : BaseResponse { */ @Throws(IOException::class) constructor(input: StreamInput) : super(input) { - notificationId = input.readString() + notificationEvent = NotificationEvent(input) } /** @@ -80,16 +58,13 @@ class SendNotificationResponse : BaseResponse { */ @Throws(IOException::class) override fun writeTo(output: StreamOutput) { - output.writeString(notificationId) + notificationEvent.writeTo(output) } /** * {@inheritDoc} */ override fun toXContent(builder: XContentBuilder?, params: ToXContent.Params?): XContentBuilder { - builder!! - return builder.startObject() - .field(EVENT_ID_TAG, notificationId) - .endObject() + return notificationEvent.toXContent(builder, params) } } diff --git a/src/test/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterfaceTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterfaceTests.kt index 556c35b6..61cbca7a 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterfaceTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterfaceTests.kt @@ -40,10 +40,13 @@ import org.opensearch.commons.notifications.model.Channel import org.opensearch.commons.notifications.model.ChannelList import org.opensearch.commons.notifications.model.ChannelMessage import org.opensearch.commons.notifications.model.ConfigType +import org.opensearch.commons.notifications.model.DeliveryStatus import org.opensearch.commons.notifications.model.EventSource +import org.opensearch.commons.notifications.model.EventStatus import org.opensearch.commons.notifications.model.NotificationConfig import org.opensearch.commons.notifications.model.NotificationConfigInfo import org.opensearch.commons.notifications.model.NotificationConfigSearchResult +import org.opensearch.commons.notifications.model.NotificationEvent import org.opensearch.commons.notifications.model.SeverityType import org.opensearch.commons.notifications.model.Slack import org.opensearch.rest.RestStatus @@ -180,7 +183,16 @@ internal class NotificationsPluginInterfaceTests { null ) - val response = SendNotificationResponse("configId") + val sampleStatus = EventStatus( + "config_id", + "name", + ConfigType.SLACK, + deliveryStatus = DeliveryStatus("404", "invalid recipient") + ) + + val sampleEvent = NotificationEvent(notificationInfo, listOf(sampleStatus)) + + val response = SendNotificationResponse(sampleEvent) val listener: ActionListener = mock(ActionListener::class.java) as ActionListener diff --git a/src/test/kotlin/org/opensearch/commons/notifications/action/SendNotificationResponseTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/action/SendNotificationResponseTests.kt index ca7f789c..4d828998 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/action/SendNotificationResponseTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/action/SendNotificationResponseTests.kt @@ -5,9 +5,15 @@ package org.opensearch.commons.notifications.action import com.fasterxml.jackson.core.JsonParseException +import org.junit.Test import org.junit.jupiter.api.Assertions.assertEquals -import org.junit.jupiter.api.Test import org.junit.jupiter.api.assertThrows +import org.opensearch.commons.notifications.model.ConfigType +import org.opensearch.commons.notifications.model.DeliveryStatus +import org.opensearch.commons.notifications.model.EventSource +import org.opensearch.commons.notifications.model.EventStatus +import org.opensearch.commons.notifications.model.NotificationEvent +import org.opensearch.commons.notifications.model.SeverityType import org.opensearch.commons.utils.createObjectFromJsonString import org.opensearch.commons.utils.getJsonString import org.opensearch.commons.utils.recreateObject @@ -16,25 +22,29 @@ internal class SendNotificationResponseTests { @Test fun `Create response serialize and deserialize transport object should be equal`() { - val configResponse = SendNotificationResponse("sample_notification_id") - val recreatedObject = recreateObject(configResponse) { SendNotificationResponse(it) } - assertEquals(configResponse.notificationId, recreatedObject.notificationId) + + val sampleEvent = getSampleEvent() + + val recreatedObject = recreateObject(sampleEvent) { SendNotificationResponse(it) } + assertEquals(sampleEvent, recreatedObject) } @Test fun `Create response serialize and deserialize using json object should be equal`() { - val configResponse = SendNotificationResponse("sample_notification_id") - val jsonString = getJsonString(configResponse) + + val sampleEvent = getSampleEvent() + + val jsonString = getJsonString(sampleEvent) val recreatedObject = createObjectFromJsonString(jsonString) { SendNotificationResponse.parse(it) } - assertEquals(configResponse.notificationId, recreatedObject.notificationId) + assertEquals(sampleEvent, recreatedObject) } @Test fun `Create response should deserialize json object using parser`() { - val notificationId = "sample_notification_id" - val jsonString = "{\"event_id\":\"$notificationId\"}" + val sampleEvent = getSampleEvent() + val jsonString = "{\"event_id\":\"$sampleEvent\"}" val recreatedObject = createObjectFromJsonString(jsonString) { SendNotificationResponse.parse(it) } - assertEquals(notificationId, recreatedObject.notificationId) + assertEquals(sampleEvent, recreatedObject) } @Test @@ -55,16 +65,32 @@ internal class SendNotificationResponseTests { @Test fun `Create response should safely ignore extra field in json object`() { - val notificationId = "sample_notification_id" + val sampleEvent = getSampleEvent() val jsonString = """ { - "event_id":"$notificationId", + "event_id":"$sampleEvent", "extra_field_1":["extra", "value"], "extra_field_2":{"extra":"value"}, "extra_field_3":"extra value 3" } """.trimIndent() val recreatedObject = createObjectFromJsonString(jsonString) { SendNotificationResponse.parse(it) } - assertEquals(notificationId, recreatedObject.notificationId) + assertEquals(sampleEvent, recreatedObject) + } + + private fun getSampleEvent(): NotificationEvent { + val sampleEventSource = EventSource( + "title", + "reference_id", + severity = SeverityType.INFO + ) + val sampleStatus = EventStatus( + "config_id", + "name", + ConfigType.SLACK, + deliveryStatus = DeliveryStatus("404", "invalid recipient") + ) + + return NotificationEvent(sampleEventSource, listOf(sampleStatus)) } } From 14e76ecedde1aac2fae4595ea68d333749295753 Mon Sep 17 00:00:00 2001 From: Saurabh Singh Date: Wed, 13 Apr 2022 23:00:48 -0700 Subject: [PATCH 052/140] Remove JDK 14 (#159) Signed-off-by: Saurabh Singh --- .github/workflows/ci.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 69e7573d..5e017740 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -13,7 +13,6 @@ jobs: matrix: java: - 11 - - 14 - 17 name: Build and Test From 17bb37c0809f240e85fb305f827c34a8e0343fc3 Mon Sep 17 00:00:00 2001 From: "Daniel Doubrovkine (dB.)" Date: Fri, 15 Apr 2022 14:06:06 -0400 Subject: [PATCH 053/140] Incremented version to 2.0-rc1. (#160) Signed-off-by: dblock --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index cf3ca5b9..b3680fcd 100644 --- a/build.gradle +++ b/build.gradle @@ -6,9 +6,9 @@ buildscript { ext { opensearch_group = "org.opensearch" - opensearch_version = System.getProperty("opensearch.version", "2.0.0-alpha1-SNAPSHOT") + opensearch_version = System.getProperty("opensearch.version", "2.0.0-rc1-SNAPSHOT") isSnapshot = "true" == System.getProperty("build.snapshot", "true") - buildVersionQualifier = System.getProperty("build.version_qualifier", "alpha1") + buildVersionQualifier = System.getProperty("build.version_qualifier", "rc1") kotlin_version = System.getProperty("kotlin.version", "1.6.10") } From a80b8b1020c79bf0813b256ea9b27b489d72a6c3 Mon Sep 17 00:00:00 2001 From: Mohammad Qureshi <47198598+qreshi@users.noreply.github.com> Date: Sat, 16 Apr 2022 14:24:12 -0700 Subject: [PATCH 054/140] Support sending email message via Notifications passthrough API (#158) * Add legacy email support as a legacy Destination type Signed-off-by: Mohammad Qureshi <47198598+qreshi@users.noreply.github.com> * Add accountName to LegacyEmailMessage Signed-off-by: Mohammad Qureshi <47198598+qreshi@users.noreply.github.com> --- .../message/LegacyCustomWebhookMessage.java | 5 +- .../message/LegacyDestinationType.java | 3 +- .../message/LegacyEmailMessage.java | 234 ++++++++++++++ .../LegacyPublishNotificationRequest.kt | 2 + .../notifications/model/NotificationEvent.kt | 12 + .../message/LegacyEmailMessageTest.java | 295 ++++++++++++++++++ 6 files changed, 548 insertions(+), 3 deletions(-) create mode 100644 src/main/java/org/opensearch/commons/destination/message/LegacyEmailMessage.java create mode 100644 src/test/java/org/opensearch/commons/destination/message/LegacyEmailMessageTest.java diff --git a/src/main/java/org/opensearch/commons/destination/message/LegacyCustomWebhookMessage.java b/src/main/java/org/opensearch/commons/destination/message/LegacyCustomWebhookMessage.java index d0421ca9..dbc4b7df 100644 --- a/src/main/java/org/opensearch/commons/destination/message/LegacyCustomWebhookMessage.java +++ b/src/main/java/org/opensearch/commons/destination/message/LegacyCustomWebhookMessage.java @@ -236,8 +236,9 @@ public String getMessage() { @Override public void writeTo(StreamOutput streamOutput) throws IOException { super.writeTo(streamOutput); - // Making LegacyCustomWebhookMessage streamable is purely to support the new pass through API from ISM -> Notification plugin - // and it only supports LegacyCustomWebhookMessage when the url is already constructed by ISM. + // Making LegacyCustomWebhookMessage streamable is purely to support the new pass through API from Alerting/ISM -> Notification + // plugin + // and it only supports LegacyCustomWebhookMessage when the url is already constructed by Alerting/ISM. if (Strings.isNullOrEmpty(getUrl())) { throw new IllegalStateException("Cannot use LegacyCustomWebhookMessage across transport wire without defining full url."); } diff --git a/src/main/java/org/opensearch/commons/destination/message/LegacyDestinationType.java b/src/main/java/org/opensearch/commons/destination/message/LegacyDestinationType.java index 1bad1029..f5086c27 100644 --- a/src/main/java/org/opensearch/commons/destination/message/LegacyDestinationType.java +++ b/src/main/java/org/opensearch/commons/destination/message/LegacyDestinationType.java @@ -11,5 +11,6 @@ public enum LegacyDestinationType { LEGACY_CHIME, LEGACY_SLACK, - LEGACY_CUSTOM_WEBHOOK + LEGACY_CUSTOM_WEBHOOK, + LEGACY_EMAIL } diff --git a/src/main/java/org/opensearch/commons/destination/message/LegacyEmailMessage.java b/src/main/java/org/opensearch/commons/destination/message/LegacyEmailMessage.java new file mode 100644 index 00000000..01810868 --- /dev/null +++ b/src/main/java/org/opensearch/commons/destination/message/LegacyEmailMessage.java @@ -0,0 +1,234 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.opensearch.commons.destination.message; + +import java.io.IOException; +import java.net.URI; +import java.util.List; + +import org.opensearch.common.Strings; +import org.opensearch.common.io.stream.StreamInput; +import org.opensearch.common.io.stream.StreamOutput; +import org.opensearch.commons.notifications.model.MethodType; + +/** + * This class holds the content of an CustomWebhook message + */ +public class LegacyEmailMessage extends LegacyBaseMessage { + + private final String accountName; + private final String host; + private final int port; + private final String method; + private final String from; + private final List recipients; + private final String subject; + private final String message; + + private LegacyEmailMessage( + final String destinationName, + final String accountName, + final String host, + final Integer port, + final String method, + final String from, + final List recipients, + final String subject, + final String message + ) { + super(LegacyDestinationType.LEGACY_EMAIL, destinationName, message); + + if (Strings.isNullOrEmpty(message)) { + throw new IllegalArgumentException("Message content is missing"); + } + + if (Strings.isNullOrEmpty(accountName)) { + throw new IllegalArgumentException("Account name should be provided"); + } + + if (Strings.isNullOrEmpty(host)) { + throw new IllegalArgumentException("Host name should be provided"); + } + + if (Strings.isNullOrEmpty(from)) { + throw new IllegalArgumentException("From address should be provided"); + } + + if (recipients == null || recipients.isEmpty()) { + throw new IllegalArgumentException("List of recipients should be provided"); + } + + this.message = message; + this.accountName = accountName; + this.host = host; + this.port = port == null ? 25 : port; + + if (Strings.isNullOrEmpty(method)) { + // Default to "none" + this.method = "none"; + } else if (!MethodType.NONE.toString().equals(method) + && !MethodType.SSL.toString().equals(method) + && !MethodType.START_TLS.toString().equals(method)) { + throw new IllegalArgumentException("Invalid method supplied. Only none, ssl and start_tls are allowed"); + } else { + this.method = method; + } + + this.from = from; + this.recipients = recipients; + this.subject = Strings.isNullOrEmpty(subject) ? destinationName : subject; + } + + public LegacyEmailMessage(StreamInput streamInput) throws IOException { + super(streamInput); + this.message = super.getMessageContent(); + this.accountName = streamInput.readString(); + this.host = streamInput.readString(); + this.port = streamInput.readInt(); + this.method = streamInput.readString(); + this.from = streamInput.readString(); + this.recipients = streamInput.readStringList(); + this.subject = streamInput.readString(); + } + + @Override + public String toString() { + return "DestinationType: " + + getChannelType() + + ", DestinationName:" + + destinationName + + ", AccountName:" + + accountName + + ", From: " + + from + + ", Host: " + + host + + ", Port: " + + port + + ", Method: " + + method + + ", Subject: <...>" + + ", Message: <...>"; + } + + public static class Builder { + private final String destinationName; + private String accountName; + private String host; + private Integer port; + private String method; + private String from; + private List recipients; + private String subject; + private String message; + + public Builder(String destinationName) { + this.destinationName = destinationName; + } + + public LegacyEmailMessage.Builder withAccountName(String accountName) { + this.accountName = accountName; + return this; + } + + public LegacyEmailMessage.Builder withHost(String host) { + this.host = host; + return this; + } + + public LegacyEmailMessage.Builder withPort(Integer port) { + this.port = port; + return this; + } + + public LegacyEmailMessage.Builder withMethod(String method) { + this.method = method; + return this; + } + + public LegacyEmailMessage.Builder withFrom(String from) { + this.from = from; + return this; + } + + public LegacyEmailMessage.Builder withRecipients(List recipients) { + this.recipients = recipients; + return this; + } + + public LegacyEmailMessage.Builder withSubject(String subject) { + this.subject = subject; + return this; + } + + public LegacyEmailMessage.Builder withMessage(String message) { + this.message = message; + return this; + } + + public LegacyEmailMessage build() { + return new LegacyEmailMessage( + this.destinationName, + this.accountName, + this.host, + this.port, + this.method, + this.from, + this.recipients, + this.subject, + this.message + ); + } + } + + public String getAccountName() { + return accountName; + } + + public String getHost() { + return host; + } + + public int getPort() { + return port; + } + + public String getMethod() { + return method; + } + + public String getFrom() { + return from; + } + + public List getRecipients() { + return recipients; + } + + public String getSubject() { + return subject; + } + + public String getMessage() { + return message; + } + + public URI getUri() { + return buildUri(null, null, host, port, null, null); + } + + @Override + public void writeTo(StreamOutput streamOutput) throws IOException { + super.writeTo(streamOutput); + streamOutput.writeString(accountName); + streamOutput.writeString(host); + streamOutput.writeInt(port); + streamOutput.writeString(method); + streamOutput.writeString(from); + streamOutput.writeStringCollection(recipients); + streamOutput.writeString(subject); + } +} diff --git a/src/main/kotlin/org/opensearch/commons/notifications/action/LegacyPublishNotificationRequest.kt b/src/main/kotlin/org/opensearch/commons/notifications/action/LegacyPublishNotificationRequest.kt index 508815a8..211e2076 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/action/LegacyPublishNotificationRequest.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/action/LegacyPublishNotificationRequest.kt @@ -14,6 +14,7 @@ import org.opensearch.commons.destination.message.LegacyBaseMessage import org.opensearch.commons.destination.message.LegacyChimeMessage import org.opensearch.commons.destination.message.LegacyCustomWebhookMessage import org.opensearch.commons.destination.message.LegacyDestinationType +import org.opensearch.commons.destination.message.LegacyEmailMessage import org.opensearch.commons.destination.message.LegacySlackMessage import java.io.IOException @@ -50,6 +51,7 @@ class LegacyPublishNotificationRequest : ActionRequest { LegacyDestinationType.LEGACY_CHIME -> LegacyChimeMessage(input) LegacyDestinationType.LEGACY_CUSTOM_WEBHOOK -> LegacyCustomWebhookMessage(input) LegacyDestinationType.LEGACY_SLACK -> LegacySlackMessage(input) + LegacyDestinationType.LEGACY_EMAIL -> LegacyEmailMessage(input) } } diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationEvent.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationEvent.kt index a76f552d..6bc49d5f 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationEvent.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationEvent.kt @@ -8,9 +8,12 @@ import org.opensearch.common.io.stream.StreamInput import org.opensearch.common.io.stream.StreamOutput import org.opensearch.common.io.stream.Writeable import org.opensearch.common.xcontent.ToXContent +import org.opensearch.common.xcontent.ToXContent.EMPTY_PARAMS import org.opensearch.common.xcontent.XContentBuilder +import org.opensearch.common.xcontent.XContentHelper import org.opensearch.common.xcontent.XContentParser import org.opensearch.common.xcontent.XContentParserUtils +import org.opensearch.common.xcontent.XContentType import org.opensearch.commons.notifications.NotificationConstants.EVENT_SOURCE_TAG import org.opensearch.commons.notifications.NotificationConstants.STATUS_LIST_TAG import org.opensearch.commons.utils.logger @@ -102,4 +105,13 @@ data class NotificationEvent( .field(STATUS_LIST_TAG, statusList) .endObject() } + + // Overriding toString so consuming plugins can log/output this from the sendNotification response if needed + override fun toString(): String { + return try { + XContentHelper.toXContent(this, XContentType.JSON, EMPTY_PARAMS, true).utf8ToString() + } catch (e: IOException) { + super.toString() + " threw " + e.toString() + } + } } diff --git a/src/test/java/org/opensearch/commons/destination/message/LegacyEmailMessageTest.java b/src/test/java/org/opensearch/commons/destination/message/LegacyEmailMessageTest.java new file mode 100644 index 00000000..06625053 --- /dev/null +++ b/src/test/java/org/opensearch/commons/destination/message/LegacyEmailMessageTest.java @@ -0,0 +1,295 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.opensearch.commons.destination.message; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.fail; + +import java.io.IOException; +import java.util.Arrays; +import java.util.List; + +import org.junit.jupiter.api.Test; +import org.opensearch.common.io.stream.BytesStreamOutput; +import org.opensearch.common.io.stream.StreamInput; + +public class LegacyEmailMessageTest { + + @Test + public void testBuildingLegacyEmailMessage() { + LegacyEmailMessage message = new LegacyEmailMessage.Builder("email") + .withAccountName("test_email") + .withHost("smtp.test.com") + .withPort(123) + .withMethod("none") + .withFrom("test@email.com") + .withRecipients(Arrays.asList("test2@email.com", "test3@email.com")) + .withSubject("Test Subject") + .withMessage("Hello world") + .build(); + + assertEquals("email", message.destinationName); + assertEquals(LegacyDestinationType.LEGACY_EMAIL, message.getChannelType()); + assertEquals("test_email", message.getAccountName()); + assertEquals("smtp.test.com", message.getHost()); + assertEquals(123, message.getPort()); + assertEquals("none", message.getMethod()); + assertEquals("test@email.com", message.getFrom()); + assertEquals(Arrays.asList("test2@email.com", "test3@email.com"), message.getRecipients()); + assertEquals("Test Subject", message.getSubject()); + assertEquals("Hello world", message.getMessage()); + } + + @Test + public void testRoundTrippingLegacyEmailMessage() throws IOException { + LegacyEmailMessage message = new LegacyEmailMessage.Builder("email") + .withAccountName("test_email") + .withHost("smtp.test.com") + .withPort(123) + .withMethod("none") + .withFrom("test@email.com") + .withRecipients(Arrays.asList("test2@email.com", "test3@email.com")) + .withSubject("Test Subject") + .withMessage("Hello world") + .build(); + BytesStreamOutput out = new BytesStreamOutput(); + message.writeTo(out); + + StreamInput in = StreamInput.wrap(out.bytes().toBytesRef().bytes); + LegacyEmailMessage newMessage = new LegacyEmailMessage(in); + + assertEquals(newMessage.destinationName, message.destinationName); + assertEquals(newMessage.getChannelType(), message.getChannelType()); + assertEquals(newMessage.getAccountName(), message.getAccountName()); + assertEquals(newMessage.getHost(), message.getHost()); + assertEquals(newMessage.getPort(), message.getPort()); + assertEquals(newMessage.getMethod(), message.getMethod()); + assertEquals(newMessage.getFrom(), message.getFrom()); + assertEquals(newMessage.getRecipients(), message.getRecipients()); + assertEquals(newMessage.getSubject(), message.getSubject()); + assertEquals(newMessage.getMessage(), message.getMessage()); + } + + @Test + public void testContentMissingMessage() { + try { + new LegacyEmailMessage.Builder("email") + .withAccountName("test_email") + .withHost("smtp.test.com") + .withPort(123) + .withMethod("none") + .withFrom("test@email.com") + .withRecipients(Arrays.asList("test2@email.com", "test3@email.com")) + .withSubject("Test Subject") + .build(); + fail("Building legacy email message without message should fail"); + } catch (IllegalArgumentException e) { + assertEquals("Message content is missing", e.getMessage()); + } + } + + @Test + public void testMissingDestinationName() { + try { + new LegacyEmailMessage.Builder(null) + .withAccountName("test_email") + .withHost("smtp.test.com") + .withPort(123) + .withMethod("none") + .withFrom("test@email.com") + .withRecipients(Arrays.asList("test2@email.com", "test3@email.com")) + .withSubject("Test Subject") + .withMessage("Hello world") + .build(); + fail("Building legacy email message with null destination name should fail"); + } catch (IllegalArgumentException e) { + assertEquals("Channel name must be defined", e.getMessage()); + } + } + + @Test + public void testUnsupportedMethods() { + try { + new LegacyEmailMessage.Builder("email") + .withAccountName("test_email") + .withHost("smtp.test.com") + .withPort(123) + .withMethod("unsupported") + .withFrom("test@email.com") + .withRecipients(Arrays.asList("test2@email.com", "test3@email.com")) + .withSubject("Test Subject") + .withMessage("Hello world") + .build(); + fail("Building legacy email message with unsupported method should fail"); + } catch (IllegalArgumentException e) { + assertEquals("Invalid method supplied. Only none, ssl and start_tls are allowed", e.getMessage()); + } + } + + @Test + public void testAccountNameMissingOrEmpty() { + try { + new LegacyEmailMessage.Builder("email") + .withHost("smtp.test.com") + .withPort(123) + .withMethod("none") + .withFrom("test@email.com") + .withRecipients(Arrays.asList("test2@email.com", "test3@email.com")) + .withSubject("Test Subject") + .withMessage("Hello world") + .build(); + fail("Building legacy email message with missing account name should fail"); + } catch (IllegalArgumentException e) { + assertEquals("Account name should be provided", e.getMessage()); + } + + try { + new LegacyEmailMessage.Builder("email") + .withAccountName("") + .withHost("smtp.test.com") + .withPort(123) + .withMethod("none") + .withFrom("test@email.com") + .withRecipients(Arrays.asList("test2@email.com", "test3@email.com")) + .withSubject("Test Subject") + .withMessage("Hello world") + .build(); + fail("Building legacy email message with empty account name should fail"); + } catch (IllegalArgumentException e) { + assertEquals("Account name should be provided", e.getMessage()); + } + } + + @Test + public void testHostMissingOrEmpty() { + try { + new LegacyEmailMessage.Builder("email") + .withAccountName("test_email") + .withPort(123) + .withMethod("none") + .withFrom("test@email.com") + .withRecipients(Arrays.asList("test2@email.com", "test3@email.com")) + .withSubject("Test Subject") + .withMessage("Hello world") + .build(); + fail("Building legacy email message with missing host should fail"); + } catch (IllegalArgumentException e) { + assertEquals("Host name should be provided", e.getMessage()); + } + + try { + new LegacyEmailMessage.Builder("email") + .withAccountName("test_email") + .withHost("") + .withPort(123) + .withMethod("none") + .withFrom("test@email.com") + .withRecipients(Arrays.asList("test2@email.com", "test3@email.com")) + .withSubject("Test Subject") + .withMessage("Hello world") + .build(); + fail("Building legacy email message with empty host should fail"); + } catch (IllegalArgumentException e) { + assertEquals("Host name should be provided", e.getMessage()); + } + } + + @Test + public void testFromMissingOrEmpty() { + try { + new LegacyEmailMessage.Builder("email") + .withAccountName("test_email") + .withHost("smtp.test.com") + .withPort(123) + .withMethod("none") + .withRecipients(Arrays.asList("test2@email.com", "test3@email.com")) + .withSubject("Test Subject") + .withMessage("Hello world") + .build(); + fail("Building legacy email message with missing from should fail"); + } catch (IllegalArgumentException e) { + assertEquals("From address should be provided", e.getMessage()); + } + + try { + new LegacyEmailMessage.Builder("email") + .withAccountName("test_email") + .withHost("smtp.test.com") + .withPort(123) + .withMethod("none") + .withFrom("") + .withRecipients(Arrays.asList("test2@email.com", "test3@email.com")) + .withSubject("Test Subject") + .withMessage("Hello world") + .build(); + fail("Building legacy email message with empty from should fail"); + } catch (IllegalArgumentException e) { + assertEquals("From address should be provided", e.getMessage()); + } + } + + @Test + public void testRecipientsMissingOrEmpty() { + try { + new LegacyEmailMessage.Builder("email") + .withAccountName("test_email") + .withHost("smtp.test.com") + .withPort(123) + .withMethod("none") + .withFrom("test@email.com") + .withSubject("Test Subject") + .withMessage("Hello world") + .build(); + fail("Building legacy email message with missing recipients should fail"); + } catch (IllegalArgumentException e) { + assertEquals("List of recipients should be provided", e.getMessage()); + } + + try { + new LegacyEmailMessage.Builder("email") + .withAccountName("test_email") + .withHost("smtp.test.com") + .withPort(123) + .withMethod("none") + .withFrom("test@email.com") + .withRecipients(List.of()) + .withSubject("Test Subject") + .withMessage("Hello world") + .build(); + fail("Building legacy email message with empty recipients should fail"); + } catch (IllegalArgumentException e) { + assertEquals("List of recipients should be provided", e.getMessage()); + } + } + + @Test + public void testSubjectDefaultsToDestinationNameWhenMissingOrEmpty() { + LegacyEmailMessage message = new LegacyEmailMessage.Builder("email") + .withAccountName("test_email") + .withHost("smtp.test.com") + .withPort(123) + .withMethod("none") + .withFrom("test@email.com") + .withRecipients(Arrays.asList("test2@email.com", "test3@email.com")) + .withMessage("Hello world") + .build(); + + assertEquals("email", message.getSubject()); + + message = new LegacyEmailMessage.Builder("email") + .withAccountName("test_email") + .withHost("smtp.test.com") + .withPort(123) + .withMethod("none") + .withFrom("test@email.com") + .withRecipients(Arrays.asList("test2@email.com", "test3@email.com")) + .withSubject("") + .withMessage("Hello world") + .build(); + + assertEquals("email", message.getSubject()); + } +} From 39bd777641a23ed1fa94a56fae2e001028eca58b Mon Sep 17 00:00:00 2001 From: Saurabh Singh Date: Mon, 25 Apr 2022 15:37:16 -0700 Subject: [PATCH 055/140] Add release notes for version 2.0.0.0-rc1 (#162) Signed-off-by: Saurabh Singh --- ...-common-utils.release-notes-2.0.0.0-rc1.md | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 release-notes/opensearch-common-utils.release-notes-2.0.0.0-rc1.md diff --git a/release-notes/opensearch-common-utils.release-notes-2.0.0.0-rc1.md b/release-notes/opensearch-common-utils.release-notes-2.0.0.0-rc1.md new file mode 100644 index 00000000..84418524 --- /dev/null +++ b/release-notes/opensearch-common-utils.release-notes-2.0.0.0-rc1.md @@ -0,0 +1,29 @@ +## Version 2.0.0.0-rc1 2022-04-25 + +Compatible with OpenSearch 2.0.0-rc1 + +### Enhancements + + * Add SQL/PPL transport request/response models for SQL plugin ([#155](https://github.com/opensearch-project/common-utils/pull/155)) + * Support sending email message via Notifications pass-through API ([#158](https://github.com/opensearch-project/common-utils/pull/158)) + +### Infrastructure + + * Upgrade gradle artifacts to 7.3.3 ([#135](https://github.com/opensearch-project/common-utils/pull/135) + * Update common-utils to depend on the OpenSearch repositories plugin ([#137](https://github.com/opensearch-project/common-utils/pull/137)) + * Add sign-off option for version workflow PR ([#143](https://github.com/opensearch-project/common-utils/pull/143)) + * Add qualifier default to alpha1 in build.gradle ([#151](https://github.com/opensearch-project/common-utils/pull/151)) + * Update issue templates from github for bugs and features ([#154](https://github.com/opensearch-project/common-utils/pull/154)) + * Remove support for JDK 14 ([#159](https://github.com/opensearch-project/common-utils/pull/159)) + +### Refactoring + + * Remove feature and feature_list usage for Notifications ([#136](https://github.com/opensearch-project/common-utils/pull/136)) + * Rename references for Get Channels API for Notifications ([#140](https://github.com/opensearch-project/common-utils/pull/140)) + * Remove allowedConfigFeatureList from GetPluginFeaturesResponse for Notifications ([#144](https://github.com/opensearch-project/common-utils/pull/144)) + * Remove NotificationEvent Request, Response and SearchResults ([#153](https://github.com/opensearch-project/common-utils/pull/153)) + * Add NotificationEvent to SendNotificationResponse and Removal of NotificationID ([#156](https://github.com/opensearch-project/common-utils/pull/156)) + +### Documentation + + * Add release notes for version 2.0.0-rc1 ([#162](https://github.com/opensearch-project/common-utils/pull/162)) From 389bb3c27f88720995846be2ff95afee19b16cd1 Mon Sep 17 00:00:00 2001 From: Aditya Jindal <13850971+aditjind@users.noreply.github.com> Date: Thu, 5 May 2022 19:23:49 -0700 Subject: [PATCH 056/140] Removing RC1 as the qualifier from Common Utils (#168) Signed-off-by: Aditya Jindal --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index b3680fcd..eb2e8bc9 100644 --- a/build.gradle +++ b/build.gradle @@ -6,9 +6,9 @@ buildscript { ext { opensearch_group = "org.opensearch" - opensearch_version = System.getProperty("opensearch.version", "2.0.0-rc1-SNAPSHOT") + opensearch_version = System.getProperty("opensearch.version", "2.0.0-SNAPSHOT") isSnapshot = "true" == System.getProperty("build.snapshot", "true") - buildVersionQualifier = System.getProperty("build.version_qualifier", "rc1") + buildVersionQualifier = System.getProperty("build.version_qualifier", "") kotlin_version = System.getProperty("kotlin.version", "1.6.10") } From 1eef82c0d9a8259e2bdbd2bf23194869f93a2c48 Mon Sep 17 00:00:00 2001 From: Subhobrata Dey Date: Mon, 9 May 2022 14:44:02 -0700 Subject: [PATCH 057/140] add code coverage badge (#169) Signed-off-by: Subhobrata Dey --- .codecov.yml | 12 ++++++++++++ .github/workflows/ci.yml | 3 +-- 2 files changed, 13 insertions(+), 2 deletions(-) create mode 100644 .codecov.yml diff --git a/.codecov.yml b/.codecov.yml new file mode 100644 index 00000000..e711a04d --- /dev/null +++ b/.codecov.yml @@ -0,0 +1,12 @@ +codecov: + require_ci_to_pass: yes + +coverage: + precision: 2 + round: down + range: "75...100" + status: + project: + default: + target: 75% # the required coverage value + threshold: 1% # the leniency in hitting the target \ No newline at end of file diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5e017740..0bcc5e2c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -38,6 +38,5 @@ jobs: - name: Upload Coverage Report uses: codecov/codecov-action@v1 with: - file: ./build/reports/jacoco/test/jacocoTestReport.xml - flags: plugin + token: ${{ secrets.CODECOV_TOKEN }} From d36924d5d7b218d2c70f8492c9dff6023560abe1 Mon Sep 17 00:00:00 2001 From: Mohammad Qureshi <47198598+qreshi@users.noreply.github.com> Date: Wed, 11 May 2022 16:45:44 -0700 Subject: [PATCH 058/140] Change BaseModel to extend ToXContentObject instead of ToXContent (#173) Signed-off-by: Mohammad Qureshi <47198598+qreshi@users.noreply.github.com> --- .../org/opensearch/commons/notifications/model/BaseModel.kt | 4 ++-- .../commons/notifications/model/NotificationEvent.kt | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/BaseModel.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/BaseModel.kt index 5ead5594..056fcc6e 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/BaseModel.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/BaseModel.kt @@ -5,9 +5,9 @@ package org.opensearch.commons.notifications.model import org.opensearch.common.io.stream.Writeable -import org.opensearch.common.xcontent.ToXContent +import org.opensearch.common.xcontent.ToXContentObject /** * interface for representing objects. */ -interface BaseModel : Writeable, ToXContent +interface BaseModel : Writeable, ToXContentObject diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationEvent.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationEvent.kt index 6bc49d5f..2ab5426b 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationEvent.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationEvent.kt @@ -111,6 +111,7 @@ data class NotificationEvent( return try { XContentHelper.toXContent(this, XContentType.JSON, EMPTY_PARAMS, true).utf8ToString() } catch (e: IOException) { + log.debug("Failed to convert NotificationEvent to string", e) super.toString() + " threw " + e.toString() } } From 4557ed1ee9c05ab8baee9424f74e0c9e7e5aa812 Mon Sep 17 00:00:00 2001 From: Subhobrata Dey Date: Mon, 16 May 2022 15:57:04 -0700 Subject: [PATCH 059/140] add code coverage badge (#171) --- README.md | 1 + build-tools/opensearchplugin-coverage.gradle | 49 ++++++++++++++++++++ build.gradle | 1 + 3 files changed, 51 insertions(+) create mode 100644 build-tools/opensearchplugin-coverage.gradle diff --git a/README.md b/README.md index fc95f76e..b900ee32 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,5 @@ +[![codecov](https://codecov.io/gh/opensearch-project/common-utils/branch/main/graph/badge.svg?token=CQ01D9MNQL)](https://codecov.io/gh/opensearch-project/common-utils) - [OpenSearch Common Utils](#opensearch-common-utils) - [Contributing](#contributing) diff --git a/build-tools/opensearchplugin-coverage.gradle b/build-tools/opensearchplugin-coverage.gradle new file mode 100644 index 00000000..2b4d21c0 --- /dev/null +++ b/build-tools/opensearchplugin-coverage.gradle @@ -0,0 +1,49 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * OpenSearch Plugin build tools don't work with the Gradle Jacoco Plugin to report coverage out of the box. + * https://github.com/elastic/elasticsearch/issues/28867. + * + * This code sets up coverage reporting manually for OpenSearch plugin tests. This is complicated because: + * 1. The OpenSearch integTest Task doesn't implement Gradle's JavaForkOptions so we have to manually start the jacoco agent with the test JVM + * 2. The cluster nodes are stopped using 'kill -9' which means jacoco can't dump it's execution output to a file on VM shutdown + * 3. The Java Security Manager prevents JMX from writing execution output to the file. + * + * To workaround these we start the cluster with jmx enabled and then use Jacoco's JMX MBean to get the execution data before the + * cluster is stopped and dump it to a file. Luckily our current security policy seems to allow this. This will also probably + * break if there are multiple nodes in the integTestCluster. But for now... it sorta works. + */ +apply plugin: 'jacoco' + +// Get gradle to generate the required jvm agent arg for us using a dummy tasks of type Test. Unfortunately Elastic's +// testing tasks don't derive from Test so the jacoco plugin can't do this automatically. +def jacocoDir = "${buildDir}/jacoco" +task dummyTest(type: Test) { + enabled = false + workingDir = file("/") // Force absolute path to jacoco agent jar + jacoco { + destinationFile = file("${jacocoDir}/test.exec") + destinationFile.parentFile.mkdirs() + jmx = true + } +} + +jacocoTestReport { + dependsOn test + executionData dummyTest.jacoco.destinationFile + getSourceDirectories().from(sourceSets.main.allSource) + getClassDirectories().from(sourceSets.main.output) + reports { + html.enabled = true // human readable + xml.enabled = true // for coverlay + } +} + +project.gradle.projectsEvaluated { + jacocoTestReport.dependsOn test +} + +check.dependsOn jacocoTestReport diff --git a/build.gradle b/build.gradle index eb2e8bc9..67e4bef1 100644 --- a/build.gradle +++ b/build.gradle @@ -63,6 +63,7 @@ apply plugin: 'io.gitlab.arturbosch.detekt' apply plugin: 'org.jetbrains.kotlin.jvm' apply plugin: 'org.jetbrains.kotlin.plugin.allopen' apply plugin: 'opensearch.repositories' +apply from: 'build-tools/opensearchplugin-coverage.gradle' configurations { ktlint From 1d0ee34f8cb4d5e859836f962ac0022a8dee368e Mon Sep 17 00:00:00 2001 From: Subhobrata Dey Date: Mon, 16 May 2022 21:46:53 -0700 Subject: [PATCH 060/140] fix code coverage badge (#175) Signed-off-by: Subhobrata Dey --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index b900ee32..47a0b97b 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ -[![codecov](https://codecov.io/gh/opensearch-project/common-utils/branch/main/graph/badge.svg?token=CQ01D9MNQL)](https://codecov.io/gh/opensearch-project/common-utils) + + + - [OpenSearch Common Utils](#opensearch-common-utils) - [Contributing](#contributing) From e8b991ee0787f7afa16c33383a1454847d88115f Mon Sep 17 00:00:00 2001 From: Subhobrata Dey Date: Tue, 17 May 2022 11:02:52 -0700 Subject: [PATCH 061/140] fix code coverage badge (#176) Signed-off-by: Subhobrata Dey --- README.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 47a0b97b..98ee4ce2 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,6 @@ +[![codecov](https://codecov.io/gh/opensearch-project/common-utils/branch/main/graph/badge.svg)](https://codecov.io/gh/opensearch-project/common-utils) + - - - - [OpenSearch Common Utils](#opensearch-common-utils) - [Contributing](#contributing) From a03453c99b3db82ea4dc579e48a8d8bb605c2ee5 Mon Sep 17 00:00:00 2001 From: Saurabh Singh Date: Wed, 18 May 2022 12:34:37 -0700 Subject: [PATCH 062/140] Add release notes for version 2.0.0.0 (#177) Signed-off-by: Saurabh Singh --- ...arch-common-utils.release-notes-2.0.0.0.md | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 release-notes/opensearch-common-utils.release-notes-2.0.0.0.md diff --git a/release-notes/opensearch-common-utils.release-notes-2.0.0.0.md b/release-notes/opensearch-common-utils.release-notes-2.0.0.0.md new file mode 100644 index 00000000..70295ccc --- /dev/null +++ b/release-notes/opensearch-common-utils.release-notes-2.0.0.0.md @@ -0,0 +1,32 @@ +## Version 2.0.0.0 2022-05-18 + +Compatible with OpenSearch 2.0.0 + +### Enhancements + + * Add SQL/PPL transport request/response models for SQL plugin ([#155](https://github.com/opensearch-project/common-utils/pull/155)) + * Support sending email message via Notifications pass-through API ([#158](https://github.com/opensearch-project/common-utils/pull/158)) + +### Infrastructure + + * Upgrade gradle artifacts to 7.3.3 ([#135](https://github.com/opensearch-project/common-utils/pull/135) + * Update common-utils to depend on the OpenSearch repositories plugin ([#137](https://github.com/opensearch-project/common-utils/pull/137)) + * Add sign-off option for version workflow PR ([#143](https://github.com/opensearch-project/common-utils/pull/143)) + * Add qualifier default to alpha1 in build.gradle ([#151](https://github.com/opensearch-project/common-utils/pull/151)) + * Update issue templates from github for bugs and features ([#154](https://github.com/opensearch-project/common-utils/pull/154)) + * Remove support for JDK 14 ([#159](https://github.com/opensearch-project/common-utils/pull/159)) + * Remove RC1 as the qualifier from Common Utils ([#168](https://github.com/opensearch-project/common-utils/pull/168)) + +### Refactoring + + * Remove feature and feature_list usage for Notifications ([#136](https://github.com/opensearch-project/common-utils/pull/136)) + * Rename references for Get Channels API for Notifications ([#140](https://github.com/opensearch-project/common-utils/pull/140)) + * Remove allowedConfigFeatureList from GetPluginFeaturesResponse for Notifications ([#144](https://github.com/opensearch-project/common-utils/pull/144)) + * Remove NotificationEvent Request, Response and SearchResults ([#153](https://github.com/opensearch-project/common-utils/pull/153)) + * Add NotificationEvent to SendNotificationResponse and Removal of NotificationID ([#156](https://github.com/opensearch-project/common-utils/pull/156)) + * Change BaseModel to extend ToXContentObject instead of ToXContent ([#173](https://github.com/opensearch-project/common-utils/pull/173)) + +### Documentation + + * Add release notes for version 2.0.0-rc1 ([#162](https://github.com/opensearch-project/common-utils/pull/162)) + * Add release notes for version 2.0.0.0 ([#177](https://github.com/opensearch-project/common-utils/pull/177)) From b0544208a851544e33a73912c3322f0591e9ad54 Mon Sep 17 00:00:00 2001 From: "Daniel Doubrovkine (dB.)" Date: Tue, 24 May 2022 14:02:00 -0400 Subject: [PATCH 063/140] Remove duplicate DCO workflow. (#181) Signed-off-by: dblock --- .github/workflows/dco.yml | 18 ------------------ 1 file changed, 18 deletions(-) delete mode 100644 .github/workflows/dco.yml diff --git a/.github/workflows/dco.yml b/.github/workflows/dco.yml deleted file mode 100644 index 53ed5304..00000000 --- a/.github/workflows/dco.yml +++ /dev/null @@ -1,18 +0,0 @@ -name: Developer Certificate of Origin Check - -on: [pull_request] - -jobs: - check: - runs-on: ubuntu-latest - - steps: - - name: Get PR Commits - id: 'get-pr-commits' - uses: tim-actions/get-pr-commits@v1.1.0 - with: - token: ${{ secrets.GITHUB_TOKEN }} - - name: DCO Check - uses: tim-actions/dco@v1.1.0 - with: - commits: ${{ steps.get-pr-commits.outputs.commits }} \ No newline at end of file From 26a4c3629cfea8e49d6b2fde80d32bfdddc74812 Mon Sep 17 00:00:00 2001 From: Ankit Kala Date: Thu, 23 Jun 2022 00:08:18 +0530 Subject: [PATCH 064/140] Bump up the version to 2.1 (#190) Signed-off-by: Ankit Kala --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 67e4bef1..280a92e7 100644 --- a/build.gradle +++ b/build.gradle @@ -6,7 +6,7 @@ buildscript { ext { opensearch_group = "org.opensearch" - opensearch_version = System.getProperty("opensearch.version", "2.0.0-SNAPSHOT") + opensearch_version = System.getProperty("opensearch.version", "2.1.0-SNAPSHOT") isSnapshot = "true" == System.getProperty("build.snapshot", "true") buildVersionQualifier = System.getProperty("build.version_qualifier", "") kotlin_version = System.getProperty("kotlin.version", "1.6.10") From 5d96f3c2084f3ecfe263dea99397f1d9796e7cfc Mon Sep 17 00:00:00 2001 From: Subhobrata Dey Date: Wed, 22 Jun 2022 14:19:40 -0700 Subject: [PATCH 065/140] Upgrade gradle to 7.4.2 (#191) --- gradle/wrapper/gradle-wrapper.jar | Bin 59536 -> 59821 bytes gradle/wrapper/gradle-wrapper.properties | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 7454180f2ae8848c63b8b4dea2cb829da983f2fa..41d9927a4d4fb3f96a785543079b8df6723c946b 100644 GIT binary patch delta 8958 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 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 2e6e5897..aa991fce 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.2-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists From 79a2ae3bf06a2e7c759058e2036033ef87f47012 Mon Sep 17 00:00:00 2001 From: "opensearch-trigger-bot[bot]" <98922864+opensearch-trigger-bot[bot]@users.noreply.github.com> Date: Wed, 6 Jul 2022 15:28:18 -0700 Subject: [PATCH 066/140] Added 2.1 release notes. (#194) (#196) (cherry picked from commit 739d155a0f6ed03c83e5cb014abaef6432d8ca23) Signed-off-by: Subhobrata Dey Co-authored-by: Subhobrata Dey --- .../opensearch-common-utils.release-notes-2.1.0.0.md | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 release-notes/opensearch-common-utils.release-notes-2.1.0.0.md diff --git a/release-notes/opensearch-common-utils.release-notes-2.1.0.0.md b/release-notes/opensearch-common-utils.release-notes-2.1.0.0.md new file mode 100644 index 00000000..3bf4465f --- /dev/null +++ b/release-notes/opensearch-common-utils.release-notes-2.1.0.0.md @@ -0,0 +1,10 @@ +## Version 2.1.0.0 2022-07-06 + +Compatible with OpenSearch 2.1.0 + +### Maintenance +* Upgrade gradle to 7.4.2. ([#191](https://github.com/opensearch-project/common-utils/pull/191)) +* Bump up the version to 2.1. ([#190](https://github.com/opensearch-project/common-utils/pull/190)) + +### Documentation +* Added 2.1 release notes. ([#194](https://github.com/opensearch-project/common-utils/pull/194)) \ No newline at end of file From fe37126bf78ee336a91c0f5b2552eb97aec375f8 Mon Sep 17 00:00:00 2001 From: Mohammad Qureshi <47198598+qreshi@users.noreply.github.com> Date: Mon, 25 Jul 2022 10:02:57 -0700 Subject: [PATCH 067/140] Bump 2.x branch to 2.2 (#204) Signed-off-by: Mohammad Qureshi <47198598+qreshi@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 280a92e7..674ac630 100644 --- a/build.gradle +++ b/build.gradle @@ -6,7 +6,7 @@ buildscript { ext { opensearch_group = "org.opensearch" - opensearch_version = System.getProperty("opensearch.version", "2.1.0-SNAPSHOT") + opensearch_version = System.getProperty("opensearch.version", "2.2.0-SNAPSHOT") isSnapshot = "true" == System.getProperty("build.snapshot", "true") buildVersionQualifier = System.getProperty("build.version_qualifier", "") kotlin_version = System.getProperty("kotlin.version", "1.6.10") From 7d531022af8f5c4ec3ef38194596b4f6ccd5bb6b Mon Sep 17 00:00:00 2001 From: "opensearch-trigger-bot[bot]" <98922864+opensearch-trigger-bot[bot]@users.noreply.github.com> Date: Thu, 4 Aug 2022 14:11:16 -0700 Subject: [PATCH 068/140] Staging for version increment automation (#200) (#211) * Version increment automation Signed-off-by: pgodithi * Version increment automation: task rename updateVersion Signed-off-by: pgodithi (cherry picked from commit 366bf16496f43474a45c47b99bb4f91edc4109fb) Signed-off-by: prudhvigodithi Co-authored-by: Prudhvi Godithi --- build.gradle | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/build.gradle b/build.gradle index 674ac630..7849fd91 100644 --- a/build.gradle +++ b/build.gradle @@ -199,3 +199,15 @@ publishing { gradle.startParameter.setShowStacktrace(ShowStacktrace.ALWAYS) gradle.startParameter.setLogLevel(LogLevel.DEBUG) } + +// updateVersion: Task to auto increment to the next development iteration +task updateVersion { + onlyIf { System.getProperty('newVersion') } + doLast { + ext.newVersion = System.getProperty('newVersion') + println "Setting version to ${newVersion}." + // String tokenization to support -SNAPSHOT + // Include the required files that needs to be updated with new Version + ant.replaceregexp(file:'build.gradle', match: '"opensearch.version", "\\d.*"', replace: '"opensearch.version", "' + newVersion.tokenize('-')[0] + '-SNAPSHOT"', flags:'g', byline:true) + } +} \ No newline at end of file From c3408f34961eb7e8ebc0510306f62238a457dbbc Mon Sep 17 00:00:00 2001 From: Saurabh Singh Date: Tue, 9 Aug 2022 11:43:58 -0700 Subject: [PATCH 069/140] Added 2.2 release notes. (#216) Signed-off-by: Saurabh Singh --- .../opensearch-common-utils.release-notes-2.2.0.0.md | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 release-notes/opensearch-common-utils.release-notes-2.2.0.0.md diff --git a/release-notes/opensearch-common-utils.release-notes-2.2.0.0.md b/release-notes/opensearch-common-utils.release-notes-2.2.0.0.md new file mode 100644 index 00000000..b77f7244 --- /dev/null +++ b/release-notes/opensearch-common-utils.release-notes-2.2.0.0.md @@ -0,0 +1,10 @@ +## Version 2.2.0.0 2022-08-09 + +Compatible with OpenSearch 2.2.0 + +### Infrastructure +* Execute version auto increment in staging ([#200](https://github.com/opensearch-project/common-utils/pull/200)) +* Bump up the version to 2.2. ([#204](https://github.com/opensearch-project/common-utils/pull/204)) + +### Documentation +* Added 2.2 release notes. ([#212](https://github.com/opensearch-project/common-utils/pull/212)) \ No newline at end of file From b809166376460f40fda0c0408736b47434f6588b Mon Sep 17 00:00:00 2001 From: "opensearch-trigger-bot[bot]" <98922864+opensearch-trigger-bot[bot]@users.noreply.github.com> Date: Tue, 16 Aug 2022 13:11:16 -0700 Subject: [PATCH 070/140] Added 2.2 release notes. (#212) (#215) Signed-off-by: Saurabh Singh (cherry picked from commit b82ef4a63913b6ef5b72dc50b9e4c88ea85302a9) Co-authored-by: Saurabh Singh From b6980f2da263359ba10ccc3a334bc0f9f4333cfe Mon Sep 17 00:00:00 2001 From: Aditya Jindal <13850971+aditjind@users.noreply.github.com> Date: Thu, 1 Jul 2021 17:47:57 -0700 Subject: [PATCH 071/140] Update Release Notes for GA (#36) * Update Release Notes for GA * Update Release Notes for GA include RC1 Changes as well. Signed-off-by: Aditya Jindal Signed-off-by: Zelin Hao --- ...arch-common-utils.release-notes-1.0.0.0.md | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 release-notes/opensearch-common-utils.release-notes-1.0.0.0.md diff --git a/release-notes/opensearch-common-utils.release-notes-1.0.0.0.md b/release-notes/opensearch-common-utils.release-notes-1.0.0.0.md new file mode 100644 index 00000000..71d1a7db --- /dev/null +++ b/release-notes/opensearch-common-utils.release-notes-1.0.0.0.md @@ -0,0 +1,29 @@ +## Version 1.0.0.0 2021-07-01 + +Compatible with OpenSearch 1.0.0 + +### Enhancements + + * Notification plugin interface and models ([#31](https://github.com/opensearch-project/common-utils/pull/31)) + +### Infrastructure + + * Support for kotlin and JUnit5 with mockito ([#29](https://github.com/opensearch-project/common-utils/pull/29)) + * Removing Kotlin Runtime library bundled into library ([#30](https://github.com/opensearch-project/common-utils/pull/30)) + * Bump to version 1.0.0.0 #34 ([#34](https://github.com/opensearch-project/common-utils/pull/34)) + +### Documentation + + * Update OpenSearch branch to 1.0 ([#28](https://github.com/opensearch-project/common-utils/pull/28)) + * Cleanup READMEs. ([#32](https://github.com/opensearch-project/common-utils/pull/32)) + +### Maintainence + + * Update issue template with multiple labels ([#18](https://github.com/opensearch-project/common-utils/pull/18)) + * Rename namespaces from OpenDistro to OpenSearch ([#20](https://github.com/opensearch-project/common-utils/pull/20)) + * Rename classes, variables, methods to incorporate OpenSearch ([#21](https://github.com/opensearch-project/common-utils/pull/21)) + * Rename remaining identifiers to OpenSearch ([#23](https://github.com/opensearch-project/common-utils/pull/23)) + * Version changed to rc1 #24 ([#24](https://github.com/opensearch-project/common-utils/pull/24)) + * Rename consts as per changes in security plugin ([#25](https://github.com/opensearch-project/common-utils/pull/25)) + * Move workflow tags to rc1 ([#26](https://github.com/opensearch-project/common-utils/pull/26)) + * Add rc1 release notes ([#27](https://github.com/opensearch-project/common-utils/pull/27)) From 6966cf6703691f3be1e5a4a9fb1329bd937bf4b0 Mon Sep 17 00:00:00 2001 From: Zhongnan Su Date: Fri, 16 Jul 2021 15:08:55 -0700 Subject: [PATCH 072/140] add method type in CustomWebhook data model (#39) Signed-off-by: Zhongnan Su Signed-off-by: Zelin Hao --- .../notifications/model/HttpMethodType.kt | 36 +++++++++++++++++++ .../commons/notifications/model/Webhook.kt | 13 +++++-- .../notifications/model/WebhookTests.kt | 15 ++++++-- 3 files changed, 58 insertions(+), 6 deletions(-) create mode 100644 src/main/kotlin/org/opensearch/commons/notifications/model/HttpMethodType.kt diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/HttpMethodType.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/HttpMethodType.kt new file mode 100644 index 00000000..8485e4fd --- /dev/null +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/HttpMethodType.kt @@ -0,0 +1,36 @@ +package org.opensearch.commons.notifications.model + +import org.opensearch.commons.utils.EnumParser + +enum class HttpMethodType(val tag: String) { + POST("POST") { + override fun toString(): String { + return tag + } + }, + PUT("PUT") { + override fun toString(): String { + return tag + } + }, + PATCH("PATCH") { + override fun toString(): String { + return tag + } + }; + + companion object { + private val tagMap = values().associateBy { it.tag } + + val enumParser = EnumParser { fromTagOrDefault(it) } + + /** + * Get HttpMethodType from tag or POST if not found + * @param tag the tag + * @return MethodType corresponding to tag. POST if invalid tag. + */ + fun fromTagOrDefault(tag: String): HttpMethodType { + return tagMap[tag] ?: POST + } + } +} diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/Webhook.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/Webhook.kt index 55a4cb3e..09dbfe9d 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/Webhook.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/Webhook.kt @@ -35,6 +35,7 @@ import org.opensearch.common.xcontent.XContentBuilder import org.opensearch.common.xcontent.XContentParser import org.opensearch.common.xcontent.XContentParserUtils import org.opensearch.commons.notifications.NotificationConstants.HEADER_PARAMS_TAG +import org.opensearch.commons.notifications.NotificationConstants.METHOD_TAG import org.opensearch.commons.notifications.NotificationConstants.URL_TAG import org.opensearch.commons.utils.STRING_READER import org.opensearch.commons.utils.STRING_WRITER @@ -47,7 +48,8 @@ import java.io.IOException */ data class Webhook( val url: String, - val headerParams: Map = mapOf() + val headerParams: Map = mapOf(), + val method: HttpMethodType = HttpMethodType.POST ) : BaseConfigData { init { @@ -77,6 +79,7 @@ data class Webhook( fun parse(parser: XContentParser): Webhook { var url: String? = null var headerParams: Map = mapOf() + var method = HttpMethodType.POST XContentParserUtils.ensureExpectedToken( XContentParser.Token.START_OBJECT, @@ -89,6 +92,7 @@ data class Webhook( when (fieldName) { URL_TAG -> url = parser.text() HEADER_PARAMS_TAG -> headerParams = parser.mapStrings() + METHOD_TAG -> method = HttpMethodType.fromTagOrDefault(parser.text()) else -> { parser.skipChildren() log.info("Unexpected field: $fieldName, while parsing Webhook destination") @@ -96,7 +100,7 @@ data class Webhook( } } url ?: throw IllegalArgumentException("$URL_TAG field absent") - return Webhook(url, headerParams) + return Webhook(url, headerParams, method) } } @@ -108,6 +112,7 @@ data class Webhook( return builder.startObject() .field(URL_TAG, url) .field(HEADER_PARAMS_TAG, headerParams) + .field(METHOD_TAG, method.tag) .endObject() } @@ -117,7 +122,8 @@ data class Webhook( */ constructor(input: StreamInput) : this( url = input.readString(), - headerParams = input.readMap(STRING_READER, STRING_READER) + headerParams = input.readMap(STRING_READER, STRING_READER), + method = input.readEnum(HttpMethodType::class.java) ) /** @@ -126,5 +132,6 @@ data class Webhook( override fun writeTo(output: StreamOutput) { output.writeString(url) output.writeMap(headerParams, STRING_WRITER, STRING_WRITER) + output.writeEnum(method) } } diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/WebhookTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/WebhookTests.kt index 9ca39c7c..48dedf49 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/WebhookTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/WebhookTests.kt @@ -46,7 +46,11 @@ internal class WebhookTests { @Test fun `Webhook serialize and deserialize using json object should be equal`() { - val sampleWebhook = Webhook("https://domain.com/sample_url#1234567890", mapOf(Pair("key", "value"))) + val sampleWebhook = Webhook( + "https://domain.com/sample_url#1234567890", + mapOf(Pair("key", "value")), + HttpMethodType.PUT + ) val jsonString = getJsonString(sampleWebhook) val recreatedObject = createObjectFromJsonString(jsonString) { Webhook.parse(it) } assertEquals(sampleWebhook, recreatedObject) @@ -54,13 +58,18 @@ internal class WebhookTests { @Test fun `Webhook should deserialize json object using parser`() { - val sampleWebhook = Webhook("https://domain.com/sample_url#1234567890", mapOf(Pair("key", "value"))) + val sampleWebhook = Webhook( + "https://domain.com/sample_url#1234567890", + mapOf(Pair("key", "value")), + HttpMethodType.PATCH + ) val jsonString = """ { "url":"${sampleWebhook.url}", "header_params":{ "key":"value" - } + }, + "method":"PATCH" } """.trimIndent() val recreatedObject = createObjectFromJsonString(jsonString) { Webhook.parse(it) } From 87b84949ae479dd923b5939462ed5ff9a86d85b0 Mon Sep 17 00:00:00 2001 From: Chen Dai <46505291+dai-chen@users.noreply.github.com> Date: Tue, 20 Jul 2021 09:37:48 -0700 Subject: [PATCH 073/140] Fix class loader issue for notifications response (#40) * Fix class loader issue for notifications Signed-off-by: Joshua Li * Fix formatting Signed-off-by: Joshua Li * Refactor creation of action listener object Signed-off-by: Joshua Li * Fix indentation Signed-off-by: Joshua Li * Remove unused suppresses Signed-off-by: Joshua Li * Add UT for notification API Signed-off-by: Chen Dai * Add UT for notification API Signed-off-by: Chen Dai * Add UT for send notification API Signed-off-by: Chen Dai * Fix Github workflow failure Signed-off-by: Chen Dai * Fix Github workflow failure Signed-off-by: Chen Dai * Refactor UT code Signed-off-by: Chen Dai Co-authored-by: Joshua Li Signed-off-by: Zelin Hao --- .../NotificationsPluginInterface.kt | 43 ++- .../NotificationsPluginInterfaceTests.kt | 268 ++++++++++++++++++ .../org.mockito.plugins.MockMaker | 1 + 3 files changed, 304 insertions(+), 8 deletions(-) create mode 100644 src/test/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterfaceTests.kt create mode 100644 src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker diff --git a/src/main/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterface.kt b/src/main/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterface.kt index e82aaba8..2f043351 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterface.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterface.kt @@ -27,8 +27,11 @@ package org.opensearch.commons.notifications import org.opensearch.action.ActionListener +import org.opensearch.action.ActionResponse import org.opensearch.client.node.NodeClient +import org.opensearch.common.io.stream.Writeable import org.opensearch.commons.ConfigConstants.OPENSEARCH_SECURITY_USER_INFO_THREAD_CONTEXT +import org.opensearch.commons.notifications.action.BaseResponse import org.opensearch.commons.notifications.action.CreateNotificationConfigRequest import org.opensearch.commons.notifications.action.CreateNotificationConfigResponse import org.opensearch.commons.notifications.action.DeleteNotificationConfigRequest @@ -56,6 +59,7 @@ import org.opensearch.commons.notifications.action.UpdateNotificationConfigRespo import org.opensearch.commons.notifications.model.ChannelMessage import org.opensearch.commons.notifications.model.EventSource import org.opensearch.commons.utils.SecureClientWrapper +import org.opensearch.commons.utils.recreateObject /** * All the transport action plugin interfaces for the Notification plugin @@ -76,7 +80,7 @@ object NotificationsPluginInterface { client.execute( CREATE_NOTIFICATION_CONFIG_ACTION_TYPE, request, - listener + wrapActionListener(listener) { response -> recreateObject(response) { CreateNotificationConfigResponse(it) } } ) } @@ -94,7 +98,7 @@ object NotificationsPluginInterface { client.execute( UPDATE_NOTIFICATION_CONFIG_ACTION_TYPE, request, - listener + wrapActionListener(listener) { response -> recreateObject(response) { UpdateNotificationConfigResponse(it) } } ) } @@ -112,7 +116,7 @@ object NotificationsPluginInterface { client.execute( DELETE_NOTIFICATION_CONFIG_ACTION_TYPE, request, - listener + wrapActionListener(listener) { response -> recreateObject(response) { DeleteNotificationConfigResponse(it) } } ) } @@ -130,7 +134,7 @@ object NotificationsPluginInterface { client.execute( GET_NOTIFICATION_CONFIG_ACTION_TYPE, request, - listener + wrapActionListener(listener) { response -> recreateObject(response) { GetNotificationConfigResponse(it) } } ) } @@ -148,7 +152,7 @@ object NotificationsPluginInterface { client.execute( GET_NOTIFICATION_EVENT_ACTION_TYPE, request, - listener + wrapActionListener(listener) { response -> recreateObject(response) { GetNotificationEventResponse(it) } } ) } @@ -166,7 +170,7 @@ object NotificationsPluginInterface { client.execute( GET_PLUGIN_FEATURES_ACTION_TYPE, request, - listener + wrapActionListener(listener) { response -> recreateObject(response) { GetPluginFeaturesResponse(it) } } ) } @@ -184,7 +188,7 @@ object NotificationsPluginInterface { client.execute( GET_FEATURE_CHANNEL_LIST_ACTION_TYPE, request, - listener + wrapActionListener(listener) { response -> recreateObject(response) { GetFeatureChannelListResponse(it) } } ) } @@ -209,7 +213,30 @@ object NotificationsPluginInterface { wrapper.execute( SEND_NOTIFICATION_ACTION_TYPE, SendNotificationRequest(eventSource, channelMessage, channelIds, threadContext), - listener + wrapActionListener(listener) { response -> recreateObject(response) { SendNotificationResponse(it) } } ) } + + /** + * Wrap action listener on concrete response class by a new created one on ActionResponse. + * This is required because the response may be loaded by different classloader across plugins. + * The onResponse(ActionResponse) avoids type cast exception and give a chance to recreate + * the response object. + */ + @Suppress("UNCHECKED_CAST") + private fun wrapActionListener( + listener: ActionListener, + recreate: (Writeable) -> Response + ): ActionListener { + return object : ActionListener { + override fun onResponse(response: ActionResponse) { + val recreated = response as? Response ?: recreate(response) + listener.onResponse(recreated) + } + + override fun onFailure(exception: java.lang.Exception) { + listener.onFailure(exception) + } + } as ActionListener + } } diff --git a/src/test/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterfaceTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterfaceTests.kt new file mode 100644 index 00000000..99f558f4 --- /dev/null +++ b/src/test/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterfaceTests.kt @@ -0,0 +1,268 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + * + * Modifications Copyright OpenSearch Contributors. See + * GitHub history for details. + */ +package org.opensearch.commons.notifications + +import com.nhaarman.mockitokotlin2.whenever +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.extension.ExtendWith +import org.mockito.Answers +import org.mockito.ArgumentMatchers.eq +import org.mockito.Mock +import org.mockito.Mockito.any +import org.mockito.Mockito.doAnswer +import org.mockito.Mockito.mock +import org.mockito.Mockito.times +import org.mockito.Mockito.verify +import org.mockito.junit.jupiter.MockitoExtension +import org.opensearch.action.ActionListener +import org.opensearch.action.ActionType +import org.opensearch.client.node.NodeClient +import org.opensearch.commons.notifications.action.CreateNotificationConfigRequest +import org.opensearch.commons.notifications.action.CreateNotificationConfigResponse +import org.opensearch.commons.notifications.action.DeleteNotificationConfigRequest +import org.opensearch.commons.notifications.action.DeleteNotificationConfigResponse +import org.opensearch.commons.notifications.action.GetFeatureChannelListRequest +import org.opensearch.commons.notifications.action.GetFeatureChannelListResponse +import org.opensearch.commons.notifications.action.GetNotificationConfigRequest +import org.opensearch.commons.notifications.action.GetNotificationConfigResponse +import org.opensearch.commons.notifications.action.GetNotificationEventRequest +import org.opensearch.commons.notifications.action.GetNotificationEventResponse +import org.opensearch.commons.notifications.action.GetPluginFeaturesRequest +import org.opensearch.commons.notifications.action.GetPluginFeaturesResponse +import org.opensearch.commons.notifications.action.SendNotificationResponse +import org.opensearch.commons.notifications.action.UpdateNotificationConfigRequest +import org.opensearch.commons.notifications.action.UpdateNotificationConfigResponse +import org.opensearch.commons.notifications.model.ChannelMessage +import org.opensearch.commons.notifications.model.ConfigType +import org.opensearch.commons.notifications.model.DeliveryStatus +import org.opensearch.commons.notifications.model.EventSource +import org.opensearch.commons.notifications.model.EventStatus +import org.opensearch.commons.notifications.model.Feature +import org.opensearch.commons.notifications.model.FeatureChannel +import org.opensearch.commons.notifications.model.FeatureChannelList +import org.opensearch.commons.notifications.model.NotificationConfig +import org.opensearch.commons.notifications.model.NotificationConfigInfo +import org.opensearch.commons.notifications.model.NotificationConfigSearchResult +import org.opensearch.commons.notifications.model.NotificationEvent +import org.opensearch.commons.notifications.model.NotificationEventInfo +import org.opensearch.commons.notifications.model.NotificationEventSearchResult +import org.opensearch.commons.notifications.model.SeverityType +import org.opensearch.commons.notifications.model.Slack +import org.opensearch.rest.RestStatus +import java.time.Instant +import java.util.EnumSet + +@Suppress("UNCHECKED_CAST") +@ExtendWith(MockitoExtension::class) +internal class NotificationsPluginInterfaceTests { + + @Mock(answer = Answers.RETURNS_DEEP_STUBS) + private lateinit var client: NodeClient + + @Test + fun createNotificationConfig() { + val request = mock(CreateNotificationConfigRequest::class.java) + val response = CreateNotificationConfigResponse("configId") + val listener: ActionListener = + mock(ActionListener::class.java) as ActionListener + + doAnswer { + (it.getArgument(2) as ActionListener) + .onResponse(response) + }.whenever(client).execute(any(ActionType::class.java), any(), any()) + + NotificationsPluginInterface.createNotificationConfig(client, request, listener) + verify(listener, times(1)).onResponse(eq(response)) + } + + @Test + fun updateNotificationConfig() { + val request = mock(UpdateNotificationConfigRequest::class.java) + val response = UpdateNotificationConfigResponse("configId") + val listener: ActionListener = + mock(ActionListener::class.java) as ActionListener + + doAnswer { + (it.getArgument(2) as ActionListener) + .onResponse(response) + }.whenever(client).execute(any(ActionType::class.java), any(), any()) + + NotificationsPluginInterface.updateNotificationConfig(client, request, listener) + verify(listener, times(1)).onResponse(eq(response)) + } + + @Test + fun deleteNotificationConfig() { + val request = mock(DeleteNotificationConfigRequest::class.java) + val response = DeleteNotificationConfigResponse(mapOf(Pair("sample_config_id", RestStatus.OK))) + val listener: ActionListener = + mock(ActionListener::class.java) as ActionListener + + doAnswer { + (it.getArgument(2) as ActionListener) + .onResponse(response) + }.whenever(client).execute(any(ActionType::class.java), any(), any()) + + NotificationsPluginInterface.deleteNotificationConfig(client, request, listener) + verify(listener, times(1)).onResponse(eq(response)) + } + + @Test + fun getNotificationConfig() { + val request = mock(GetNotificationConfigRequest::class.java) + val response = mockGetNotificationConfigResponse() + val listener: ActionListener = + mock(ActionListener::class.java) as ActionListener + + doAnswer { + (it.getArgument(2) as ActionListener) + .onResponse(response) + }.whenever(client).execute(any(ActionType::class.java), any(), any()) + + NotificationsPluginInterface.getNotificationConfig(client, request, listener) + verify(listener, times(1)).onResponse(eq(response)) + } + + @Test + fun getNotificationEvent() { + val request = mock(GetNotificationEventRequest::class.java) + val response = mockGetNotificationEventResponse() + val listener: ActionListener = + mock(ActionListener::class.java) as ActionListener + + doAnswer { + (it.getArgument(2) as ActionListener) + .onResponse(response) + }.whenever(client).execute(any(ActionType::class.java), any(), any()) + + NotificationsPluginInterface.getNotificationEvent(client, request, listener) + verify(listener, times(1)).onResponse(eq(response)) + } + + @Test + fun getPluginFeatures() { + val request = mock(GetPluginFeaturesRequest::class.java) + val response = GetPluginFeaturesResponse( + listOf("config_type_1", "config_type_2", "config_type_3"), + mapOf( + Pair("FeatureKey1", "FeatureValue1"), + Pair("FeatureKey2", "FeatureValue2"), + Pair("FeatureKey3", "FeatureValue3") + ) + ) + val listener: ActionListener = + mock(ActionListener::class.java) as ActionListener + + doAnswer { + (it.getArgument(2) as ActionListener) + .onResponse(response) + }.whenever(client).execute(any(ActionType::class.java), any(), any()) + + NotificationsPluginInterface.getPluginFeatures(client, request, listener) + verify(listener, times(1)).onResponse(eq(response)) + } + + @Test + fun getFeatureChannelList() { + val sampleConfig = FeatureChannel( + "config_id", + "name", + "description", + ConfigType.SLACK + ) + + val request = mock(GetFeatureChannelListRequest::class.java) + val response = GetFeatureChannelListResponse(FeatureChannelList(sampleConfig)) + val listener: ActionListener = + mock(ActionListener::class.java) as ActionListener + + doAnswer { + (it.getArgument(2) as ActionListener) + .onResponse(response) + }.whenever(client).execute(any(ActionType::class.java), any(), any()) + + NotificationsPluginInterface.getFeatureChannelList(client, request, listener) + verify(listener, times(1)).onResponse(eq(response)) + } + + @Test + fun sendNotification() { + val notificationInfo = EventSource( + "title", + "reference_id", + Feature.REPORTS, + SeverityType.HIGH, + listOf("tag1", "tag2") + ) + val channelMessage = ChannelMessage( + "text_description", + "htmlDescription", + null + ) + + val response = SendNotificationResponse("configId") + val listener: ActionListener = + mock(ActionListener::class.java) as ActionListener + + doAnswer { + (it.getArgument(2) as ActionListener) + .onResponse(response) + }.whenever(client).execute(any(ActionType::class.java), any(), any()) + + NotificationsPluginInterface.sendNotification( + client, notificationInfo, channelMessage, listOf("channelId1", "channelId2"), listener + ) + verify(listener, times(1)).onResponse(eq(response)) + } + + private fun mockGetNotificationConfigResponse(): GetNotificationConfigResponse { + val sampleSlack = Slack("https://domain.com/sample_url#1234567890") + val sampleConfig = NotificationConfig( + "name", + "description", + ConfigType.SLACK, + EnumSet.of(Feature.REPORTS), + configData = sampleSlack + ) + val configInfo = NotificationConfigInfo( + "config_id", + Instant.now(), + Instant.now(), + "tenant", + sampleConfig + ) + return GetNotificationConfigResponse(NotificationConfigSearchResult(configInfo)) + } + + private fun mockGetNotificationEventResponse(): GetNotificationEventResponse { + val sampleEventSource = EventSource( + "title", + "reference_id", + Feature.ALERTING, + severity = SeverityType.INFO + ) + val sampleStatus = EventStatus( + "config_id", + "name", + ConfigType.SLACK, + deliveryStatus = DeliveryStatus("404", "invalid recipient") + ) + val sampleEvent = NotificationEvent(sampleEventSource, listOf(sampleStatus)) + val eventInfo = NotificationEventInfo( + "event_id", + Instant.now(), + Instant.now(), + "tenant", + sampleEvent + ) + return GetNotificationEventResponse(NotificationEventSearchResult(eventInfo)) + } +} diff --git a/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker b/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker new file mode 100644 index 00000000..ca6ee9ce --- /dev/null +++ b/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker @@ -0,0 +1 @@ +mock-maker-inline \ No newline at end of file From c3086f4f0f27baa70a856662ea8e93d39b8b8032 Mon Sep 17 00:00:00 2001 From: Zhongnan Su Date: Mon, 2 Aug 2021 10:34:23 -0700 Subject: [PATCH 074/140] remove restrictions on webhook url protocols to also include http (#43) Signed-off-by: Zelin Hao --- .../org/opensearch/commons/utils/ValidationHelpers.kt | 6 +----- .../opensearch/commons/notifications/model/ChimeTests.kt | 6 +++--- .../opensearch/commons/notifications/model/SlackTests.kt | 6 +++--- .../commons/notifications/model/WebhookTests.kt | 8 ++++---- 4 files changed, 11 insertions(+), 15 deletions(-) diff --git a/src/main/kotlin/org/opensearch/commons/utils/ValidationHelpers.kt b/src/main/kotlin/org/opensearch/commons/utils/ValidationHelpers.kt index 93bcdc77..0124179f 100644 --- a/src/main/kotlin/org/opensearch/commons/utils/ValidationHelpers.kt +++ b/src/main/kotlin/org/opensearch/commons/utils/ValidationHelpers.kt @@ -34,9 +34,6 @@ private val VALID_ID_CHARS: Set = (('a'..'z') + ('A'..'Z') + ('0'..'9') + fun validateUrl(urlString: String) { require(isValidUrl(urlString)) { "Invalid URL or unsupported" } - val url = URL(urlString) - require("https" == url.protocol) // Support only HTTPS. HTTP and other protocols not supported - // TODO : Add hosts deny list } fun validateEmail(email: String) { @@ -49,8 +46,7 @@ fun validateId(idString: String) { fun isValidUrl(urlString: String): Boolean { val url = URL(urlString) // throws MalformedURLException if URL is invalid - // TODO : Add hosts deny list - return ("https" == url.protocol) // Support only HTTPS. HTTP and other protocols not supported + return ("https" == url.protocol || "http" == url.protocol) // Support only http/https, other protocols not supported } /** diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/ChimeTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/ChimeTests.kt index f70dc097..da404b28 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/ChimeTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/ChimeTests.kt @@ -89,11 +89,11 @@ internal class ChimeTests { } @Test - fun `Chime should throw exception when url protocol is not https`() { + fun `Chime should throw exception when url protocol is not https or http`() { assertThrows { - Chime("http://domain.com/sample_url#1234567890") + Chime("ftp://domain.com/sample_url#1234567890") } - val jsonString = "{\"url\":\"http://domain.com/sample_url\"}" + val jsonString = "{\"url\":\"ftp://domain.com/sample_url\"}" assertThrows { createObjectFromJsonString(jsonString) { Chime.parse(it) } } diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/SlackTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/SlackTests.kt index b5bf7783..98fbc0cd 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/SlackTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/SlackTests.kt @@ -89,11 +89,11 @@ internal class SlackTests { } @Test - fun `Slack should throw exception when url protocol is not https`() { + fun `Slack should throw exception when url protocol is not https or http`() { assertThrows { - Slack("http://domain.com/sample_url#1234567890") + Slack("ftp://domain.com/sample_url#1234567890") } - val jsonString = "{\"url\":\"http://domain.com/sample_url\"}" + val jsonString = "{\"url\":\"ftp://domain.com/sample_url\"}" assertThrows { createObjectFromJsonString(jsonString) { Slack.parse(it) } } diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/WebhookTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/WebhookTests.kt index 48dedf49..5a717669 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/WebhookTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/WebhookTests.kt @@ -47,7 +47,7 @@ internal class WebhookTests { @Test fun `Webhook serialize and deserialize using json object should be equal`() { val sampleWebhook = Webhook( - "https://domain.com/sample_url#1234567890", + "http://domain.com/sample_url#1234567890", mapOf(Pair("key", "value")), HttpMethodType.PUT ) @@ -105,11 +105,11 @@ internal class WebhookTests { } @Test - fun `Webhook should throw exception when url protocol is not https`() { + fun `Webhook should throw exception when url protocol is not https or http`() { assertThrows { - Webhook("http://domain.com/sample_url#1234567890") + Webhook("ftp://domain.com/sample_url#1234567890") } - val jsonString = "{\"url\":\"http://domain.com/sample_url\"}" + val jsonString = "{\"url\":\"ftp://domain.com/sample_url\"}" assertThrows { createObjectFromJsonString(jsonString) { Webhook.parse(it) } } From fa074e904fe360dfd0931980888b4d4f59e8d544 Mon Sep 17 00:00:00 2001 From: Sarat Vemulapalli Date: Fri, 6 Aug 2021 09:43:06 -0700 Subject: [PATCH 075/140] Bumping common-utils to build with OpenSearch(main) 1.1.0 (#48) Signed-off-by: Sarat Vemulapalli Signed-off-by: Zelin Hao --- .github/workflows/ci.yml | 6 +++--- build.gradle | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f49c13b9..4f0adf94 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -31,7 +31,7 @@ jobs: with: repository: 'opensearch-project/OpenSearch' path: OpenSearch - ref: '1.0' + ref: 'main' - name: Build OpenSearch working-directory: ./OpenSearch run: ./gradlew publishToMavenLocal -Dbuild.snapshot=false @@ -39,11 +39,11 @@ jobs: # common-utils - name: Build and Test run: | - ./gradlew build -Dopensearch.version=1.0.0 + ./gradlew build -Dopensearch.version=1.1.0 - name: Publish to Maven Local run: | - ./gradlew publishToMavenLocal -Dopensearch.version=1.0.0 + ./gradlew publishToMavenLocal -Dopensearch.version=1.1.0 - name: Upload Coverage Report uses: codecov/codecov-action@v1 diff --git a/build.gradle b/build.gradle index 2d955951..0f2b241a 100644 --- a/build.gradle +++ b/build.gradle @@ -12,7 +12,7 @@ buildscript { ext { opensearch_group = "org.opensearch" - opensearch_version = System.getProperty("opensearch.version", "1.0.0") + opensearch_version = System.getProperty("opensearch.version", "1.1.0") kotlin_version = System.getProperty("kotlin.version", "1.4.32") } @@ -146,7 +146,7 @@ task javadocJar(type: Jar) { from javadoc.destinationDir } -version '1.0.0.0' +version '1.1.0.0' publishing { publications { From 40dcad53a113efb912111072d201cdd49bd98772 Mon Sep 17 00:00:00 2001 From: Ravi <6005951+thalurur@users.noreply.github.com> Date: Fri, 6 Aug 2021 09:47:39 -0700 Subject: [PATCH 076/140] Adding an utility method that allows consumers to set custom thread context property in InjectSecurity class (#47) Signed-off-by: Ravi Thaluru Signed-off-by: Zelin Hao --- .../opensearch/commons/InjectSecurity.java | 17 ++++++ .../commons/InjectSecurityTest.java | 54 +++++++++++++++++++ 2 files changed, 71 insertions(+) diff --git a/src/main/java/org/opensearch/commons/InjectSecurity.java b/src/main/java/org/opensearch/commons/InjectSecurity.java index ab4f0323..2240ab60 100644 --- a/src/main/java/org/opensearch/commons/InjectSecurity.java +++ b/src/main/java/org/opensearch/commons/InjectSecurity.java @@ -160,6 +160,23 @@ public void injectRoles(final List roles) { } } + /** + * Allows one to set the property in threadContext if possible to the value provided. If not possible returns false. + * @param property + * @param value + * @return boolean + */ + public boolean injectProperty(final String property, final Object value) { + if (Strings.isNullOrEmpty(property) || value == null || threadContext.getTransient(property) != null) { + log.debug("{}, InjectSecurity - cannot inject property: {}", Thread.currentThread().getName(), id); + return false; + } else { + threadContext.putTransient(property, value); + log.debug("{}, InjectSecurity - inject property: {}", Thread.currentThread().getName(), id); + return true; + } + } + @Override public void close() { if (ctx != null) { diff --git a/src/test/java/org/opensearch/commons/InjectSecurityTest.java b/src/test/java/org/opensearch/commons/InjectSecurityTest.java index 0f6e0c83..a9073d93 100644 --- a/src/test/java/org/opensearch/commons/InjectSecurityTest.java +++ b/src/test/java/org/opensearch/commons/InjectSecurityTest.java @@ -27,13 +27,16 @@ package org.opensearch.commons; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; import static org.opensearch.commons.ConfigConstants.INJECTED_USER; import static org.opensearch.commons.ConfigConstants.OPENSEARCH_SECURITY_INJECTED_ROLES; import static org.opensearch.commons.ConfigConstants.OPENSEARCH_SECURITY_USE_INJECTED_USER_FOR_PLUGINS; import java.util.Arrays; +import java.util.Map; import org.junit.jupiter.api.Test; import org.opensearch.common.settings.Settings; @@ -102,4 +105,55 @@ public void testInjectUser() { assertEquals("plugin", threadContext.getTransient("ctx.name")); assertNull(threadContext.getTransient(INJECTED_USER)); } + + @Test + public void testInjectProperty() { + Settings settings = Settings.builder().put(OPENSEARCH_SECURITY_USE_INJECTED_USER_FOR_PLUGINS, false).build(); + Settings headerSettings = Settings.builder().put("request.headers.default", "1").build(); + ThreadContext threadContext = new ThreadContext(headerSettings); + threadContext.putHeader("name", "opendistro"); + threadContext.putTransient("ctx.name", "plugin"); + + assertEquals("1", threadContext.getHeader("default")); + assertEquals("opendistro", threadContext.getHeader("name")); + assertEquals("plugin", threadContext.getTransient("ctx.name")); + + try (InjectSecurity helper = new InjectSecurity("test-name", settings, threadContext)) { + helper.inject("joe", Arrays.asList("ops-role", "logs-role")); + assertEquals("1", threadContext.getHeader("default")); + assertEquals("opendistro", threadContext.getHeader("name")); + assertEquals("plugin", threadContext.getTransient("ctx.name")); + assertNotNull(threadContext.getTransient(OPENSEARCH_SECURITY_INJECTED_ROLES)); + // cannot inject property that is already set + assertFalse(helper.injectProperty(OPENSEARCH_SECURITY_INJECTED_ROLES, "new value")); + assertEquals("plugin|ops-role,logs-role", threadContext.getTransient(OPENSEARCH_SECURITY_INJECTED_ROLES)); + // cannot inject invalid property/value + assertFalse(helper.injectProperty("", "new value")); + assertFalse(helper.injectProperty(null, "new value")); + assertFalse(helper.injectProperty("property", null)); + // can inject non-set valid properties + assertTrue(helper.injectProperty("property1", true)); + assertTrue(helper.injectProperty("property2", "some value")); + assertTrue(helper.injectProperty("property3", "")); + assertTrue(helper.injectProperty("property4", Map.of("key", "value"))); + // verify the set properties are not null and equal to what was set + assertNull(threadContext.getTransient("property")); + assertNotNull(threadContext.getTransient("property1")); + assertEquals(true, threadContext.getTransient("property1")); + assertNotNull(threadContext.getTransient("property2")); + assertEquals("some value", threadContext.getTransient("property2")); + assertNotNull(threadContext.getTransient("property3")); + assertEquals("", threadContext.getTransient("property3")); + assertNotNull(threadContext.getTransient("property4")); + assertEquals(Map.of("key", "value"), threadContext.getTransient("property4")); + } + assertEquals("1", threadContext.getHeader("default")); + assertEquals("opendistro", threadContext.getHeader("name")); + assertEquals("plugin", threadContext.getTransient("ctx.name")); + assertNull(threadContext.getTransient(OPENSEARCH_SECURITY_INJECTED_ROLES)); + assertNull(threadContext.getTransient("property1")); + assertNull(threadContext.getTransient("property2")); + assertNull(threadContext.getTransient("property3")); + assertNull(threadContext.getTransient("property4")); + } } From 5faa50518a750dfc1445c05a083298fdabc2a0d9 Mon Sep 17 00:00:00 2001 From: Joshua Date: Mon, 9 Aug 2021 15:00:19 -0700 Subject: [PATCH 077/140] Add Notifications SNS model (#50) Signed-off-by: Zelin Hao --- .../notifications/NotificationConstants.kt | 2 + .../commons/notifications/model/ConfigType.kt | 5 + .../notifications/model/EventStatus.kt | 1 + .../commons/notifications/model/SNS.kt | 112 ++++++++++++++++++ .../model/config/ConfigDataProperties.kt | 3 + .../commons/utils/ValidationHelpers.kt | 6 + .../commons/notifications/model/SNSTests.kt | 105 ++++++++++++++++ 7 files changed, 234 insertions(+) create mode 100644 src/main/kotlin/org/opensearch/commons/notifications/model/SNS.kt create mode 100644 src/test/kotlin/org/opensearch/commons/notifications/model/SNSTests.kt diff --git a/src/main/kotlin/org/opensearch/commons/notifications/NotificationConstants.kt b/src/main/kotlin/org/opensearch/commons/notifications/NotificationConstants.kt index 344cf0b8..04f3affe 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/NotificationConstants.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/NotificationConstants.kt @@ -42,6 +42,8 @@ object NotificationConstants { const val TAGS_TAG = "tags" const val URL_TAG = "url" const val HEADER_PARAMS_TAG = "header_params" + const val TOPIC_ARN_FIELD = "topic_arn" + const val ROLE_ARN_FIELD = "role_arn" const val HOST_TAG = "host" const val PORT_TAG = "port" const val METHOD_TAG = "method" diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/ConfigType.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/ConfigType.kt index 0dbe70a6..d5400a75 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/ConfigType.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/ConfigType.kt @@ -57,6 +57,11 @@ enum class ConfigType(val tag: String) { return tag } }, + SNS("sns") { + override fun toString(): String { + return tag + } + }, SMTP_ACCOUNT("smtp_account") { override fun toString(): String { return tag diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/EventStatus.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/EventStatus.kt index 1233a997..bf72836d 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/EventStatus.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/EventStatus.kt @@ -64,6 +64,7 @@ data class EventStatus( ConfigType.WEBHOOK -> requireNotNull(deliveryStatus) ConfigType.SLACK -> requireNotNull(deliveryStatus) ConfigType.EMAIL -> require(emailRecipientStatus.isNotEmpty()) + ConfigType.SNS -> requireNotNull(deliveryStatus) ConfigType.NONE -> log.info("Some config field not recognized") else -> { log.info("non-allowed config type for Status") diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/SNS.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/SNS.kt new file mode 100644 index 00000000..12cdba4f --- /dev/null +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/SNS.kt @@ -0,0 +1,112 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + * + * Modifications Copyright OpenSearch Contributors. See + * GitHub history for details. + */ +package org.opensearch.commons.notifications.model + +import org.opensearch.common.io.stream.StreamInput +import org.opensearch.common.io.stream.StreamOutput +import org.opensearch.common.io.stream.Writeable +import org.opensearch.common.xcontent.ToXContent +import org.opensearch.common.xcontent.XContentBuilder +import org.opensearch.common.xcontent.XContentParser +import org.opensearch.common.xcontent.XContentParserUtils +import org.opensearch.commons.notifications.NotificationConstants.ROLE_ARN_FIELD +import org.opensearch.commons.notifications.NotificationConstants.TOPIC_ARN_FIELD +import org.opensearch.commons.utils.fieldIfNotNull +import org.opensearch.commons.utils.logger +import org.opensearch.commons.utils.validateIAMRoleArn +import java.io.IOException +import java.util.regex.Pattern + +/** + * SNS notification data model + */ +data class SNS(val topicARN: String, val roleARN: String?) : BaseConfigData { + + init { + require(SNS_ARN_REGEX.matcher(topicARN).find()) { "Invalid AWS SNS topic ARN: $topicARN" } + if (roleARN != null) { + validateIAMRoleArn(roleARN) + } + } + + override fun toXContent(builder: XContentBuilder, params: ToXContent.Params): XContentBuilder { + return builder.startObject() + .field(TOPIC_ARN_FIELD, topicARN) + .fieldIfNotNull(ROLE_ARN_FIELD, roleARN) + .endObject() + } + + /** + * Constructor used in transport action communication. + * @param input StreamInput stream to deserialize data from. + */ + constructor(input: StreamInput) : this( + topicARN = input.readString(), + roleARN = input.readOptionalString() + ) + + @Throws(IOException::class) + override fun writeTo(out: StreamOutput) { + out.writeString(topicARN) + out.writeOptionalString(roleARN) + } + + companion object { + private val log by logger(SNS::class.java) + + private val SNS_ARN_REGEX = + Pattern.compile("^arn:aws(-[^:]+)?:sns:([a-zA-Z0-9-]+):([0-9]{12}):([a-zA-Z0-9-_]+)$") + + /** + * reader to create instance of class from writable. + */ + val reader = Writeable.Reader { SNS(it) } + + /** + * Parser to parse xContent + */ + val xParser = XParser { parse(it) } + + @JvmStatic + @Throws(IOException::class) + fun parse(xcp: XContentParser): SNS { + var topicARN: String? = null + var roleARN: String? = null + + XContentParserUtils.ensureExpectedToken(XContentParser.Token.START_OBJECT, xcp.currentToken(), xcp) + while (xcp.nextToken() != XContentParser.Token.END_OBJECT) { + val fieldName = xcp.currentName() + xcp.nextToken() + when (fieldName) { + TOPIC_ARN_FIELD -> topicARN = xcp.textOrNull() + ROLE_ARN_FIELD -> roleARN = xcp.textOrNull() + else -> { + xcp.skipChildren() + log.info("Unexpected field: $fieldName, while parsing SNS destination") + } + } + } + topicARN ?: throw IllegalArgumentException("$TOPIC_ARN_FIELD field absent") + return SNS(topicARN, roleARN) + } + + @JvmStatic + @Throws(IOException::class) + fun readFrom(sin: StreamInput): SNS? { + return if (sin.readBoolean()) { + SNS( + topicARN = sin.readString(), + roleARN = sin.readOptionalString() + ) + } else null + } + } +} diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/config/ConfigDataProperties.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/config/ConfigDataProperties.kt index 1500879c..34bd2edc 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/config/ConfigDataProperties.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/config/ConfigDataProperties.kt @@ -33,6 +33,7 @@ import org.opensearch.commons.notifications.model.Chime import org.opensearch.commons.notifications.model.ConfigType import org.opensearch.commons.notifications.model.Email import org.opensearch.commons.notifications.model.EmailGroup +import org.opensearch.commons.notifications.model.SNS import org.opensearch.commons.notifications.model.Slack import org.opensearch.commons.notifications.model.SmtpAccount import org.opensearch.commons.notifications.model.Webhook @@ -53,6 +54,7 @@ internal object ConfigDataProperties { Pair(ConfigType.CHIME, ConfigProperty(Chime.reader, Chime.xParser)), Pair(ConfigType.WEBHOOK, ConfigProperty(Webhook.reader, Webhook.xParser)), Pair(ConfigType.EMAIL, ConfigProperty(Email.reader, Email.xParser)), + Pair(ConfigType.SNS, ConfigProperty(SNS.reader, SNS.xParser)), Pair(ConfigType.EMAIL_GROUP, ConfigProperty(EmailGroup.reader, EmailGroup.xParser)), Pair(ConfigType.SMTP_ACCOUNT, ConfigProperty(SmtpAccount.reader, SmtpAccount.xParser)) ) @@ -78,6 +80,7 @@ internal object ConfigDataProperties { ConfigType.EMAIL_GROUP -> configData is EmailGroup ConfigType.SMTP_ACCOUNT -> configData is SmtpAccount ConfigType.CHIME -> configData is Chime + ConfigType.SNS -> configData is SNS ConfigType.NONE -> true } } diff --git a/src/main/kotlin/org/opensearch/commons/utils/ValidationHelpers.kt b/src/main/kotlin/org/opensearch/commons/utils/ValidationHelpers.kt index 0124179f..fc117923 100644 --- a/src/main/kotlin/org/opensearch/commons/utils/ValidationHelpers.kt +++ b/src/main/kotlin/org/opensearch/commons/utils/ValidationHelpers.kt @@ -28,6 +28,7 @@ package org.opensearch.commons.utils import java.net.URL +import java.util.regex.Pattern // Valid ID characters = (All Base64 chars + "_-") to support UUID format and Base64 encoded IDs private val VALID_ID_CHARS: Set = (('a'..'z') + ('A'..'Z') + ('0'..'9') + '+' + '/' + '_' + '-').toSet() @@ -69,3 +70,8 @@ fun isValidEmail(email: String): Boolean { fun isValidId(idString: String): Boolean { return idString.isNotBlank() && idString.all { VALID_ID_CHARS.contains(it) } } + +fun validateIAMRoleArn(roleARN: String) { + val roleArnRegex = Pattern.compile("^arn:aws(-[^:]+)?:iam::([0-9]{12}):([a-zA-Z_0-9+=,.@\\-_/]+)$") + require(roleArnRegex.matcher(roleARN).find()) { "Invalid AWS role ARN: $roleARN " } +} diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/SNSTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/SNSTests.kt new file mode 100644 index 00000000..46d7cfc8 --- /dev/null +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/SNSTests.kt @@ -0,0 +1,105 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + * + * Modifications Copyright OpenSearch Contributors. See + * GitHub history for details. + */ + +package org.opensearch.commons.notifications.model + +import com.fasterxml.jackson.core.JsonParseException +import org.junit.jupiter.api.Assertions +import org.junit.jupiter.api.Assertions.assertThrows +import org.junit.jupiter.api.Test +import org.opensearch.commons.utils.createObjectFromJsonString +import org.opensearch.commons.utils.getJsonString +import org.opensearch.commons.utils.recreateObject + +internal class SNSTests { + + @Test + fun `SNS should throw exception if empty topic`() { + assertThrows(IllegalArgumentException::class.java) { + SNS("", null) + } + val jsonString = "{\"topic_arn\":\"\"}" + assertThrows(IllegalArgumentException::class.java) { + createObjectFromJsonString(jsonString) { SNS.parse(it) } + } + } + + @Test + fun `SNS should throw exception if invalid topic ARN`() { + assertThrows(IllegalArgumentException::class.java) { + SNS("arn:aws:es:us-east-1:012345678989:test", null) + } + val jsonString = "{\"topic_arn\":\"arn:aws:es:us-east-1:012345678989:test\"}" + assertThrows(IllegalArgumentException::class.java) { + createObjectFromJsonString(jsonString) { SNS.parse(it) } + } + } + + @Test + fun `SNS should throw exception if invalid role ARN`() { + assertThrows(IllegalArgumentException::class.java) { + SNS("arn:aws:sns:us-east-1:012345678912:topic-test", "arn:aws:iam:us-east-1:0123456789:role-test") + } + val jsonString = + "{\"topic_arn\":\"arn:aws:sns:us-east-1:012345678912:topic-test\",\"role_arn\":\"arn:aws:iam:us-east-1:0123456789:role-test\"}" + assertThrows(IllegalArgumentException::class.java) { + createObjectFromJsonString(jsonString) { SNS.parse(it) } + } + } + + @Test + fun `SNS serialize and deserialize transport object should be equal`() { + val sampleSNS = SNS("arn:aws:sns:us-east-1:012345678912:topic-test", "arn:aws:iam::012345678912:role/iam-test") + val recreatedObject = recreateObject(sampleSNS) { SNS(it) } + Assertions.assertEquals(sampleSNS, recreatedObject) + } + + @Test + fun `SNS serialize and deserialize using json object should be equal`() { + val sampleSNS = SNS("arn:aws:sns:us-east-1:012345678912:topic-test", "arn:aws:iam::012345678912:role/iam-test") + val jsonString = getJsonString(sampleSNS) + val recreatedObject = createObjectFromJsonString(jsonString) { SNS.parse(it) } + Assertions.assertEquals(sampleSNS, recreatedObject) + } + + @Test + fun `SNS should deserialize json object using parser`() { + val sampleSNS = SNS("arn:aws:sns:us-east-1:012345678912:topic-test", "arn:aws:iam::012345678912:role/iam-test") + val jsonString = "{\"topic_arn\":\"${sampleSNS.topicARN}\",\"role_arn\":\"${sampleSNS.roleARN}\"}" + val recreatedObject = createObjectFromJsonString(jsonString) { SNS.parse(it) } + Assertions.assertEquals(sampleSNS, recreatedObject) + } + + @Test + fun `SNS should throw exception when invalid json object is passed`() { + val jsonString = "sample message" + assertThrows(JsonParseException::class.java) { + createObjectFromJsonString(jsonString) { SNS.parse(it) } + } + } + + @Test + fun `SNS should throw exception when arn is replace with arn2 in json object`() { + val sampleSNS = SNS("arn:aws:sns:us-east-1:012345678912:topic-test", "arn:aws:iam::012345678912:role/iam-test") + val jsonString = "{\"topic_arn2\":\"${sampleSNS.topicARN}\",\"role_arn\":\"${sampleSNS.roleARN}\"}" + assertThrows(IllegalArgumentException::class.java) { + createObjectFromJsonString(jsonString) { SNS.parse(it) } + } + } + + @Test + fun `SNS should safely ignore extra field in json object`() { + val sampleSNS = SNS("arn:aws:sns:us-east-1:012345678912:topic-test", null) + val jsonString = "{\"topic_arn\":\"${sampleSNS.topicARN}\", \"another\":\"field\"}" + val recreatedObject = createObjectFromJsonString(jsonString) { SNS.parse(it) } + Assertions.assertEquals(sampleSNS, recreatedObject) + } +} From cb2d125ee08e48982a03f6528652faa2968d7342 Mon Sep 17 00:00:00 2001 From: Anantha Krishna Bhatta <31894175+akbhatta@users.noreply.github.com> Date: Thu, 12 Aug 2021 17:00:19 -0700 Subject: [PATCH 078/140] Added support for SesAccount (#54) Also updated Feature to be simple string for future plugin easy addition [Tests] Added unit tests for SesAccount Updated Unit tests for changes Signed-off-by: @akbhatta Signed-off-by: Zelin Hao --- .../notifications/NotificationConstants.kt | 9 +- .../action/GetFeatureChannelListRequest.kt | 13 +- .../commons/notifications/model/ConfigType.kt | 5 + .../notifications/model/EventSource.kt | 12 +- .../commons/notifications/model/Feature.kt | 71 -------- .../notifications/model/NotificationConfig.kt | 15 +- .../commons/notifications/model/SesAccount.kt | 124 ++++++++++++++ .../notifications/model/{SNS.kt => Sns.kt} | 55 +++---- .../model/config/ConfigDataProperties.kt | 9 +- .../commons/utils/ValidationHelpers.kt | 4 +- .../NotificationsPluginInterfaceTests.kt | 10 +- .../CreateNotificationConfigRequestTests.kt | 29 ++-- .../GetFeatureChannelListRequestTests.kt | 10 +- .../GetNotificationConfigResponseTests.kt | 20 +-- .../GetNotificationEventResponseTests.kt | 19 +-- .../action/SendNotificationRequestTests.kt | 12 +- .../UpdateNotificationConfigRequestTests.kt | 29 ++-- .../notifications/model/EventSourceTests.kt | 13 +- .../notifications/model/FeatureTests.kt | 56 ------- .../model/NotificationConfigInfoTests.kt | 13 +- .../NotificationConfigSearchResultsTests.kt | 23 +-- .../model/NotificationConfigTests.kt | 34 ++-- .../model/NotificationEventInfoTests.kt | 11 +- .../NotificationEventSearchResultTests.kt | 22 +-- .../model/NotificationEventTests.kt | 8 +- .../notifications/model/SesAccountTests.kt | 151 ++++++++++++++++++ .../model/{SNSTests.kt => SnsTests.kt} | 52 +++--- 27 files changed, 496 insertions(+), 333 deletions(-) delete mode 100644 src/main/kotlin/org/opensearch/commons/notifications/model/Feature.kt create mode 100644 src/main/kotlin/org/opensearch/commons/notifications/model/SesAccount.kt rename src/main/kotlin/org/opensearch/commons/notifications/model/{SNS.kt => Sns.kt} (63%) delete mode 100644 src/test/kotlin/org/opensearch/commons/notifications/model/FeatureTests.kt create mode 100644 src/test/kotlin/org/opensearch/commons/notifications/model/SesAccountTests.kt rename src/test/kotlin/org/opensearch/commons/notifications/model/{SNSTests.kt => SnsTests.kt} (65%) diff --git a/src/main/kotlin/org/opensearch/commons/notifications/NotificationConstants.kt b/src/main/kotlin/org/opensearch/commons/notifications/NotificationConstants.kt index 04f3affe..55dc9a44 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/NotificationConstants.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/NotificationConstants.kt @@ -42,8 +42,9 @@ object NotificationConstants { const val TAGS_TAG = "tags" const val URL_TAG = "url" const val HEADER_PARAMS_TAG = "header_params" - const val TOPIC_ARN_FIELD = "topic_arn" - const val ROLE_ARN_FIELD = "role_arn" + const val TOPIC_ARN_TAG = "topic_arn" + const val ROLE_ARN_TAG = "role_arn" + const val REGION_TAG = "region" const val HOST_TAG = "host" const val PORT_TAG = "port" const val METHOD_TAG = "method" @@ -69,5 +70,9 @@ object NotificationConstants { const val CONFIG_TYPE_LIST_TAG = "config_type_list" const val PLUGIN_FEATURES_TAG = "plugin_features" + const val FEATURE_ALERTING = "alerting" + const val FEATURE_INDEX_MANAGEMENT = "index_management" + const val FEATURE_REPORTS = "reports" + const val DEFAULT_MAX_ITEMS = 1000 } diff --git a/src/main/kotlin/org/opensearch/commons/notifications/action/GetFeatureChannelListRequest.kt b/src/main/kotlin/org/opensearch/commons/notifications/action/GetFeatureChannelListRequest.kt index 17e4f6fb..309a31bc 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/action/GetFeatureChannelListRequest.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/action/GetFeatureChannelListRequest.kt @@ -37,7 +37,6 @@ import org.opensearch.common.xcontent.XContentBuilder import org.opensearch.common.xcontent.XContentParser import org.opensearch.common.xcontent.XContentParserUtils import org.opensearch.commons.notifications.NotificationConstants.FEATURE_TAG -import org.opensearch.commons.notifications.model.Feature import org.opensearch.commons.utils.logger import java.io.IOException @@ -48,7 +47,7 @@ import java.io.IOException * Hence the request also contains tenant info for space isolation. */ class GetFeatureChannelListRequest : ActionRequest, ToXContentObject { - val feature: Feature + val feature: String companion object { private val log by logger(GetFeatureChannelListRequest::class.java) @@ -65,7 +64,7 @@ class GetFeatureChannelListRequest : ActionRequest, ToXContentObject { @JvmStatic @Throws(IOException::class) fun parse(parser: XContentParser): GetFeatureChannelListRequest { - var feature: Feature? = null + var feature: String? = null XContentParserUtils.ensureExpectedToken( XContentParser.Token.START_OBJECT, @@ -76,7 +75,7 @@ class GetFeatureChannelListRequest : ActionRequest, ToXContentObject { val fieldName = parser.currentName() parser.nextToken() when (fieldName) { - FEATURE_TAG -> feature = Feature.fromTagOrDefault(parser.text()) + FEATURE_TAG -> feature = parser.text() else -> { parser.skipChildren() log.info("Unexpected field: $fieldName, while parsing GetFeatureChannelListRequest") @@ -92,7 +91,7 @@ class GetFeatureChannelListRequest : ActionRequest, ToXContentObject { * constructor for creating the class * @param feature the caller plugin feature */ - constructor(feature: Feature) { + constructor(feature: String) { this.feature = feature } @@ -101,7 +100,7 @@ class GetFeatureChannelListRequest : ActionRequest, ToXContentObject { */ @Throws(IOException::class) constructor(input: StreamInput) : super(input) { - feature = input.readEnum(Feature::class.java) + feature = input.readString() } /** @@ -110,7 +109,7 @@ class GetFeatureChannelListRequest : ActionRequest, ToXContentObject { @Throws(IOException::class) override fun writeTo(output: StreamOutput) { super.writeTo(output) - output.writeEnum(feature) + output.writeString(feature) } /** diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/ConfigType.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/ConfigType.kt index d5400a75..85c10e35 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/ConfigType.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/ConfigType.kt @@ -62,6 +62,11 @@ enum class ConfigType(val tag: String) { return tag } }, + SES_ACCOUNT("ses_account") { + override fun toString(): String { + return tag + } + }, SMTP_ACCOUNT("smtp_account") { override fun toString(): String { return tag diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/EventSource.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/EventSource.kt index caf86dcd..98c46d2a 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/EventSource.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/EventSource.kt @@ -49,7 +49,7 @@ import java.io.IOException data class EventSource( val title: String, val referenceId: String, - val feature: Feature, + val feature: String, val severity: SeverityType = SeverityType.INFO, val tags: List = listOf() ) : BaseModel { @@ -75,7 +75,7 @@ data class EventSource( fun parse(parser: XContentParser): EventSource { var title: String? = null var referenceId: String? = null - var feature: Feature? = null + var feature: String? = null var severity: SeverityType = SeverityType.INFO var tags: List = emptyList() @@ -90,7 +90,7 @@ data class EventSource( when (fieldName) { TITLE_TAG -> title = parser.text() REFERENCE_ID_TAG -> referenceId = parser.text() - FEATURE_TAG -> feature = Feature.fromTagOrDefault(parser.text()) + FEATURE_TAG -> feature = parser.text() SEVERITY_TAG -> severity = SeverityType.fromTagOrDefault(parser.text()) TAGS_TAG -> tags = parser.stringList() else -> { @@ -121,7 +121,7 @@ data class EventSource( return builder.startObject() .field(TITLE_TAG, title) .field(REFERENCE_ID_TAG, referenceId) - .field(FEATURE_TAG, feature.tag) + .field(FEATURE_TAG, feature) .field(SEVERITY_TAG, severity.tag) .field(TAGS_TAG, tags) .endObject() @@ -134,7 +134,7 @@ data class EventSource( constructor(input: StreamInput) : this( title = input.readString(), referenceId = input.readString(), - feature = input.readEnum(Feature::class.java), + feature = input.readString(), severity = input.readEnum(SeverityType::class.java), tags = input.readStringList() ) @@ -145,7 +145,7 @@ data class EventSource( override fun writeTo(output: StreamOutput) { output.writeString(title) output.writeString(referenceId) - output.writeEnum(feature) + output.writeString(feature) output.writeEnum(severity) output.writeStringCollection(tags) } diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/Feature.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/Feature.kt deleted file mode 100644 index 84b37139..00000000 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/Feature.kt +++ /dev/null @@ -1,71 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * - */ - -package org.opensearch.commons.notifications.model - -import org.opensearch.commons.utils.EnumParser - -/** - * Features using notification plugin - */ -enum class Feature(val tag: String) { - NONE("none") { - override fun toString(): String { - return tag - } - }, - ALERTING("alerting") { - override fun toString(): String { - return tag - } - }, - INDEX_MANAGEMENT("index_management") { - override fun toString(): String { - return tag - } - }, - REPORTS("reports") { - override fun toString(): String { - return tag - } - }; - - companion object { - private val tagMap = values().associateBy { it.tag } - - val enumParser = EnumParser { fromTagOrDefault(it) } - - /** - * Get Feature from tag or NONE if not found - * @param tag the tag - * @return Feature corresponding to tag. NONE if invalid tag. - */ - fun fromTagOrDefault(tag: String): Feature { - return tagMap[tag] ?: NONE - } - } -} diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationConfig.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationConfig.kt index 30d72147..a0f7f5ad 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationConfig.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationConfig.kt @@ -42,11 +42,12 @@ import org.opensearch.commons.notifications.NotificationConstants.NAME_TAG import org.opensearch.commons.notifications.model.config.ConfigDataProperties.createConfigData import org.opensearch.commons.notifications.model.config.ConfigDataProperties.getReaderForConfigType import org.opensearch.commons.notifications.model.config.ConfigDataProperties.validateConfigData -import org.opensearch.commons.utils.enumSet +import org.opensearch.commons.utils.STRING_READER +import org.opensearch.commons.utils.STRING_WRITER import org.opensearch.commons.utils.fieldIfNotNull import org.opensearch.commons.utils.logger +import org.opensearch.commons.utils.stringList import java.io.IOException -import java.util.EnumSet /** * Data class representing Notification config. @@ -55,7 +56,7 @@ data class NotificationConfig( val name: String, val description: String, val configType: ConfigType, - val features: EnumSet, + val features: Set, val configData: BaseConfigData?, val isEnabled: Boolean = true ) : BaseModel { @@ -89,7 +90,7 @@ data class NotificationConfig( var name: String? = null var description = "" var configType: ConfigType? = null - var features: EnumSet? = null + var features: Set? = null var isEnabled = true var configData: BaseConfigData? = null XContentParserUtils.ensureExpectedToken( @@ -104,7 +105,7 @@ data class NotificationConfig( NAME_TAG -> name = parser.text() DESCRIPTION_TAG -> description = parser.text() CONFIG_TYPE_TAG -> configType = ConfigType.fromTagOrDefault(parser.text()) - FEATURE_LIST_TAG -> features = parser.enumSet(Feature.enumParser) + FEATURE_LIST_TAG -> features = parser.stringList().toSet() IS_ENABLED_TAG -> isEnabled = parser.booleanValue() else -> { val configTypeForTag = ConfigType.fromTagOrDefault(fieldName) @@ -154,7 +155,7 @@ data class NotificationConfig( name = input.readString(), description = input.readString(), configType = input.readEnum(ConfigType::class.java), - features = input.readEnumSet(Feature::class.java), + features = input.readSet(STRING_READER), isEnabled = input.readBoolean(), configData = input.readOptionalWriteable(getReaderForConfigType(input.readEnum(ConfigType::class.java))) ) @@ -166,7 +167,7 @@ data class NotificationConfig( output.writeString(name) output.writeString(description) output.writeEnum(configType) - output.writeEnumSet(features) + output.writeCollection(features, STRING_WRITER) output.writeBoolean(isEnabled) // Reading config types multiple times in constructor output.writeEnum(configType) diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/SesAccount.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/SesAccount.kt new file mode 100644 index 00000000..d529b407 --- /dev/null +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/SesAccount.kt @@ -0,0 +1,124 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + * + * Modifications Copyright OpenSearch Contributors. See + * GitHub history for details. + */ + +package org.opensearch.commons.notifications.model + +import org.opensearch.common.Strings +import org.opensearch.common.io.stream.StreamInput +import org.opensearch.common.io.stream.StreamOutput +import org.opensearch.common.io.stream.Writeable +import org.opensearch.common.xcontent.ToXContent +import org.opensearch.common.xcontent.XContentBuilder +import org.opensearch.common.xcontent.XContentParser +import org.opensearch.common.xcontent.XContentParserUtils +import org.opensearch.commons.notifications.NotificationConstants.FROM_ADDRESS_TAG +import org.opensearch.commons.notifications.NotificationConstants.REGION_TAG +import org.opensearch.commons.notifications.NotificationConstants.ROLE_ARN_TAG +import org.opensearch.commons.utils.logger +import org.opensearch.commons.utils.validateEmail +import org.opensearch.commons.utils.validateIamRoleArn +import java.io.IOException + +/** + * Data class representing SES account channel. + */ +data class SesAccount( + val awsRegion: String, + val roleArn: String?, + val fromAddress: String +) : BaseConfigData { + + init { + require(!Strings.isNullOrEmpty(awsRegion)) { "awsRegion is null or empty" } + validateEmail(fromAddress) + if (roleArn != null) { + validateIamRoleArn(roleArn) + } + } + + companion object { + private val log by logger(SesAccount::class.java) + + /** + * reader to create instance of class from writable. + */ + val reader = Writeable.Reader { SesAccount(it) } + + /** + * Parser to parse xContent + */ + val xParser = XParser { parse(it) } + + @JvmStatic + @Throws(IOException::class) + fun parse(parser: XContentParser): SesAccount { + var awsRegion: String? = null + var roleArn: String? = null + var fromAddress: String? = null + + XContentParserUtils.ensureExpectedToken( + XContentParser.Token.START_OBJECT, + parser.currentToken(), + parser + ) + while (parser.nextToken() != XContentParser.Token.END_OBJECT) { + val fieldName = parser.currentName() + parser.nextToken() + when (fieldName) { + REGION_TAG -> awsRegion = parser.text() + ROLE_ARN_TAG -> roleArn = parser.text() + FROM_ADDRESS_TAG -> fromAddress = parser.text() + else -> { + parser.skipChildren() + log.info("Unexpected field: $fieldName, while parsing SesAccount") + } + } + } + awsRegion ?: throw IllegalArgumentException("$REGION_TAG field absent") + fromAddress ?: throw IllegalArgumentException("$FROM_ADDRESS_TAG field absent") + return SesAccount( + awsRegion, + roleArn, + fromAddress + ) + } + } + + /** + * {@inheritDoc} + */ + override fun toXContent(builder: XContentBuilder?, params: ToXContent.Params?): XContentBuilder { + return builder!!.startObject() + .field(REGION_TAG, awsRegion) + .field(ROLE_ARN_TAG, roleArn) + .field(FROM_ADDRESS_TAG, fromAddress) + .endObject() + } + + /** + * Constructor used in transport action communication. + * @param input StreamInput stream to deserialize data from. + */ + constructor(input: StreamInput) : this( + awsRegion = input.readString(), + roleArn = input.readOptionalString(), + fromAddress = input.readString() + ) + + /** + * {@inheritDoc} + */ + override fun writeTo(out: StreamOutput) { + out.writeString(awsRegion) + out.writeOptionalString(roleArn) + out.writeString(fromAddress) + } +} diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/SNS.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/Sns.kt similarity index 63% rename from src/main/kotlin/org/opensearch/commons/notifications/model/SNS.kt rename to src/main/kotlin/org/opensearch/commons/notifications/model/Sns.kt index 12cdba4f..5e723926 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/SNS.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/Sns.kt @@ -17,30 +17,30 @@ import org.opensearch.common.xcontent.ToXContent import org.opensearch.common.xcontent.XContentBuilder import org.opensearch.common.xcontent.XContentParser import org.opensearch.common.xcontent.XContentParserUtils -import org.opensearch.commons.notifications.NotificationConstants.ROLE_ARN_FIELD -import org.opensearch.commons.notifications.NotificationConstants.TOPIC_ARN_FIELD +import org.opensearch.commons.notifications.NotificationConstants.ROLE_ARN_TAG +import org.opensearch.commons.notifications.NotificationConstants.TOPIC_ARN_TAG import org.opensearch.commons.utils.fieldIfNotNull import org.opensearch.commons.utils.logger -import org.opensearch.commons.utils.validateIAMRoleArn +import org.opensearch.commons.utils.validateIamRoleArn import java.io.IOException import java.util.regex.Pattern /** * SNS notification data model */ -data class SNS(val topicARN: String, val roleARN: String?) : BaseConfigData { +data class Sns(val topicArn: String, val roleArn: String?) : BaseConfigData { init { - require(SNS_ARN_REGEX.matcher(topicARN).find()) { "Invalid AWS SNS topic ARN: $topicARN" } - if (roleARN != null) { - validateIAMRoleArn(roleARN) + require(SNS_ARN_REGEX.matcher(topicArn).find()) { "Invalid AWS SNS topic ARN: $topicArn" } + if (roleArn != null) { + validateIamRoleArn(roleArn) } } override fun toXContent(builder: XContentBuilder, params: ToXContent.Params): XContentBuilder { return builder.startObject() - .field(TOPIC_ARN_FIELD, topicARN) - .fieldIfNotNull(ROLE_ARN_FIELD, roleARN) + .field(TOPIC_ARN_TAG, topicArn) + .fieldIfNotNull(ROLE_ARN_TAG, roleArn) .endObject() } @@ -49,18 +49,18 @@ data class SNS(val topicARN: String, val roleARN: String?) : BaseConfigData { * @param input StreamInput stream to deserialize data from. */ constructor(input: StreamInput) : this( - topicARN = input.readString(), - roleARN = input.readOptionalString() + topicArn = input.readString(), + roleArn = input.readOptionalString() ) @Throws(IOException::class) override fun writeTo(out: StreamOutput) { - out.writeString(topicARN) - out.writeOptionalString(roleARN) + out.writeString(topicArn) + out.writeOptionalString(roleArn) } companion object { - private val log by logger(SNS::class.java) + private val log by logger(Sns::class.java) private val SNS_ARN_REGEX = Pattern.compile("^arn:aws(-[^:]+)?:sns:([a-zA-Z0-9-]+):([0-9]{12}):([a-zA-Z0-9-_]+)$") @@ -68,7 +68,7 @@ data class SNS(val topicARN: String, val roleARN: String?) : BaseConfigData { /** * reader to create instance of class from writable. */ - val reader = Writeable.Reader { SNS(it) } + val reader = Writeable.Reader { Sns(it) } /** * Parser to parse xContent @@ -77,36 +77,25 @@ data class SNS(val topicARN: String, val roleARN: String?) : BaseConfigData { @JvmStatic @Throws(IOException::class) - fun parse(xcp: XContentParser): SNS { - var topicARN: String? = null - var roleARN: String? = null + fun parse(xcp: XContentParser): Sns { + var topicArn: String? = null + var roleArn: String? = null XContentParserUtils.ensureExpectedToken(XContentParser.Token.START_OBJECT, xcp.currentToken(), xcp) while (xcp.nextToken() != XContentParser.Token.END_OBJECT) { val fieldName = xcp.currentName() xcp.nextToken() when (fieldName) { - TOPIC_ARN_FIELD -> topicARN = xcp.textOrNull() - ROLE_ARN_FIELD -> roleARN = xcp.textOrNull() + TOPIC_ARN_TAG -> topicArn = xcp.textOrNull() + ROLE_ARN_TAG -> roleArn = xcp.textOrNull() else -> { xcp.skipChildren() log.info("Unexpected field: $fieldName, while parsing SNS destination") } } } - topicARN ?: throw IllegalArgumentException("$TOPIC_ARN_FIELD field absent") - return SNS(topicARN, roleARN) - } - - @JvmStatic - @Throws(IOException::class) - fun readFrom(sin: StreamInput): SNS? { - return if (sin.readBoolean()) { - SNS( - topicARN = sin.readString(), - roleARN = sin.readOptionalString() - ) - } else null + topicArn ?: throw IllegalArgumentException("$TOPIC_ARN_TAG field absent") + return Sns(topicArn, roleArn) } } } diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/config/ConfigDataProperties.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/config/ConfigDataProperties.kt index 34bd2edc..e6844934 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/config/ConfigDataProperties.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/config/ConfigDataProperties.kt @@ -33,9 +33,10 @@ import org.opensearch.commons.notifications.model.Chime import org.opensearch.commons.notifications.model.ConfigType import org.opensearch.commons.notifications.model.Email import org.opensearch.commons.notifications.model.EmailGroup -import org.opensearch.commons.notifications.model.SNS +import org.opensearch.commons.notifications.model.SesAccount import org.opensearch.commons.notifications.model.Slack import org.opensearch.commons.notifications.model.SmtpAccount +import org.opensearch.commons.notifications.model.Sns import org.opensearch.commons.notifications.model.Webhook import org.opensearch.commons.notifications.model.XParser @@ -54,7 +55,8 @@ internal object ConfigDataProperties { Pair(ConfigType.CHIME, ConfigProperty(Chime.reader, Chime.xParser)), Pair(ConfigType.WEBHOOK, ConfigProperty(Webhook.reader, Webhook.xParser)), Pair(ConfigType.EMAIL, ConfigProperty(Email.reader, Email.xParser)), - Pair(ConfigType.SNS, ConfigProperty(SNS.reader, SNS.xParser)), + Pair(ConfigType.SNS, ConfigProperty(Sns.reader, Sns.xParser)), + Pair(ConfigType.SES_ACCOUNT, ConfigProperty(SesAccount.reader, SesAccount.xParser)), Pair(ConfigType.EMAIL_GROUP, ConfigProperty(EmailGroup.reader, EmailGroup.xParser)), Pair(ConfigType.SMTP_ACCOUNT, ConfigProperty(SmtpAccount.reader, SmtpAccount.xParser)) ) @@ -80,7 +82,8 @@ internal object ConfigDataProperties { ConfigType.EMAIL_GROUP -> configData is EmailGroup ConfigType.SMTP_ACCOUNT -> configData is SmtpAccount ConfigType.CHIME -> configData is Chime - ConfigType.SNS -> configData is SNS + ConfigType.SNS -> configData is Sns + ConfigType.SES_ACCOUNT -> configData is SesAccount ConfigType.NONE -> true } } diff --git a/src/main/kotlin/org/opensearch/commons/utils/ValidationHelpers.kt b/src/main/kotlin/org/opensearch/commons/utils/ValidationHelpers.kt index fc117923..9f9082c4 100644 --- a/src/main/kotlin/org/opensearch/commons/utils/ValidationHelpers.kt +++ b/src/main/kotlin/org/opensearch/commons/utils/ValidationHelpers.kt @@ -71,7 +71,7 @@ fun isValidId(idString: String): Boolean { return idString.isNotBlank() && idString.all { VALID_ID_CHARS.contains(it) } } -fun validateIAMRoleArn(roleARN: String) { +fun validateIamRoleArn(roleArn: String) { val roleArnRegex = Pattern.compile("^arn:aws(-[^:]+)?:iam::([0-9]{12}):([a-zA-Z_0-9+=,.@\\-_/]+)$") - require(roleArnRegex.matcher(roleARN).find()) { "Invalid AWS role ARN: $roleARN " } + require(roleArnRegex.matcher(roleArn).find()) { "Invalid AWS role ARN: $roleArn " } } diff --git a/src/test/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterfaceTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterfaceTests.kt index 99f558f4..cf4f8420 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterfaceTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterfaceTests.kt @@ -25,6 +25,8 @@ import org.mockito.junit.jupiter.MockitoExtension import org.opensearch.action.ActionListener import org.opensearch.action.ActionType import org.opensearch.client.node.NodeClient +import org.opensearch.commons.notifications.NotificationConstants.FEATURE_ALERTING +import org.opensearch.commons.notifications.NotificationConstants.FEATURE_REPORTS import org.opensearch.commons.notifications.action.CreateNotificationConfigRequest import org.opensearch.commons.notifications.action.CreateNotificationConfigResponse import org.opensearch.commons.notifications.action.DeleteNotificationConfigRequest @@ -45,7 +47,6 @@ import org.opensearch.commons.notifications.model.ConfigType import org.opensearch.commons.notifications.model.DeliveryStatus import org.opensearch.commons.notifications.model.EventSource import org.opensearch.commons.notifications.model.EventStatus -import org.opensearch.commons.notifications.model.Feature import org.opensearch.commons.notifications.model.FeatureChannel import org.opensearch.commons.notifications.model.FeatureChannelList import org.opensearch.commons.notifications.model.NotificationConfig @@ -58,7 +59,6 @@ import org.opensearch.commons.notifications.model.SeverityType import org.opensearch.commons.notifications.model.Slack import org.opensearch.rest.RestStatus import java.time.Instant -import java.util.EnumSet @Suppress("UNCHECKED_CAST") @ExtendWith(MockitoExtension::class) @@ -198,7 +198,7 @@ internal class NotificationsPluginInterfaceTests { val notificationInfo = EventSource( "title", "reference_id", - Feature.REPORTS, + FEATURE_REPORTS, SeverityType.HIGH, listOf("tag1", "tag2") ) @@ -229,7 +229,7 @@ internal class NotificationsPluginInterfaceTests { "name", "description", ConfigType.SLACK, - EnumSet.of(Feature.REPORTS), + setOf(FEATURE_REPORTS), configData = sampleSlack ) val configInfo = NotificationConfigInfo( @@ -246,7 +246,7 @@ internal class NotificationsPluginInterfaceTests { val sampleEventSource = EventSource( "title", "reference_id", - Feature.ALERTING, + FEATURE_ALERTING, severity = SeverityType.INFO ) val sampleStatus = EventStatus( diff --git a/src/test/kotlin/org/opensearch/commons/notifications/action/CreateNotificationConfigRequestTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/action/CreateNotificationConfigRequestTests.kt index 679ded46..f190e7f6 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/action/CreateNotificationConfigRequestTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/action/CreateNotificationConfigRequestTests.kt @@ -31,11 +31,11 @@ import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Assertions.assertNull import org.junit.jupiter.api.Test import org.junit.jupiter.api.assertThrows +import org.opensearch.commons.notifications.NotificationConstants.FEATURE_INDEX_MANAGEMENT import org.opensearch.commons.notifications.model.Chime import org.opensearch.commons.notifications.model.ConfigType import org.opensearch.commons.notifications.model.Email import org.opensearch.commons.notifications.model.EmailGroup -import org.opensearch.commons.notifications.model.Feature import org.opensearch.commons.notifications.model.MethodType import org.opensearch.commons.notifications.model.NotificationConfig import org.opensearch.commons.notifications.model.Slack @@ -44,7 +44,6 @@ import org.opensearch.commons.notifications.model.Webhook import org.opensearch.commons.utils.createObjectFromJsonString import org.opensearch.commons.utils.getJsonString import org.opensearch.commons.utils.recreateObject -import java.util.EnumSet internal class CreateNotificationConfigRequestTests { @@ -54,7 +53,7 @@ internal class CreateNotificationConfigRequestTests { "name", "description", ConfigType.WEBHOOK, - EnumSet.of(Feature.INDEX_MANAGEMENT), + setOf(FEATURE_INDEX_MANAGEMENT), isEnabled = true, configData = sampleWebhook ) @@ -66,7 +65,7 @@ internal class CreateNotificationConfigRequestTests { "name", "description", ConfigType.SLACK, - EnumSet.of(Feature.INDEX_MANAGEMENT), + setOf(FEATURE_INDEX_MANAGEMENT), isEnabled = true, configData = sampleSlack ) @@ -78,7 +77,7 @@ internal class CreateNotificationConfigRequestTests { "name", "description", ConfigType.CHIME, - EnumSet.of(Feature.INDEX_MANAGEMENT), + setOf(FEATURE_INDEX_MANAGEMENT), isEnabled = true, configData = sampleChime ) @@ -90,7 +89,7 @@ internal class CreateNotificationConfigRequestTests { "name", "description", ConfigType.EMAIL_GROUP, - EnumSet.of(Feature.INDEX_MANAGEMENT), + setOf(FEATURE_INDEX_MANAGEMENT), isEnabled = true, configData = sampleEmailGroup ) @@ -106,7 +105,7 @@ internal class CreateNotificationConfigRequestTests { "name", "description", ConfigType.EMAIL, - EnumSet.of(Feature.INDEX_MANAGEMENT), + setOf(FEATURE_INDEX_MANAGEMENT), isEnabled = true, configData = sampleEmail ) @@ -123,7 +122,7 @@ internal class CreateNotificationConfigRequestTests { "name", "description", ConfigType.SMTP_ACCOUNT, - EnumSet.of(Feature.INDEX_MANAGEMENT), + setOf(FEATURE_INDEX_MANAGEMENT), isEnabled = true, configData = sampleSmtpAccount ) @@ -286,7 +285,7 @@ internal class CreateNotificationConfigRequestTests { "name", "description", ConfigType.SLACK, - EnumSet.of(Feature.INDEX_MANAGEMENT), + setOf(FEATURE_INDEX_MANAGEMENT), isEnabled = true, configData = sampleSlack ) @@ -314,7 +313,7 @@ internal class CreateNotificationConfigRequestTests { "name", "description", ConfigType.WEBHOOK, - EnumSet.of(Feature.INDEX_MANAGEMENT), + setOf(FEATURE_INDEX_MANAGEMENT), isEnabled = true, configData = sampleWebhook ) @@ -342,7 +341,7 @@ internal class CreateNotificationConfigRequestTests { "name", "description", ConfigType.CHIME, - EnumSet.of(Feature.INDEX_MANAGEMENT), + setOf(FEATURE_INDEX_MANAGEMENT), isEnabled = true, configData = sampleChime ) @@ -371,7 +370,7 @@ internal class CreateNotificationConfigRequestTests { "name", "description", ConfigType.EMAIL_GROUP, - EnumSet.of(Feature.INDEX_MANAGEMENT), + setOf(FEATURE_INDEX_MANAGEMENT), isEnabled = true, configData = sampleEmailGroup ) @@ -404,7 +403,7 @@ internal class CreateNotificationConfigRequestTests { "name", "description", ConfigType.EMAIL, - EnumSet.of(Feature.INDEX_MANAGEMENT), + setOf(FEATURE_INDEX_MANAGEMENT), isEnabled = true, configData = sampleEmail ) @@ -439,7 +438,7 @@ internal class CreateNotificationConfigRequestTests { "name", "description", ConfigType.SMTP_ACCOUNT, - EnumSet.of(Feature.INDEX_MANAGEMENT), + setOf(FEATURE_INDEX_MANAGEMENT), isEnabled = true, configData = sampleSmtpAccount ) @@ -507,7 +506,7 @@ internal class CreateNotificationConfigRequestTests { "name", "description", ConfigType.SLACK, - EnumSet.of(Feature.INDEX_MANAGEMENT), + setOf(FEATURE_INDEX_MANAGEMENT), isEnabled = true, configData = sampleSlack ) diff --git a/src/test/kotlin/org/opensearch/commons/notifications/action/GetFeatureChannelListRequestTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/action/GetFeatureChannelListRequestTests.kt index c9788a80..8c5c770f 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/action/GetFeatureChannelListRequestTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/action/GetFeatureChannelListRequestTests.kt @@ -30,7 +30,9 @@ import com.fasterxml.jackson.core.JsonParseException import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Test import org.junit.jupiter.api.assertThrows -import org.opensearch.commons.notifications.model.Feature +import org.opensearch.commons.notifications.NotificationConstants.FEATURE_ALERTING +import org.opensearch.commons.notifications.NotificationConstants.FEATURE_INDEX_MANAGEMENT +import org.opensearch.commons.notifications.NotificationConstants.FEATURE_REPORTS import org.opensearch.commons.utils.createObjectFromJsonString import org.opensearch.commons.utils.getJsonString import org.opensearch.commons.utils.recreateObject @@ -46,14 +48,14 @@ internal class GetFeatureChannelListRequestTests { @Test fun `Get request serialize and deserialize transport object should be equal`() { - val configRequest = GetFeatureChannelListRequest(Feature.REPORTS) + val configRequest = GetFeatureChannelListRequest(FEATURE_REPORTS) val recreatedObject = recreateObject(configRequest) { GetFeatureChannelListRequest(it) } assertGetRequestEquals(configRequest, recreatedObject) } @Test fun `Get request serialize and deserialize using json object should be equal`() { - val configRequest = GetFeatureChannelListRequest(Feature.INDEX_MANAGEMENT) + val configRequest = GetFeatureChannelListRequest(FEATURE_INDEX_MANAGEMENT) val jsonString = getJsonString(configRequest) val recreatedObject = createObjectFromJsonString(jsonString) { GetFeatureChannelListRequest.parse(it) } assertGetRequestEquals(configRequest, recreatedObject) @@ -69,7 +71,7 @@ internal class GetFeatureChannelListRequestTests { @Test fun `Get request should safely ignore extra field in json object`() { - val configRequest = GetFeatureChannelListRequest(Feature.ALERTING) + val configRequest = GetFeatureChannelListRequest(FEATURE_ALERTING) val jsonString = """ { "feature":"${configRequest.feature}", diff --git a/src/test/kotlin/org/opensearch/commons/notifications/action/GetNotificationConfigResponseTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/action/GetNotificationConfigResponseTests.kt index a2e14b40..2ec08913 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/action/GetNotificationConfigResponseTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/action/GetNotificationConfigResponseTests.kt @@ -30,9 +30,10 @@ import org.apache.lucene.search.TotalHits import org.junit.jupiter.api.Assertions import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Test +import org.opensearch.commons.notifications.NotificationConstants.FEATURE_INDEX_MANAGEMENT +import org.opensearch.commons.notifications.NotificationConstants.FEATURE_REPORTS import org.opensearch.commons.notifications.model.Chime import org.opensearch.commons.notifications.model.ConfigType -import org.opensearch.commons.notifications.model.Feature import org.opensearch.commons.notifications.model.NotificationConfig import org.opensearch.commons.notifications.model.NotificationConfigInfo import org.opensearch.commons.notifications.model.NotificationConfigSearchResult @@ -41,7 +42,6 @@ import org.opensearch.commons.utils.createObjectFromJsonString import org.opensearch.commons.utils.getJsonString import org.opensearch.commons.utils.recreateObject import java.time.Instant -import java.util.EnumSet internal class GetNotificationConfigResponseTests { @@ -63,7 +63,7 @@ internal class GetNotificationConfigResponseTests { "name", "description", ConfigType.SLACK, - EnumSet.of(Feature.REPORTS), + setOf(FEATURE_REPORTS), configData = sampleSlack ) val configInfo = NotificationConfigInfo( @@ -85,7 +85,7 @@ internal class GetNotificationConfigResponseTests { "name", "description", ConfigType.SLACK, - EnumSet.of(Feature.REPORTS), + setOf(FEATURE_REPORTS), configData = Slack("https://domain.com/sample_url#1234567890") ) val configInfo1 = NotificationConfigInfo( @@ -99,7 +99,7 @@ internal class GetNotificationConfigResponseTests { "name", "description", ConfigType.CHIME, - EnumSet.of(Feature.INDEX_MANAGEMENT), + setOf(FEATURE_INDEX_MANAGEMENT), configData = Chime("https://domain.com/sample_url#1234567890") ) val configInfo2 = NotificationConfigInfo( @@ -129,7 +129,7 @@ internal class GetNotificationConfigResponseTests { "name", "description", ConfigType.SLACK, - EnumSet.of(Feature.REPORTS), + setOf(FEATURE_REPORTS), configData = sampleSlack ) val configInfo = NotificationConfigInfo( @@ -154,7 +154,7 @@ internal class GetNotificationConfigResponseTests { "name", "description", ConfigType.SLACK, - EnumSet.of(Feature.REPORTS), + setOf(FEATURE_REPORTS), configData = Slack("https://domain.com/sample_url#1234567890") ) val configInfo1 = NotificationConfigInfo( @@ -168,7 +168,7 @@ internal class GetNotificationConfigResponseTests { "name", "description", ConfigType.CHIME, - EnumSet.of(Feature.INDEX_MANAGEMENT), + setOf(FEATURE_INDEX_MANAGEMENT), configData = Chime("https://domain.com/sample_url#1234567890") ) val configInfo2 = NotificationConfigInfo( @@ -199,7 +199,7 @@ internal class GetNotificationConfigResponseTests { "name", "description", ConfigType.SLACK, - EnumSet.of(Feature.INDEX_MANAGEMENT), + setOf(FEATURE_INDEX_MANAGEMENT), isEnabled = true, configData = sampleSlack ) @@ -250,7 +250,7 @@ internal class GetNotificationConfigResponseTests { "name", "description", ConfigType.SLACK, - EnumSet.of(Feature.INDEX_MANAGEMENT), + setOf(FEATURE_INDEX_MANAGEMENT), isEnabled = true, configData = sampleSlack ) diff --git a/src/test/kotlin/org/opensearch/commons/notifications/action/GetNotificationEventResponseTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/action/GetNotificationEventResponseTests.kt index 4f7d72d1..1895d1d3 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/action/GetNotificationEventResponseTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/action/GetNotificationEventResponseTests.kt @@ -30,11 +30,12 @@ import org.apache.lucene.search.TotalHits import org.junit.jupiter.api.Assertions import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Test +import org.opensearch.commons.notifications.NotificationConstants.FEATURE_ALERTING +import org.opensearch.commons.notifications.NotificationConstants.FEATURE_REPORTS import org.opensearch.commons.notifications.model.ConfigType import org.opensearch.commons.notifications.model.DeliveryStatus import org.opensearch.commons.notifications.model.EventSource import org.opensearch.commons.notifications.model.EventStatus -import org.opensearch.commons.notifications.model.Feature import org.opensearch.commons.notifications.model.NotificationEvent import org.opensearch.commons.notifications.model.NotificationEventInfo import org.opensearch.commons.notifications.model.NotificationEventSearchResult @@ -62,7 +63,7 @@ internal class GetNotificationEventResponseTests { val sampleEventSource = EventSource( "title", "reference_id", - Feature.ALERTING, + FEATURE_ALERTING, severity = SeverityType.INFO ) val sampleStatus = EventStatus( @@ -90,13 +91,13 @@ internal class GetNotificationEventResponseTests { val eventSource1 = EventSource( "title 1", "reference_id_1", - Feature.ALERTING, + FEATURE_ALERTING, severity = SeverityType.INFO ) val eventSource2 = EventSource( "title 2", "reference_id_2", - Feature.REPORTS, + FEATURE_REPORTS, severity = SeverityType.HIGH ) val status1 = EventStatus( @@ -157,7 +158,7 @@ internal class GetNotificationEventResponseTests { val sampleEventSource = EventSource( "title", "reference_id", - Feature.ALERTING, + FEATURE_ALERTING, severity = SeverityType.INFO ) val sampleStatus = EventStatus( @@ -188,13 +189,13 @@ internal class GetNotificationEventResponseTests { val eventSource1 = EventSource( "title 1", "reference_id_1", - Feature.ALERTING, + FEATURE_ALERTING, severity = SeverityType.INFO ) val eventSource2 = EventSource( "title 2", "reference_id_2", - Feature.REPORTS, + FEATURE_REPORTS, severity = SeverityType.HIGH ) val status1 = EventStatus( @@ -242,7 +243,7 @@ internal class GetNotificationEventResponseTests { val sampleEventSource = EventSource( "title", "reference_id", - Feature.ALERTING, + FEATURE_ALERTING, severity = SeverityType.INFO ) val sampleStatus = EventStatus( @@ -310,7 +311,7 @@ internal class GetNotificationEventResponseTests { val sampleEventSource = EventSource( "title", "reference_id", - Feature.ALERTING, + FEATURE_ALERTING, severity = SeverityType.INFO ) val sampleStatus = EventStatus( diff --git a/src/test/kotlin/org/opensearch/commons/notifications/action/SendNotificationRequestTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/action/SendNotificationRequestTests.kt index 9c8bd2b4..31f6f549 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/action/SendNotificationRequestTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/action/SendNotificationRequestTests.kt @@ -32,9 +32,11 @@ import org.junit.jupiter.api.Assertions.assertNotNull import org.junit.jupiter.api.Assertions.assertNull import org.junit.jupiter.api.Test import org.junit.jupiter.api.assertThrows +import org.opensearch.commons.notifications.NotificationConstants.FEATURE_ALERTING +import org.opensearch.commons.notifications.NotificationConstants.FEATURE_INDEX_MANAGEMENT +import org.opensearch.commons.notifications.NotificationConstants.FEATURE_REPORTS import org.opensearch.commons.notifications.model.ChannelMessage import org.opensearch.commons.notifications.model.EventSource -import org.opensearch.commons.notifications.model.Feature import org.opensearch.commons.notifications.model.SeverityType import org.opensearch.commons.utils.createObjectFromJsonString import org.opensearch.commons.utils.getJsonString @@ -58,7 +60,7 @@ internal class SendNotificationRequestTests { val notificationInfo = EventSource( "title", "reference_id", - Feature.REPORTS, + FEATURE_REPORTS, SeverityType.HIGH, listOf("tag1", "tag2") ) @@ -82,7 +84,7 @@ internal class SendNotificationRequestTests { val notificationInfo = EventSource( "title", "reference_id", - Feature.INDEX_MANAGEMENT, + FEATURE_INDEX_MANAGEMENT, SeverityType.CRITICAL, listOf("tag1", "tag2") ) @@ -115,7 +117,7 @@ internal class SendNotificationRequestTests { val notificationInfo = EventSource( "title", "reference_id", - Feature.ALERTING, + FEATURE_ALERTING, SeverityType.HIGH, listOf("tag1", "tag2") ) @@ -159,7 +161,7 @@ internal class SendNotificationRequestTests { val notificationInfo = EventSource( "title", "reference_id", - Feature.REPORTS, + FEATURE_REPORTS, SeverityType.INFO, listOf("tag1", "tag2") ) diff --git a/src/test/kotlin/org/opensearch/commons/notifications/action/UpdateNotificationConfigRequestTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/action/UpdateNotificationConfigRequestTests.kt index 607e8077..2dfcff69 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/action/UpdateNotificationConfigRequestTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/action/UpdateNotificationConfigRequestTests.kt @@ -31,11 +31,11 @@ import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Assertions.assertNull import org.junit.jupiter.api.Test import org.junit.jupiter.api.assertThrows +import org.opensearch.commons.notifications.NotificationConstants.FEATURE_INDEX_MANAGEMENT import org.opensearch.commons.notifications.model.Chime import org.opensearch.commons.notifications.model.ConfigType import org.opensearch.commons.notifications.model.Email import org.opensearch.commons.notifications.model.EmailGroup -import org.opensearch.commons.notifications.model.Feature import org.opensearch.commons.notifications.model.MethodType import org.opensearch.commons.notifications.model.NotificationConfig import org.opensearch.commons.notifications.model.Slack @@ -44,7 +44,6 @@ import org.opensearch.commons.notifications.model.Webhook import org.opensearch.commons.utils.createObjectFromJsonString import org.opensearch.commons.utils.getJsonString import org.opensearch.commons.utils.recreateObject -import java.util.EnumSet internal class UpdateNotificationConfigRequestTests { @@ -54,7 +53,7 @@ internal class UpdateNotificationConfigRequestTests { "name", "description", ConfigType.WEBHOOK, - EnumSet.of(Feature.INDEX_MANAGEMENT), + setOf(FEATURE_INDEX_MANAGEMENT), isEnabled = true, configData = sampleWebhook ) @@ -66,7 +65,7 @@ internal class UpdateNotificationConfigRequestTests { "name", "description", ConfigType.SLACK, - EnumSet.of(Feature.INDEX_MANAGEMENT), + setOf(FEATURE_INDEX_MANAGEMENT), isEnabled = true, configData = sampleSlack ) @@ -78,7 +77,7 @@ internal class UpdateNotificationConfigRequestTests { "name", "description", ConfigType.CHIME, - EnumSet.of(Feature.INDEX_MANAGEMENT), + setOf(FEATURE_INDEX_MANAGEMENT), isEnabled = true, configData = sampleChime ) @@ -90,7 +89,7 @@ internal class UpdateNotificationConfigRequestTests { "name", "description", ConfigType.EMAIL_GROUP, - EnumSet.of(Feature.INDEX_MANAGEMENT), + setOf(FEATURE_INDEX_MANAGEMENT), isEnabled = true, configData = sampleEmailGroup ) @@ -106,7 +105,7 @@ internal class UpdateNotificationConfigRequestTests { "name", "description", ConfigType.EMAIL, - EnumSet.of(Feature.INDEX_MANAGEMENT), + setOf(FEATURE_INDEX_MANAGEMENT), isEnabled = true, configData = sampleEmail ) @@ -123,7 +122,7 @@ internal class UpdateNotificationConfigRequestTests { "name", "description", ConfigType.SMTP_ACCOUNT, - EnumSet.of(Feature.INDEX_MANAGEMENT), + setOf(FEATURE_INDEX_MANAGEMENT), isEnabled = true, configData = sampleSmtpAccount ) @@ -250,7 +249,7 @@ internal class UpdateNotificationConfigRequestTests { "name", "description", ConfigType.SLACK, - EnumSet.of(Feature.INDEX_MANAGEMENT), + setOf(FEATURE_INDEX_MANAGEMENT), isEnabled = true, configData = sampleSlack ) @@ -280,7 +279,7 @@ internal class UpdateNotificationConfigRequestTests { "name", "description", ConfigType.WEBHOOK, - EnumSet.of(Feature.INDEX_MANAGEMENT), + setOf(FEATURE_INDEX_MANAGEMENT), isEnabled = true, configData = sampleWebhook ) @@ -310,7 +309,7 @@ internal class UpdateNotificationConfigRequestTests { "name", "description", ConfigType.CHIME, - EnumSet.of(Feature.INDEX_MANAGEMENT), + setOf(FEATURE_INDEX_MANAGEMENT), isEnabled = true, configData = sampleChime ) @@ -340,7 +339,7 @@ internal class UpdateNotificationConfigRequestTests { "name", "description", ConfigType.EMAIL_GROUP, - EnumSet.of(Feature.INDEX_MANAGEMENT), + setOf(FEATURE_INDEX_MANAGEMENT), isEnabled = true, configData = sampleEmailGroup ) @@ -374,7 +373,7 @@ internal class UpdateNotificationConfigRequestTests { "name", "description", ConfigType.EMAIL, - EnumSet.of(Feature.INDEX_MANAGEMENT), + setOf(FEATURE_INDEX_MANAGEMENT), isEnabled = true, configData = sampleEmail ) @@ -410,7 +409,7 @@ internal class UpdateNotificationConfigRequestTests { "name", "description", ConfigType.SMTP_ACCOUNT, - EnumSet.of(Feature.INDEX_MANAGEMENT), + setOf(FEATURE_INDEX_MANAGEMENT), isEnabled = true, configData = sampleSmtpAccount ) @@ -448,7 +447,7 @@ internal class UpdateNotificationConfigRequestTests { "name", "description", ConfigType.SLACK, - EnumSet.of(Feature.INDEX_MANAGEMENT), + setOf(FEATURE_INDEX_MANAGEMENT), isEnabled = true, configData = sampleSlack ) diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/EventSourceTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/EventSourceTests.kt index 883c5047..6a87ed3f 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/EventSourceTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/EventSourceTests.kt @@ -29,6 +29,7 @@ package org.opensearch.commons.notifications.model import org.junit.jupiter.api.Assertions import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Test +import org.opensearch.commons.notifications.NotificationConstants.FEATURE_ALERTING import org.opensearch.commons.utils.createObjectFromJsonString import org.opensearch.commons.utils.getJsonString import org.opensearch.commons.utils.recreateObject @@ -40,7 +41,7 @@ internal class EventSourceTests { val sampleEventSource = EventSource( "title", "reference_id", - Feature.ALERTING, + FEATURE_ALERTING, severity = SeverityType.INFO ) val recreatedObject = recreateObject(sampleEventSource) { EventSource(it) } @@ -52,7 +53,7 @@ internal class EventSourceTests { val sampleEventSource = EventSource( "title", "reference_id", - Feature.ALERTING, + FEATURE_ALERTING, severity = SeverityType.INFO ) @@ -66,7 +67,7 @@ internal class EventSourceTests { val sampleEventSource = EventSource( "title", "reference_id", - Feature.ALERTING, + FEATURE_ALERTING, tags = listOf("tag1", "tag2"), severity = SeverityType.INFO ) @@ -87,11 +88,11 @@ internal class EventSourceTests { } @Test - fun `Event source should safely ignore unknown feature type in json object`() { + fun `Event source should safely accepts unknown feature type in json object`() { val sampleEventSource = EventSource( "title", "reference_id", - Feature.NONE, + "NewFeature", tags = listOf("tag1", "tag2"), severity = SeverityType.INFO ) @@ -114,7 +115,7 @@ internal class EventSourceTests { EventSource( "", "reference_id", - Feature.ALERTING, + FEATURE_ALERTING, tags = listOf("tag1", "tag2"), severity = SeverityType.INFO ) diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/FeatureTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/FeatureTests.kt deleted file mode 100644 index 215c2c2c..00000000 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/FeatureTests.kt +++ /dev/null @@ -1,56 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * - */ -package org.opensearch.commons.notifications.model - -import org.junit.jupiter.api.Assertions.assertEquals -import org.junit.jupiter.api.Test -import org.opensearch.commons.notifications.model.Feature.Companion.enumParser -import org.opensearch.commons.notifications.model.Feature.Companion.fromTagOrDefault - -internal class FeatureTests { - - @Test - fun `toString should return tag`() { - Feature.values().forEach { - assertEquals(it.tag, it.toString()) - } - } - - @Test - fun `fromTagOrDefault should return corresponding enum`() { - Feature.values().forEach { - assertEquals(it, fromTagOrDefault(it.tag)) - } - } - - @Test - fun `EnumParser fromTagOrDefault should return corresponding enum`() { - Feature.values().forEach { - assertEquals(it, enumParser.fromTagOrDefault(it.tag)) - } - } -} diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationConfigInfoTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationConfigInfoTests.kt index 79c1035d..409decd7 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationConfigInfoTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationConfigInfoTests.kt @@ -29,11 +29,12 @@ package org.opensearch.commons.notifications.model import org.junit.jupiter.api.Assertions import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Test +import org.opensearch.commons.notifications.NotificationConstants.FEATURE_INDEX_MANAGEMENT +import org.opensearch.commons.notifications.NotificationConstants.FEATURE_REPORTS import org.opensearch.commons.utils.createObjectFromJsonString import org.opensearch.commons.utils.getJsonString import org.opensearch.commons.utils.recreateObject import java.time.Instant -import java.util.EnumSet internal class NotificationConfigInfoTests { @@ -44,7 +45,7 @@ internal class NotificationConfigInfoTests { "name", "description", ConfigType.SLACK, - EnumSet.of(Feature.REPORTS), + setOf(FEATURE_REPORTS), configData = sampleSlack ) val configInfo = NotificationConfigInfo( @@ -67,7 +68,7 @@ internal class NotificationConfigInfoTests { "name", "description", ConfigType.SLACK, - EnumSet.of(Feature.REPORTS), + setOf(FEATURE_REPORTS), configData = sampleSlack ) val configInfo = NotificationConfigInfo( @@ -91,7 +92,7 @@ internal class NotificationConfigInfoTests { "name", "description", ConfigType.SLACK, - EnumSet.of(Feature.INDEX_MANAGEMENT), + setOf(FEATURE_INDEX_MANAGEMENT), isEnabled = true, configData = sampleSlack ) @@ -130,7 +131,7 @@ internal class NotificationConfigInfoTests { "name", "description", ConfigType.SLACK, - EnumSet.of(Feature.INDEX_MANAGEMENT), + setOf(FEATURE_INDEX_MANAGEMENT), isEnabled = true, configData = sampleSlack ) @@ -171,7 +172,7 @@ internal class NotificationConfigInfoTests { "name", "description", ConfigType.SLACK, - EnumSet.of(Feature.REPORTS), + setOf(FEATURE_REPORTS), configData = sampleSlack ) Assertions.assertThrows(IllegalArgumentException::class.java) { diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationConfigSearchResultsTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationConfigSearchResultsTests.kt index a9543533..6a10935f 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationConfigSearchResultsTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationConfigSearchResultsTests.kt @@ -30,11 +30,12 @@ import org.apache.lucene.search.TotalHits import org.junit.jupiter.api.Assertions import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Test +import org.opensearch.commons.notifications.NotificationConstants.FEATURE_INDEX_MANAGEMENT +import org.opensearch.commons.notifications.NotificationConstants.FEATURE_REPORTS import org.opensearch.commons.utils.createObjectFromJsonString import org.opensearch.commons.utils.getJsonString import org.opensearch.commons.utils.recreateObject import java.time.Instant -import java.util.EnumSet internal class NotificationConfigSearchResultsTests { @@ -56,7 +57,7 @@ internal class NotificationConfigSearchResultsTests { "name", "description", ConfigType.SLACK, - EnumSet.of(Feature.REPORTS), + setOf(FEATURE_REPORTS), configData = sampleSlack ) val configInfo = NotificationConfigInfo( @@ -77,7 +78,7 @@ internal class NotificationConfigSearchResultsTests { "name", "description", ConfigType.SLACK, - EnumSet.of(Feature.REPORTS), + setOf(FEATURE_REPORTS), configData = Slack("https://domain.com/sample_url#1234567890") ) val configInfo1 = NotificationConfigInfo( @@ -91,7 +92,7 @@ internal class NotificationConfigSearchResultsTests { "name", "description", ConfigType.CHIME, - EnumSet.of(Feature.INDEX_MANAGEMENT), + setOf(FEATURE_INDEX_MANAGEMENT), configData = Chime("https://domain.com/sample_url#1234567890") ) val configInfo2 = NotificationConfigInfo( @@ -118,7 +119,7 @@ internal class NotificationConfigSearchResultsTests { "name", "description", ConfigType.SLACK, - EnumSet.of(Feature.REPORTS), + setOf(FEATURE_REPORTS), configData = Slack("https://domain.com/sample_url#1234567890") ) val configInfo1 = NotificationConfigInfo( @@ -132,7 +133,7 @@ internal class NotificationConfigSearchResultsTests { "name", "description", ConfigType.CHIME, - EnumSet.of(Feature.INDEX_MANAGEMENT), + setOf(FEATURE_INDEX_MANAGEMENT), configData = Chime("https://domain.com/sample_url#1234567890") ) val configInfo2 = NotificationConfigInfo( @@ -161,7 +162,7 @@ internal class NotificationConfigSearchResultsTests { "name", "description", ConfigType.SLACK, - EnumSet.of(Feature.REPORTS), + setOf(FEATURE_REPORTS), configData = sampleSlack ) val configInfo = NotificationConfigInfo( @@ -185,7 +186,7 @@ internal class NotificationConfigSearchResultsTests { "name", "description", ConfigType.SLACK, - EnumSet.of(Feature.REPORTS), + setOf(FEATURE_REPORTS), configData = Slack("https://domain.com/sample_url#1234567890") ) val configInfo1 = NotificationConfigInfo( @@ -199,7 +200,7 @@ internal class NotificationConfigSearchResultsTests { "name", "description", ConfigType.CHIME, - EnumSet.of(Feature.INDEX_MANAGEMENT), + setOf(FEATURE_INDEX_MANAGEMENT), configData = Chime("https://domain.com/sample_url#1234567890") ) val configInfo2 = NotificationConfigInfo( @@ -229,7 +230,7 @@ internal class NotificationConfigSearchResultsTests { "name", "description", ConfigType.SLACK, - EnumSet.of(Feature.INDEX_MANAGEMENT), + setOf(FEATURE_INDEX_MANAGEMENT), isEnabled = true, configData = sampleSlack ) @@ -280,7 +281,7 @@ internal class NotificationConfigSearchResultsTests { "name", "description", ConfigType.SLACK, - EnumSet.of(Feature.INDEX_MANAGEMENT), + setOf(FEATURE_INDEX_MANAGEMENT), isEnabled = true, configData = sampleSlack ) diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationConfigTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationConfigTests.kt index ab45e2fc..c7126ab0 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationConfigTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationConfigTests.kt @@ -28,10 +28,12 @@ package org.opensearch.commons.notifications.model import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Test +import org.opensearch.commons.notifications.NotificationConstants.FEATURE_ALERTING +import org.opensearch.commons.notifications.NotificationConstants.FEATURE_INDEX_MANAGEMENT +import org.opensearch.commons.notifications.NotificationConstants.FEATURE_REPORTS import org.opensearch.commons.utils.createObjectFromJsonString import org.opensearch.commons.utils.getJsonString import org.opensearch.commons.utils.recreateObject -import java.util.EnumSet internal class NotificationConfigTests { @@ -42,7 +44,7 @@ internal class NotificationConfigTests { "name", "description", ConfigType.SLACK, - EnumSet.of(Feature.REPORTS), + setOf(FEATURE_REPORTS), configData = sampleSlack ) val recreatedObject = recreateObject(sampleConfig) { NotificationConfig(it) } @@ -56,7 +58,7 @@ internal class NotificationConfigTests { "name", "description", ConfigType.SLACK, - EnumSet.of(Feature.REPORTS), + setOf(FEATURE_REPORTS), configData = sampleSlack ) val jsonString = getJsonString(sampleConfig) @@ -71,7 +73,7 @@ internal class NotificationConfigTests { "name", "description", ConfigType.CHIME, - EnumSet.of(Feature.ALERTING), + setOf(FEATURE_ALERTING), configData = sampleChime ) val recreatedObject = recreateObject(sampleConfig) { NotificationConfig(it) } @@ -85,7 +87,7 @@ internal class NotificationConfigTests { "name", "description", ConfigType.CHIME, - EnumSet.of(Feature.ALERTING), + setOf(FEATURE_ALERTING), configData = sampleChime ) val jsonString = getJsonString(sampleConfig) @@ -100,7 +102,7 @@ internal class NotificationConfigTests { "name", "description", ConfigType.WEBHOOK, - EnumSet.of(Feature.INDEX_MANAGEMENT), + setOf(FEATURE_INDEX_MANAGEMENT), configData = sampleWebhook ) val recreatedObject = recreateObject(sampleConfig) { NotificationConfig(it) } @@ -114,7 +116,7 @@ internal class NotificationConfigTests { "name", "description", ConfigType.WEBHOOK, - EnumSet.of(Feature.INDEX_MANAGEMENT), + setOf(FEATURE_INDEX_MANAGEMENT), configData = sampleWebhook ) val jsonString = getJsonString(sampleConfig) @@ -129,7 +131,7 @@ internal class NotificationConfigTests { "name", "description", ConfigType.EMAIL, - EnumSet.of(Feature.INDEX_MANAGEMENT), + setOf(FEATURE_INDEX_MANAGEMENT), configData = sampleEmail ) val recreatedObject = recreateObject(sampleConfig) { NotificationConfig(it) } @@ -143,7 +145,7 @@ internal class NotificationConfigTests { "name", "description", ConfigType.EMAIL, - EnumSet.of(Feature.INDEX_MANAGEMENT), + setOf(FEATURE_INDEX_MANAGEMENT), configData = sampleEmail ) val jsonString = getJsonString(sampleConfig) @@ -158,7 +160,7 @@ internal class NotificationConfigTests { "name", "description", ConfigType.SMTP_ACCOUNT, - EnumSet.of(Feature.INDEX_MANAGEMENT), + setOf(FEATURE_INDEX_MANAGEMENT), configData = smtpAccount ) val jsonString = getJsonString(sampleConfig) @@ -173,7 +175,7 @@ internal class NotificationConfigTests { "name", "description", ConfigType.SMTP_ACCOUNT, - EnumSet.of(Feature.INDEX_MANAGEMENT), + setOf(FEATURE_INDEX_MANAGEMENT), configData = sampleSmtpAccount ) val recreatedObject = recreateObject(sampleConfig) { NotificationConfig(it) } @@ -187,7 +189,7 @@ internal class NotificationConfigTests { "name", "description", ConfigType.EMAIL_GROUP, - EnumSet.of(Feature.INDEX_MANAGEMENT), + setOf(FEATURE_INDEX_MANAGEMENT), configData = sampleEmailGroup ) val jsonString = getJsonString(sampleConfig) @@ -202,7 +204,7 @@ internal class NotificationConfigTests { "name", "description", ConfigType.EMAIL_GROUP, - EnumSet.of(Feature.INDEX_MANAGEMENT), + setOf(FEATURE_INDEX_MANAGEMENT), configData = sampleEmailGroup ) val recreatedObject = recreateObject(sampleConfig) { NotificationConfig(it) } @@ -217,7 +219,7 @@ internal class NotificationConfigTests { "name", "description", ConfigType.NONE, - EnumSet.of(Feature.INDEX_MANAGEMENT), + setOf(FEATURE_INDEX_MANAGEMENT), isEnabled = true, configData = sampleSlack ) @@ -240,13 +242,13 @@ internal class NotificationConfigTests { } @Test - fun `Config should safely ignore unknown feature type in json object`() { + fun `Config should safely accepts unknown feature type in json object`() { val sampleWebhook = Webhook("https://domain.com/sample_webhook_url#1234567890") val sampleConfig = NotificationConfig( "name", "description", ConfigType.WEBHOOK, - EnumSet.of(Feature.INDEX_MANAGEMENT, Feature.NONE), + setOf(FEATURE_INDEX_MANAGEMENT, "NewFeature1", "NewFeature2"), isEnabled = true, configData = sampleWebhook ) diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationEventInfoTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationEventInfoTests.kt index e23ca1e0..9f45fbb0 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationEventInfoTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationEventInfoTests.kt @@ -29,6 +29,7 @@ package org.opensearch.commons.notifications.model import org.junit.jupiter.api.Assertions import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Test +import org.opensearch.commons.notifications.NotificationConstants.FEATURE_ALERTING import org.opensearch.commons.utils.createObjectFromJsonString import org.opensearch.commons.utils.getJsonString import org.opensearch.commons.utils.recreateObject @@ -41,7 +42,7 @@ internal class NotificationEventInfoTests { val sampleEventSource = EventSource( "title", "reference_id", - Feature.ALERTING, + FEATURE_ALERTING, severity = SeverityType.INFO ) val sampleStatus = EventStatus( @@ -69,7 +70,7 @@ internal class NotificationEventInfoTests { val sampleEventSource = EventSource( "title", "reference_id", - Feature.ALERTING, + FEATURE_ALERTING, severity = SeverityType.INFO ) val sampleStatus = EventStatus( @@ -98,7 +99,7 @@ internal class NotificationEventInfoTests { val sampleEventSource = EventSource( "title", "reference_id", - Feature.ALERTING, + FEATURE_ALERTING, severity = SeverityType.INFO ) val sampleStatus = EventStatus( @@ -155,7 +156,7 @@ internal class NotificationEventInfoTests { val sampleEventSource = EventSource( "title", "reference_id", - Feature.ALERTING, + FEATURE_ALERTING, severity = SeverityType.INFO ) val sampleStatus = EventStatus( @@ -215,7 +216,7 @@ internal class NotificationEventInfoTests { val sampleEventSource = EventSource( "title", "reference_id", - Feature.ALERTING, + FEATURE_ALERTING, severity = SeverityType.INFO ) val sampleStatus = EventStatus( diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationEventSearchResultTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationEventSearchResultTests.kt index d09fe9d2..078d4910 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationEventSearchResultTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationEventSearchResultTests.kt @@ -30,6 +30,8 @@ import org.apache.lucene.search.TotalHits import org.junit.jupiter.api.Assertions import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Test +import org.opensearch.commons.notifications.NotificationConstants.FEATURE_ALERTING +import org.opensearch.commons.notifications.NotificationConstants.FEATURE_REPORTS import org.opensearch.commons.utils.createObjectFromJsonString import org.opensearch.commons.utils.getJsonString import org.opensearch.commons.utils.recreateObject @@ -53,7 +55,7 @@ internal class NotificationEventSearchResultTests { val sampleEventSource = EventSource( "title", "reference_id", - Feature.ALERTING, + FEATURE_ALERTING, severity = SeverityType.INFO ) val sampleStatus = EventStatus( @@ -80,13 +82,13 @@ internal class NotificationEventSearchResultTests { val eventSource1 = EventSource( "title 1", "reference_id_1", - Feature.ALERTING, + FEATURE_ALERTING, severity = SeverityType.INFO ) val eventSource2 = EventSource( "title 2", "reference_id_2", - Feature.REPORTS, + FEATURE_REPORTS, severity = SeverityType.HIGH ) val status1 = EventStatus( @@ -147,13 +149,13 @@ internal class NotificationEventSearchResultTests { val eventSource1 = EventSource( "title 1", "reference_id_1", - Feature.ALERTING, + FEATURE_ALERTING, severity = SeverityType.INFO ) val eventSource2 = EventSource( "title 2", "reference_id_2", - Feature.REPORTS, + FEATURE_REPORTS, severity = SeverityType.HIGH ) val status1 = EventStatus( @@ -213,7 +215,7 @@ internal class NotificationEventSearchResultTests { val sampleEventSource = EventSource( "title", "reference_id", - Feature.ALERTING, + FEATURE_ALERTING, severity = SeverityType.INFO ) val sampleStatus = EventStatus( @@ -243,13 +245,13 @@ internal class NotificationEventSearchResultTests { val eventSource1 = EventSource( "title 1", "reference_id_1", - Feature.ALERTING, + FEATURE_ALERTING, severity = SeverityType.INFO ) val eventSource2 = EventSource( "title 2", "reference_id_2", - Feature.REPORTS, + FEATURE_REPORTS, severity = SeverityType.HIGH ) val status1 = EventStatus( @@ -296,7 +298,7 @@ internal class NotificationEventSearchResultTests { val sampleEventSource = EventSource( "title", "reference_id", - Feature.ALERTING, + FEATURE_ALERTING, severity = SeverityType.INFO ) val sampleStatus = EventStatus( @@ -364,7 +366,7 @@ internal class NotificationEventSearchResultTests { val sampleEventSource = EventSource( "title", "reference_id", - Feature.ALERTING, + FEATURE_ALERTING, severity = SeverityType.INFO ) val sampleStatus = EventStatus( diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationEventTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationEventTests.kt index 4a135d0c..92c53fd8 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationEventTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationEventTests.kt @@ -29,6 +29,8 @@ package org.opensearch.commons.notifications.model import org.junit.jupiter.api.Assertions import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Test +import org.opensearch.commons.notifications.NotificationConstants.FEATURE_ALERTING +import org.opensearch.commons.notifications.NotificationConstants.FEATURE_REPORTS import org.opensearch.commons.utils.createObjectFromJsonString import org.opensearch.commons.utils.getJsonString import org.opensearch.commons.utils.recreateObject @@ -40,7 +42,7 @@ internal class NotificationEventTests { val sampleEventSource = EventSource( "title", "reference_id", - Feature.ALERTING, + FEATURE_ALERTING, severity = SeverityType.INFO ) val sampleStatus = EventStatus( @@ -59,7 +61,7 @@ internal class NotificationEventTests { val sampleEventSource = EventSource( "title", "reference_id", - Feature.REPORTS, + FEATURE_REPORTS, severity = SeverityType.INFO ) val sampleStatus = EventStatus( @@ -79,7 +81,7 @@ internal class NotificationEventTests { val sampleEventSource = EventSource( "title", "reference_id", - Feature.ALERTING, + FEATURE_ALERTING, tags = listOf("tag1", "tag2"), severity = SeverityType.INFO ) diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/SesAccountTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/SesAccountTests.kt new file mode 100644 index 00000000..c99506fd --- /dev/null +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/SesAccountTests.kt @@ -0,0 +1,151 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + * + * Modifications Copyright OpenSearch Contributors. See + * GitHub history for details. + */ + +package org.opensearch.commons.notifications.model + +import com.fasterxml.jackson.core.JsonParseException +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.assertThrows +import org.opensearch.commons.utils.createObjectFromJsonString +import org.opensearch.commons.utils.getJsonString +import org.opensearch.commons.utils.recreateObject + +internal class SesAccountTests { + + @Test + fun `SES should throw exception if empty region`() { + assertThrows { + SesAccount("", null, "from@domain.com") + } + val jsonString = """ + { + "region":"", + "from_address":"from@domain.com" + } + """.trimIndent() + assertThrows { + createObjectFromJsonString(jsonString) { SesAccount.parse(it) } + } + } + + @Test + fun `SES should throw exception if invalid role ARN`() { + assertThrows { + SesAccount("us-east-1", "arn:aws:iam:us-east-1:0123456789:role-test", "from@domain.com") + } + val jsonString = """ + { + "region":"us-east-1", + "role_arn":"arn:aws:iam:us-east-1:0123456789:role-test", + "from_address":"from@domain.com" + } + """.trimIndent() + assertThrows { + createObjectFromJsonString(jsonString) { SesAccount.parse(it) } + } + } + + @Test + fun `SES should throw exception when email id is invalid`() { + val jsonString = """ + { + "region":"us-east-1", + "from_address":".from@domain.com" + } + """.trimIndent() + assertThrows { + createObjectFromJsonString(jsonString) { SesAccount.parse(it) } + } + } + + @Test + fun `SES serialize and deserialize transport object should be equal`() { + val sesAccount = SesAccount("us-east-1", "arn:aws:iam::012345678912:role/iam-test", "from@domain.com") + val recreatedObject = recreateObject(sesAccount) { SesAccount(it) } + assertEquals(sesAccount, recreatedObject) + } + + @Test + fun `SES serialize and deserialize using json object should be equal`() { + val sesAccount = SesAccount("us-east-1", "arn:aws:iam::012345678912:role/iam-test", "from@domain.com") + val jsonString = getJsonString(sesAccount) + val recreatedObject = createObjectFromJsonString(jsonString) { SesAccount.parse(it) } + assertEquals(sesAccount, recreatedObject) + } + + @Test + fun `SES should deserialize json object using parser`() { + val sesAccount = SesAccount("us-east-1", "arn:aws:iam::012345678912:role/iam-test", "from@domain.com") + val jsonString = """ + { + "region":"${sesAccount.awsRegion}", + "role_arn":"${sesAccount.roleArn}", + "from_address":"${sesAccount.fromAddress}" + } + """.trimIndent() + val recreatedObject = createObjectFromJsonString(jsonString) { SesAccount.parse(it) } + assertEquals(sesAccount, recreatedObject) + } + + @Test + fun `SES should throw exception when invalid json object is passed`() { + val jsonString = "sample message" + assertThrows { + createObjectFromJsonString(jsonString) { SesAccount.parse(it) } + } + } + + @Test + fun `SES should throw exception when region is replace with region2 in json object`() { + val jsonString = """ + { + "region2":"us-east-1", + "role_arn":"arn:aws:iam::012345678912:role/iam-test", + "from_address":"from@domain.com" + } + """.trimIndent() + assertThrows { + createObjectFromJsonString(jsonString) { SesAccount.parse(it) } + } + } + + @Test + fun `SES should throw exception when from_address is replace with from_address2 in json object`() { + val jsonString = """ + { + "region":"us-east-1", + "role_arn":"arn:aws:iam::012345678912:role/iam-test", + "from_address2":"from@domain.com" + } + """.trimIndent() + assertThrows { + createObjectFromJsonString(jsonString) { SesAccount.parse(it) } + } + } + + @Test + fun `SES should safely ignore extra field in json object`() { + val sesAccount = SesAccount("us-east-1", "arn:aws:iam::012345678912:role/iam-test", "from@domain.com") + val jsonString = """ + { + "region":"${sesAccount.awsRegion}", + "role_arn":"${sesAccount.roleArn}", + "from_address":"${sesAccount.fromAddress}", + "extra_field_1":["extra", "value"], + "extra_field_2":{"extra":"value"}, + "extra_field_3":"extra value 3" + } + """.trimIndent() + val recreatedObject = createObjectFromJsonString(jsonString) { SesAccount.parse(it) } + assertEquals(sesAccount, recreatedObject) + } +} diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/SNSTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/SnsTests.kt similarity index 65% rename from src/test/kotlin/org/opensearch/commons/notifications/model/SNSTests.kt rename to src/test/kotlin/org/opensearch/commons/notifications/model/SnsTests.kt index 46d7cfc8..03d494d2 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/SNSTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/SnsTests.kt @@ -19,87 +19,87 @@ import org.opensearch.commons.utils.createObjectFromJsonString import org.opensearch.commons.utils.getJsonString import org.opensearch.commons.utils.recreateObject -internal class SNSTests { +internal class SnsTests { @Test fun `SNS should throw exception if empty topic`() { assertThrows(IllegalArgumentException::class.java) { - SNS("", null) + Sns("", null) } val jsonString = "{\"topic_arn\":\"\"}" assertThrows(IllegalArgumentException::class.java) { - createObjectFromJsonString(jsonString) { SNS.parse(it) } + createObjectFromJsonString(jsonString) { Sns.parse(it) } } } @Test fun `SNS should throw exception if invalid topic ARN`() { assertThrows(IllegalArgumentException::class.java) { - SNS("arn:aws:es:us-east-1:012345678989:test", null) + Sns("arn:aws:es:us-east-1:012345678989:test", null) } val jsonString = "{\"topic_arn\":\"arn:aws:es:us-east-1:012345678989:test\"}" assertThrows(IllegalArgumentException::class.java) { - createObjectFromJsonString(jsonString) { SNS.parse(it) } + createObjectFromJsonString(jsonString) { Sns.parse(it) } } } @Test fun `SNS should throw exception if invalid role ARN`() { assertThrows(IllegalArgumentException::class.java) { - SNS("arn:aws:sns:us-east-1:012345678912:topic-test", "arn:aws:iam:us-east-1:0123456789:role-test") + Sns("arn:aws:sns:us-east-1:012345678912:topic-test", "arn:aws:iam:us-east-1:0123456789:role-test") } val jsonString = "{\"topic_arn\":\"arn:aws:sns:us-east-1:012345678912:topic-test\",\"role_arn\":\"arn:aws:iam:us-east-1:0123456789:role-test\"}" assertThrows(IllegalArgumentException::class.java) { - createObjectFromJsonString(jsonString) { SNS.parse(it) } + createObjectFromJsonString(jsonString) { Sns.parse(it) } } } @Test fun `SNS serialize and deserialize transport object should be equal`() { - val sampleSNS = SNS("arn:aws:sns:us-east-1:012345678912:topic-test", "arn:aws:iam::012345678912:role/iam-test") - val recreatedObject = recreateObject(sampleSNS) { SNS(it) } - Assertions.assertEquals(sampleSNS, recreatedObject) + val sampleSns = Sns("arn:aws:sns:us-east-1:012345678912:topic-test", "arn:aws:iam::012345678912:role/iam-test") + val recreatedObject = recreateObject(sampleSns) { Sns(it) } + Assertions.assertEquals(sampleSns, recreatedObject) } @Test fun `SNS serialize and deserialize using json object should be equal`() { - val sampleSNS = SNS("arn:aws:sns:us-east-1:012345678912:topic-test", "arn:aws:iam::012345678912:role/iam-test") - val jsonString = getJsonString(sampleSNS) - val recreatedObject = createObjectFromJsonString(jsonString) { SNS.parse(it) } - Assertions.assertEquals(sampleSNS, recreatedObject) + val sampleSns = Sns("arn:aws:sns:us-east-1:012345678912:topic-test", "arn:aws:iam::012345678912:role/iam-test") + val jsonString = getJsonString(sampleSns) + val recreatedObject = createObjectFromJsonString(jsonString) { Sns.parse(it) } + Assertions.assertEquals(sampleSns, recreatedObject) } @Test fun `SNS should deserialize json object using parser`() { - val sampleSNS = SNS("arn:aws:sns:us-east-1:012345678912:topic-test", "arn:aws:iam::012345678912:role/iam-test") - val jsonString = "{\"topic_arn\":\"${sampleSNS.topicARN}\",\"role_arn\":\"${sampleSNS.roleARN}\"}" - val recreatedObject = createObjectFromJsonString(jsonString) { SNS.parse(it) } - Assertions.assertEquals(sampleSNS, recreatedObject) + val sampleSns = Sns("arn:aws:sns:us-east-1:012345678912:topic-test", "arn:aws:iam::012345678912:role/iam-test") + val jsonString = "{\"topic_arn\":\"${sampleSns.topicArn}\",\"role_arn\":\"${sampleSns.roleArn}\"}" + val recreatedObject = createObjectFromJsonString(jsonString) { Sns.parse(it) } + Assertions.assertEquals(sampleSns, recreatedObject) } @Test fun `SNS should throw exception when invalid json object is passed`() { val jsonString = "sample message" assertThrows(JsonParseException::class.java) { - createObjectFromJsonString(jsonString) { SNS.parse(it) } + createObjectFromJsonString(jsonString) { Sns.parse(it) } } } @Test fun `SNS should throw exception when arn is replace with arn2 in json object`() { - val sampleSNS = SNS("arn:aws:sns:us-east-1:012345678912:topic-test", "arn:aws:iam::012345678912:role/iam-test") - val jsonString = "{\"topic_arn2\":\"${sampleSNS.topicARN}\",\"role_arn\":\"${sampleSNS.roleARN}\"}" + val sampleSns = Sns("arn:aws:sns:us-east-1:012345678912:topic-test", "arn:aws:iam::012345678912:role/iam-test") + val jsonString = "{\"topic_arn2\":\"${sampleSns.topicArn}\",\"role_arn\":\"${sampleSns.roleArn}\"}" assertThrows(IllegalArgumentException::class.java) { - createObjectFromJsonString(jsonString) { SNS.parse(it) } + createObjectFromJsonString(jsonString) { Sns.parse(it) } } } @Test fun `SNS should safely ignore extra field in json object`() { - val sampleSNS = SNS("arn:aws:sns:us-east-1:012345678912:topic-test", null) - val jsonString = "{\"topic_arn\":\"${sampleSNS.topicARN}\", \"another\":\"field\"}" - val recreatedObject = createObjectFromJsonString(jsonString) { SNS.parse(it) } - Assertions.assertEquals(sampleSNS, recreatedObject) + val sampleSns = Sns("arn:aws:sns:us-east-1:012345678912:topic-test", null) + val jsonString = "{\"topic_arn\":\"${sampleSns.topicArn}\", \"another\":\"field\"}" + val recreatedObject = createObjectFromJsonString(jsonString) { Sns.parse(it) } + Assertions.assertEquals(sampleSns, recreatedObject) } } From 0b76166d9ef472537f0d5fc38917cd6e8236ea19 Mon Sep 17 00:00:00 2001 From: Drew Baugher <46505179+dbbaughe@users.noreply.github.com> Date: Thu, 12 Aug 2021 17:47:12 -0700 Subject: [PATCH 079/140] Adds legacy chime, slack, custom webhook messages, request/response f (#53) * Adds legacy chime, slack, custom webhook messages, request/response for publishing legacy notifications, and method for executing transport action Signed-off-by: Drew Baugher <46505179+dbbaughe@users.noreply.github.com> * Fixes import and removes username/password that is not used by ISM Signed-off-by: Drew Baugher <46505179+dbbaughe@users.noreply.github.com> * Throws error for toXContent for legacy notification response Signed-off-by: Drew Baugher <46505179+dbbaughe@users.noreply.github.com> * Renames legacy destination types to have legacy prefix Signed-off-by: Drew Baugher <46505179+dbbaughe@users.noreply.github.com> * Obfuscates message to remove from logs in toString method Signed-off-by: Drew Baugher <46505179+dbbaughe@users.noreply.github.com> * Makes destinationt type private and updates places to use getter Signed-off-by: Drew Baugher <46505179+dbbaughe@users.noreply.github.com> * Inlines destination type Signed-off-by: Drew Baugher <46505179+dbbaughe@users.noreply.github.com> * Makes base message content final Signed-off-by: Drew Baugher <46505179+dbbaughe@users.noreply.github.com> * Requires url to be defined in LegacyCustomWebhookMessage for use across transport wire and only writes the full url instead of each individual part Signed-off-by: Drew Baugher <46505179+dbbaughe@users.noreply.github.com> Signed-off-by: Zelin Hao --- .../message/LegacyBaseMessage.java | 128 ++++++++ .../message/LegacyChimeMessage.java | 91 ++++++ .../message/LegacyCustomWebhookMessage.java | 274 ++++++++++++++++++ .../message/LegacyDestinationType.java | 36 +++ .../message/LegacySlackMessage.java | 95 ++++++ .../response/LegacyBaseResponse.java | 60 ++++ .../response/LegacyDestinationResponse.java | 82 ++++++ .../NotificationsPluginInterface.kt | 28 ++ .../LegacyPublishNotificationRequest.kt | 82 ++++++ .../LegacyPublishNotificationResponse.kt | 63 ++++ .../action/NotificationsActions.kt | 13 + .../message/LegacyChimeMessageTest.java | 100 +++++++ .../LegacyCustomWebhookMessageTest.java | 177 +++++++++++ .../message/LegacySlackMessageTest.java | 110 +++++++ .../LegacyDestinationResponseTest.java | 82 ++++++ .../NotificationsPluginInterfaceTests.kt | 24 ++ .../LegacyPublishNotificationRequestTests.kt | 42 +++ .../LegacyPublishNotificationResponseTests.kt | 29 ++ 18 files changed, 1516 insertions(+) create mode 100644 src/main/java/org/opensearch/commons/destination/message/LegacyBaseMessage.java create mode 100644 src/main/java/org/opensearch/commons/destination/message/LegacyChimeMessage.java create mode 100644 src/main/java/org/opensearch/commons/destination/message/LegacyCustomWebhookMessage.java create mode 100644 src/main/java/org/opensearch/commons/destination/message/LegacyDestinationType.java create mode 100644 src/main/java/org/opensearch/commons/destination/message/LegacySlackMessage.java create mode 100644 src/main/java/org/opensearch/commons/destination/response/LegacyBaseResponse.java create mode 100644 src/main/java/org/opensearch/commons/destination/response/LegacyDestinationResponse.java create mode 100644 src/main/kotlin/org/opensearch/commons/notifications/action/LegacyPublishNotificationRequest.kt create mode 100644 src/main/kotlin/org/opensearch/commons/notifications/action/LegacyPublishNotificationResponse.kt create mode 100644 src/test/java/org/opensearch/commons/destination/message/LegacyChimeMessageTest.java create mode 100644 src/test/java/org/opensearch/commons/destination/message/LegacyCustomWebhookMessageTest.java create mode 100644 src/test/java/org/opensearch/commons/destination/message/LegacySlackMessageTest.java create mode 100644 src/test/java/org/opensearch/commons/destination/response/LegacyDestinationResponseTest.java create mode 100644 src/test/kotlin/org/opensearch/commons/notifications/action/LegacyPublishNotificationRequestTests.kt create mode 100644 src/test/kotlin/org/opensearch/commons/notifications/action/LegacyPublishNotificationResponseTests.kt diff --git a/src/main/java/org/opensearch/commons/destination/message/LegacyBaseMessage.java b/src/main/java/org/opensearch/commons/destination/message/LegacyBaseMessage.java new file mode 100644 index 00000000..b5122f31 --- /dev/null +++ b/src/main/java/org/opensearch/commons/destination/message/LegacyBaseMessage.java @@ -0,0 +1,128 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + * + * Modifications Copyright OpenSearch Contributors. See + * GitHub history for details. + */ + +/* + * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package org.opensearch.commons.destination.message; + +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.Map; + +import org.apache.http.client.utils.URIBuilder; +import org.opensearch.common.Strings; +import org.opensearch.common.io.stream.StreamInput; +import org.opensearch.common.io.stream.StreamOutput; +import org.opensearch.common.io.stream.Writeable; + +/** + * This class holds the generic parameters required for a + * message. + */ +public abstract class LegacyBaseMessage implements Writeable { + + private final LegacyDestinationType destinationType; + protected String destinationName; + protected String url; + private final String content; + + LegacyBaseMessage(final LegacyDestinationType destinationType, final String destinationName, final String content) { + if (destinationType == null) { + throw new IllegalArgumentException("Channel type must be defined"); + } + if (!Strings.hasLength(destinationName)) { + throw new IllegalArgumentException("Channel name must be defined"); + } + this.destinationType = destinationType; + this.destinationName = destinationName; + this.content = content; + } + + LegacyBaseMessage(final LegacyDestinationType destinationType, final String destinationName, final String content, final String url) { + this(destinationType, destinationName, content); + if (url == null) { + throw new IllegalArgumentException("url is invalid or empty"); + } + this.url = url; + } + + LegacyBaseMessage(StreamInput streamInput) throws IOException { + this.destinationType = streamInput.readEnum(LegacyDestinationType.class); + this.destinationName = streamInput.readString(); + this.url = streamInput.readOptionalString(); + this.content = streamInput.readString(); + } + + public void setUrl(String url) { + this.url = url; + } + + public LegacyDestinationType getChannelType() { + return destinationType; + } + + public String getChannelName() { + return destinationName; + } + + public String getMessageContent() { + return content; + } + + public String getUrl() { + return url; + } + + public URI getUri() { + return buildUri(getUrl().trim(), null, null, -1, null, null); + } + + protected URI buildUri(String endpoint, String scheme, String host, int port, String path, Map queryParams) { + try { + if (Strings.isNullOrEmpty(endpoint)) { + if (Strings.isNullOrEmpty(scheme)) { + scheme = "https"; + } + URIBuilder uriBuilder = new URIBuilder(); + if (queryParams != null) { + for (Map.Entry e : queryParams.entrySet()) + uriBuilder.addParameter(e.getKey(), e.getValue()); + } + return uriBuilder.setScheme(scheme).setHost(host).setPort(port).setPath(path).build(); + } + return new URIBuilder(endpoint).build(); + } catch (URISyntaxException exception) { + throw new IllegalStateException("Error creating URI"); + } + } + + @Override + public void writeTo(StreamOutput streamOutput) throws IOException { + streamOutput.writeEnum(destinationType); + streamOutput.writeString(destinationName); + streamOutput.writeOptionalString(url); + streamOutput.writeString(content); + } +} diff --git a/src/main/java/org/opensearch/commons/destination/message/LegacyChimeMessage.java b/src/main/java/org/opensearch/commons/destination/message/LegacyChimeMessage.java new file mode 100644 index 00000000..b457d9aa --- /dev/null +++ b/src/main/java/org/opensearch/commons/destination/message/LegacyChimeMessage.java @@ -0,0 +1,91 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + * + * Modifications Copyright OpenSearch Contributors. See + * GitHub history for details. + */ + +/* + * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package org.opensearch.commons.destination.message; + +import java.io.IOException; + +import org.opensearch.common.Strings; +import org.opensearch.common.io.stream.StreamInput; + +/** + * This class holds the contents of an Chime message + */ +public class LegacyChimeMessage extends LegacyBaseMessage { + private final String message; + + private LegacyChimeMessage(final String destinationName, final String url, final String message) { + super(LegacyDestinationType.LEGACY_CHIME, destinationName, message, url); + + if (Strings.isNullOrEmpty(message)) { + throw new IllegalArgumentException("Message content is missing"); + } + + this.message = message; + } + + public LegacyChimeMessage(StreamInput streamInput) throws IOException { + super(streamInput); + this.message = super.getMessageContent(); + } + + @Override + public String toString() { + return "DestinationType: " + getChannelType() + ", DestinationName:" + destinationName + ", Url: " + url + ", Message: <...>"; + } + + public static class Builder { + private String message; + private final String destinationName; + private String url; + + public Builder(String destinationName) { + this.destinationName = destinationName; + } + + public LegacyChimeMessage.Builder withMessage(String message) { + this.message = message; + return this; + } + + public LegacyChimeMessage.Builder withUrl(String url) { + this.url = url; + return this; + } + + public LegacyChimeMessage build() { + return new LegacyChimeMessage(this.destinationName, this.url, this.message); + } + } + + public String getMessage() { + return message; + } + + public String getUrl() { + return url; + } +} diff --git a/src/main/java/org/opensearch/commons/destination/message/LegacyCustomWebhookMessage.java b/src/main/java/org/opensearch/commons/destination/message/LegacyCustomWebhookMessage.java new file mode 100644 index 00000000..9645b327 --- /dev/null +++ b/src/main/java/org/opensearch/commons/destination/message/LegacyCustomWebhookMessage.java @@ -0,0 +1,274 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + * + * Modifications Copyright OpenSearch Contributors. See + * GitHub history for details. + */ + +/* + * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package org.opensearch.commons.destination.message; + +import java.io.IOException; +import java.net.URI; +import java.util.Map; + +import org.apache.http.client.methods.HttpPatch; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.client.methods.HttpPut; +import org.opensearch.common.Strings; +import org.opensearch.common.io.stream.StreamInput; +import org.opensearch.common.io.stream.StreamOutput; + +/** + * This class holds the content of an CustomWebhook message + */ +public class LegacyCustomWebhookMessage extends LegacyBaseMessage { + + private final String message; + private final String url; + private final String scheme; + private final String host; + private final String method; + private final int port; + private String path; + private final Map queryParams; + private Map headerParams; + + private LegacyCustomWebhookMessage( + final String destinationName, + final String url, + final String scheme, + final String host, + final Integer port, + final String path, + final String method, + final Map queryParams, + final Map headerParams, + final String message + ) { + super(LegacyDestinationType.LEGACY_CUSTOM_WEBHOOK, destinationName, message); + + if (!Strings.isNullOrEmpty(url)) { + setUrl(url.trim()); + } + + if (Strings.isNullOrEmpty(message)) { + throw new IllegalArgumentException("Message content is missing"); + } + + this.scheme = Strings.isNullOrEmpty(scheme) ? "https" : scheme; + this.port = port == null ? -1 : port; + + if (!Strings.isNullOrEmpty(path)) { + if (!path.startsWith("/")) { + this.path = "/" + path; + } + } + + if (Strings.isNullOrEmpty(url) && Strings.isNullOrEmpty(host)) { + throw new IllegalArgumentException("Either fully qualified URL or host name should be provided"); + } + + if (Strings.isNullOrEmpty(method)) { + // Default to POST for backwards compatibility + this.method = "POST"; + } else if (!HttpPost.METHOD_NAME.equals(method) && !HttpPut.METHOD_NAME.equals(method) && !HttpPatch.METHOD_NAME.equals(method)) { + throw new IllegalArgumentException("Invalid method supplied. Only POST, PUT and PATCH are allowed"); + } else { + this.method = method; + } + + this.message = message; + this.url = url; + this.host = host; + this.queryParams = queryParams; + this.headerParams = headerParams; + } + + public LegacyCustomWebhookMessage(StreamInput streamInput) throws IOException { + super(streamInput); + this.message = super.getMessageContent(); + this.url = streamInput.readOptionalString(); + this.scheme = null; + this.host = null; + this.method = streamInput.readOptionalString(); + this.port = -1; + this.path = null; + this.queryParams = null; + if (streamInput.readBoolean()) { + @SuppressWarnings("unchecked") + Map headerParams = (Map) (Map) streamInput.readMap(); + this.headerParams = headerParams; + } + } + + @Override + public String toString() { + return "DestinationType: " + + getChannelType() + + ", DestinationName:" + + destinationName + + ", Url: " + + url + + ", scheme: " + + scheme + + ", Host: " + + host + + ", Port: " + + port + + ", Path: " + + path + + ", Method: " + + method + + ", Message: <...>"; + } + + public static class Builder { + private String message; + private final String destinationName; + private String url; + private String scheme; + private String host; + private Integer port; + private String path; + private String method; + private Map queryParams; + private Map headerParams; + + public Builder(String destinationName) { + this.destinationName = destinationName; + } + + public LegacyCustomWebhookMessage.Builder withScheme(String scheme) { + this.scheme = scheme; + return this; + } + + public LegacyCustomWebhookMessage.Builder withHost(String host) { + this.host = host; + return this; + } + + public LegacyCustomWebhookMessage.Builder withPort(Integer port) { + this.port = port; + return this; + } + + public LegacyCustomWebhookMessage.Builder withPath(String path) { + this.path = path; + return this; + } + + public LegacyCustomWebhookMessage.Builder withMethod(String method) { + this.method = method; + return this; + } + + public LegacyCustomWebhookMessage.Builder withQueryParams(Map queryParams) { + this.queryParams = queryParams; + return this; + } + + public LegacyCustomWebhookMessage.Builder withHeaderParams(Map headerParams) { + this.headerParams = headerParams; + return this; + } + + public LegacyCustomWebhookMessage.Builder withMessage(String message) { + this.message = message; + return this; + } + + public LegacyCustomWebhookMessage.Builder withUrl(String url) { + this.url = url; + return this; + } + + public LegacyCustomWebhookMessage build() { + return new LegacyCustomWebhookMessage( + this.destinationName, + this.url, + this.scheme, + this.host, + this.port, + this.path, + this.method, + this.queryParams, + this.headerParams, + this.message + ); + } + } + + public String getScheme() { + return scheme; + } + + public String getHost() { + return host; + } + + public int getPort() { + return port; + } + + public String getPath() { + return path; + } + + public String getMethod() { + return method; + } + + public Map getQueryParams() { + return queryParams; + } + + public Map getHeaderParams() { + return headerParams; + } + + public URI getUri() { + return buildUri(getUrl(), getScheme(), getHost(), getPort(), getPath(), getQueryParams()); + } + + public String getMessage() { + return message; + } + + @Override + public void writeTo(StreamOutput streamOutput) throws IOException { + super.writeTo(streamOutput); + // Making LegacyCustomWebhookMessage streamable is purely to support the new pass through API from ISM -> Notification plugin + // and it only supports LegacyCustomWebhookMessage when the url is already constructed by ISM. + if (Strings.isNullOrEmpty(getUrl())) { + throw new IllegalStateException("Cannot use LegacyCustomWebhookMessage across transport wire without defining full url."); + } + streamOutput.writeOptionalString(url); + streamOutput.writeOptionalString(method); + streamOutput.writeBoolean(headerParams != null); + if (headerParams != null) { + @SuppressWarnings("unchecked") + Map headerParams = (Map) (Map) this.headerParams; + streamOutput.writeMap(headerParams); + } + } +} diff --git a/src/main/java/org/opensearch/commons/destination/message/LegacyDestinationType.java b/src/main/java/org/opensearch/commons/destination/message/LegacyDestinationType.java new file mode 100644 index 00000000..85689510 --- /dev/null +++ b/src/main/java/org/opensearch/commons/destination/message/LegacyDestinationType.java @@ -0,0 +1,36 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + * + * Modifications Copyright OpenSearch Contributors. See + * GitHub history for details. + */ + +/* + * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package org.opensearch.commons.destination.message; + +/** + * Supported legacy notification destinations for Index Management + */ +public enum LegacyDestinationType { + LEGACY_CHIME, + LEGACY_SLACK, + LEGACY_CUSTOM_WEBHOOK +} diff --git a/src/main/java/org/opensearch/commons/destination/message/LegacySlackMessage.java b/src/main/java/org/opensearch/commons/destination/message/LegacySlackMessage.java new file mode 100644 index 00000000..f426894a --- /dev/null +++ b/src/main/java/org/opensearch/commons/destination/message/LegacySlackMessage.java @@ -0,0 +1,95 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + * + * Modifications Copyright OpenSearch Contributors. See + * GitHub history for details. + */ + +/* + * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package org.opensearch.commons.destination.message; + +import java.io.IOException; + +import org.opensearch.common.Strings; +import org.opensearch.common.io.stream.StreamInput; + +/** + * This class holds the content of an Slack message + */ +public class LegacySlackMessage extends LegacyBaseMessage { + private final String message; + + private LegacySlackMessage(final String destinationName, final String url, final String message) { + super(LegacyDestinationType.LEGACY_SLACK, destinationName, message, url); + + if (Strings.isNullOrEmpty(url)) { // add URL validation + throw new IllegalArgumentException("Fully qualified URL is missing/invalid: " + url); + } + + if (Strings.isNullOrEmpty(message)) { + throw new IllegalArgumentException("Message content is missing"); + } + + this.message = message; + } + + public LegacySlackMessage(StreamInput streamInput) throws IOException { + super(streamInput); + this.message = super.getMessageContent(); + } + + @Override + public String toString() { + return "DestinationType: " + getChannelType() + ", DestinationName:" + destinationName + ", Url: " + url + ", Message: <...>"; + } + + public static class Builder { + private String message; + private String destinationName; + private String url; + + public Builder(String channelName) { + this.destinationName = channelName; + } + + public LegacySlackMessage.Builder withMessage(String message) { + this.message = message; + return this; + } + + public LegacySlackMessage.Builder withUrl(String url) { + this.url = url; + return this; + } + + public LegacySlackMessage build() { + return new LegacySlackMessage(this.destinationName, this.url, this.message); + } + } + + public String getMessage() { + return message; + } + + public String getUrl() { + return url; + } +} diff --git a/src/main/java/org/opensearch/commons/destination/response/LegacyBaseResponse.java b/src/main/java/org/opensearch/commons/destination/response/LegacyBaseResponse.java new file mode 100644 index 00000000..bbdd8d70 --- /dev/null +++ b/src/main/java/org/opensearch/commons/destination/response/LegacyBaseResponse.java @@ -0,0 +1,60 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + * + * Modifications Copyright OpenSearch Contributors. See + * GitHub history for details. + */ + +/* + * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package org.opensearch.commons.destination.response; + +import java.io.IOException; + +import org.opensearch.common.io.stream.StreamInput; +import org.opensearch.common.io.stream.StreamOutput; +import org.opensearch.common.io.stream.Writeable; + +/** + * This class holds the generic response attributes + */ +public abstract class LegacyBaseResponse implements Writeable { + protected Integer statusCode; + + LegacyBaseResponse(final Integer statusCode) { + if (statusCode == null) { + throw new IllegalArgumentException("status code is invalid"); + } + this.statusCode = statusCode; + } + + public LegacyBaseResponse(StreamInput streamInput) throws IOException { + this.statusCode = streamInput.readInt(); + } + + public int getStatusCode() { + return statusCode; + } + + @Override + public void writeTo(StreamOutput streamOutput) throws IOException { + streamOutput.writeInt(statusCode); + } +} diff --git a/src/main/java/org/opensearch/commons/destination/response/LegacyDestinationResponse.java b/src/main/java/org/opensearch/commons/destination/response/LegacyDestinationResponse.java new file mode 100644 index 00000000..bb927747 --- /dev/null +++ b/src/main/java/org/opensearch/commons/destination/response/LegacyDestinationResponse.java @@ -0,0 +1,82 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + * + * Modifications Copyright OpenSearch Contributors. See + * GitHub history for details. + */ + +/* + * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package org.opensearch.commons.destination.response; + +import java.io.IOException; + +import org.opensearch.common.io.stream.StreamInput; +import org.opensearch.common.io.stream.StreamOutput; + +/** + * This class is a place holder for destination response metadata + */ +public class LegacyDestinationResponse extends LegacyBaseResponse { + + private final String responseContent; + + private LegacyDestinationResponse(final String responseString, final Integer statusCode) { + super(statusCode); + if (responseString == null) { + throw new IllegalArgumentException("Response is missing"); + } + this.responseContent = responseString; + } + + public LegacyDestinationResponse(StreamInput streamInput) throws IOException { + super(streamInput); + this.responseContent = streamInput.readString(); + } + + public static class Builder { + private String responseContent; + private Integer statusCode; + + public LegacyDestinationResponse.Builder withResponseContent(String responseContent) { + this.responseContent = responseContent; + return this; + } + + public LegacyDestinationResponse.Builder withStatusCode(Integer statusCode) { + this.statusCode = statusCode; + return this; + } + + public LegacyDestinationResponse build() { + return new LegacyDestinationResponse(responseContent, statusCode); + } + } + + public String getResponseContent() { + return this.responseContent; + } + + @Override + public void writeTo(StreamOutput streamOutput) throws IOException { + super.writeTo(streamOutput); + streamOutput.writeString(responseContent); + } +} diff --git a/src/main/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterface.kt b/src/main/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterface.kt index 2f043351..c0646d2d 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterface.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterface.kt @@ -31,6 +31,7 @@ import org.opensearch.action.ActionResponse import org.opensearch.client.node.NodeClient import org.opensearch.common.io.stream.Writeable import org.opensearch.commons.ConfigConstants.OPENSEARCH_SECURITY_USER_INFO_THREAD_CONTEXT +import org.opensearch.commons.notifications.NotificationConstants.FEATURE_INDEX_MANAGEMENT import org.opensearch.commons.notifications.action.BaseResponse import org.opensearch.commons.notifications.action.CreateNotificationConfigRequest import org.opensearch.commons.notifications.action.CreateNotificationConfigResponse @@ -44,12 +45,15 @@ import org.opensearch.commons.notifications.action.GetNotificationEventRequest import org.opensearch.commons.notifications.action.GetNotificationEventResponse import org.opensearch.commons.notifications.action.GetPluginFeaturesRequest import org.opensearch.commons.notifications.action.GetPluginFeaturesResponse +import org.opensearch.commons.notifications.action.LegacyPublishNotificationRequest +import org.opensearch.commons.notifications.action.LegacyPublishNotificationResponse import org.opensearch.commons.notifications.action.NotificationsActions.CREATE_NOTIFICATION_CONFIG_ACTION_TYPE import org.opensearch.commons.notifications.action.NotificationsActions.DELETE_NOTIFICATION_CONFIG_ACTION_TYPE import org.opensearch.commons.notifications.action.NotificationsActions.GET_FEATURE_CHANNEL_LIST_ACTION_TYPE import org.opensearch.commons.notifications.action.NotificationsActions.GET_NOTIFICATION_CONFIG_ACTION_TYPE import org.opensearch.commons.notifications.action.NotificationsActions.GET_NOTIFICATION_EVENT_ACTION_TYPE import org.opensearch.commons.notifications.action.NotificationsActions.GET_PLUGIN_FEATURES_ACTION_TYPE +import org.opensearch.commons.notifications.action.NotificationsActions.LEGACY_PUBLISH_NOTIFICATION_ACTION_TYPE import org.opensearch.commons.notifications.action.NotificationsActions.SEND_NOTIFICATION_ACTION_TYPE import org.opensearch.commons.notifications.action.NotificationsActions.UPDATE_NOTIFICATION_CONFIG_ACTION_TYPE import org.opensearch.commons.notifications.action.SendNotificationRequest @@ -217,6 +221,30 @@ object NotificationsPluginInterface { ) } + /** + * Publishes a notification API using the legacy notification implementation. No REST API. + * Internal API only for the Index Management plugin. + * @param client Node client for making transport action + * @param request The legacy publish notification request + * @param listener The listener for getting response + */ + fun publishLegacyNotification( + client: NodeClient, + request: LegacyPublishNotificationRequest, + listener: ActionListener + ) { + if (request.feature != FEATURE_INDEX_MANAGEMENT) { + // Do not change this; do not pass in FEATURE_INDEX_MANAGEMENT if you are not the Index Management plugin. + throw IllegalArgumentException("The publish notification method only supports the Index Management feature.") + } + + client.execute( + LEGACY_PUBLISH_NOTIFICATION_ACTION_TYPE, + request, + wrapActionListener(listener) { response -> recreateObject(response) { LegacyPublishNotificationResponse(it) } } + ) + } + /** * Wrap action listener on concrete response class by a new created one on ActionResponse. * This is required because the response may be loaded by different classloader across plugins. diff --git a/src/main/kotlin/org/opensearch/commons/notifications/action/LegacyPublishNotificationRequest.kt b/src/main/kotlin/org/opensearch/commons/notifications/action/LegacyPublishNotificationRequest.kt new file mode 100644 index 00000000..e5807102 --- /dev/null +++ b/src/main/kotlin/org/opensearch/commons/notifications/action/LegacyPublishNotificationRequest.kt @@ -0,0 +1,82 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + * + * Modifications Copyright OpenSearch Contributors. See + * GitHub history for details. + */ + +package org.opensearch.commons.notifications.action + +import org.opensearch.action.ActionRequest +import org.opensearch.action.ActionRequestValidationException +import org.opensearch.common.io.stream.StreamInput +import org.opensearch.common.io.stream.StreamOutput +import org.opensearch.common.io.stream.Writeable +import org.opensearch.commons.destination.message.LegacyBaseMessage +import org.opensearch.commons.destination.message.LegacyChimeMessage +import org.opensearch.commons.destination.message.LegacyCustomWebhookMessage +import org.opensearch.commons.destination.message.LegacyDestinationType +import org.opensearch.commons.destination.message.LegacySlackMessage +import java.io.IOException + +/** + * Action Request to publish notification. This is a legacy implementation. + * This should not be used going forward, instead use [SendNotificationRequest]. + */ +class LegacyPublishNotificationRequest : ActionRequest { + val baseMessage: LegacyBaseMessage + val feature: String + + companion object { + /** + * reader to create instance of class from writable. + */ + val reader = Writeable.Reader { LegacyPublishNotificationRequest(it) } + } + + /** + * constructor for creating the class + * @param baseMessage the base message to send + * @param feature the feature that is trying to use this request + */ + constructor( + baseMessage: LegacyBaseMessage, + feature: String + ) { + this.baseMessage = baseMessage + this.feature = feature + } + + /** + * {@inheritDoc} + */ + @Throws(IOException::class) + constructor(input: StreamInput) : super(input) { + baseMessage = when (requireNotNull(input.readEnum(LegacyDestinationType::class.java)) { "Destination type cannot be null" }) { + LegacyDestinationType.LEGACY_CHIME -> LegacyChimeMessage(input) + LegacyDestinationType.LEGACY_CUSTOM_WEBHOOK -> LegacyCustomWebhookMessage(input) + LegacyDestinationType.LEGACY_SLACK -> LegacySlackMessage(input) + } + feature = input.readString() + } + + /** + * {@inheritDoc} + */ + @Throws(IOException::class) + override fun writeTo(output: StreamOutput) { + super.writeTo(output) + output.writeEnum(baseMessage.channelType) + baseMessage.writeTo(output) + output.writeString(feature) + } + + /** + * {@inheritDoc} + */ + override fun validate(): ActionRequestValidationException? = null +} diff --git a/src/main/kotlin/org/opensearch/commons/notifications/action/LegacyPublishNotificationResponse.kt b/src/main/kotlin/org/opensearch/commons/notifications/action/LegacyPublishNotificationResponse.kt new file mode 100644 index 00000000..60f68e71 --- /dev/null +++ b/src/main/kotlin/org/opensearch/commons/notifications/action/LegacyPublishNotificationResponse.kt @@ -0,0 +1,63 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + * + * Modifications Copyright OpenSearch Contributors. See + * GitHub history for details. + */ + +package org.opensearch.commons.notifications.action + +import org.opensearch.common.io.stream.StreamInput +import org.opensearch.common.io.stream.StreamOutput +import org.opensearch.common.io.stream.Writeable +import org.opensearch.common.xcontent.ToXContent +import org.opensearch.common.xcontent.XContentBuilder +import org.opensearch.commons.destination.response.LegacyDestinationResponse +import java.io.IOException + +/** + * Action Response for legacy publish notification. + */ +class LegacyPublishNotificationResponse : BaseResponse { + val destinationResponse: LegacyDestinationResponse + + companion object { + /** + * reader to create instance of class from writable. + */ + val reader = Writeable.Reader { LegacyPublishNotificationResponse(it) } + } + + /** + * constructor for creating the class + * @param destinationResponse the response of the published notification + */ + constructor(destinationResponse: LegacyDestinationResponse) { + this.destinationResponse = destinationResponse + } + + /** + * {@inheritDoc} + */ + @Throws(IOException::class) + constructor(input: StreamInput) : super(input) { + destinationResponse = LegacyDestinationResponse(input) + } + + /** + * {@inheritDoc} + */ + @Throws(IOException::class) + override fun writeTo(output: StreamOutput) { + destinationResponse.writeTo(output) + } + + // This class is only used across transport wire and does not need to implement toXContent + override fun toXContent(builder: XContentBuilder, params: ToXContent.Params): XContentBuilder { + throw IllegalStateException("Legacy notification response is not intended for REST or persistence and does not support XContent.") + } +} diff --git a/src/main/kotlin/org/opensearch/commons/notifications/action/NotificationsActions.kt b/src/main/kotlin/org/opensearch/commons/notifications/action/NotificationsActions.kt index fe7457d0..d93dd29a 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/action/NotificationsActions.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/action/NotificationsActions.kt @@ -72,6 +72,12 @@ object NotificationsActions { */ const val SEND_NOTIFICATION_NAME = "cluster:admin/opensearch/notifications/feature/send" + /** + * Publish legacy notification message. Internal only - Inter plugin communication. + * Only for the Index Management plugin. + */ + const val LEGACY_PUBLISH_NOTIFICATION_NAME = "cluster:admin/opensearch/notifications/feature/publish" + /** * Create notification configuration transport action type. */ @@ -119,4 +125,11 @@ object NotificationsActions { */ val SEND_NOTIFICATION_ACTION_TYPE = ActionType(SEND_NOTIFICATION_NAME, ::SendNotificationResponse) + + /** + * Send legacy notification transport action type. Internal only - Inter plugin communication. + * Only for the Index Management plugin. + */ + val LEGACY_PUBLISH_NOTIFICATION_ACTION_TYPE = + ActionType(LEGACY_PUBLISH_NOTIFICATION_NAME, ::LegacyPublishNotificationResponse) } diff --git a/src/test/java/org/opensearch/commons/destination/message/LegacyChimeMessageTest.java b/src/test/java/org/opensearch/commons/destination/message/LegacyChimeMessageTest.java new file mode 100644 index 00000000..4477789e --- /dev/null +++ b/src/test/java/org/opensearch/commons/destination/message/LegacyChimeMessageTest.java @@ -0,0 +1,100 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + * + * Modifications Copyright OpenSearch Contributors. See + * GitHub history for details. + */ + +/* + * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package org.opensearch.commons.destination.message; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.fail; + +import java.io.IOException; + +import org.junit.jupiter.api.Test; +import org.opensearch.common.io.stream.BytesStreamOutput; +import org.opensearch.common.io.stream.StreamInput; + +public class LegacyChimeMessageTest { + + @Test + public void testBuildingLegacyChimeMessage() { + LegacyChimeMessage message = new LegacyChimeMessage.Builder("custom_webhook") + .withMessage("Hello world") + .withUrl("https://amazon.com") + .build(); + + assertEquals("custom_webhook", message.destinationName); + assertEquals(LegacyDestinationType.LEGACY_CHIME, message.getChannelType()); + assertEquals("Hello world", message.getMessageContent()); + assertEquals("https://amazon.com", message.url); + } + + @Test + public void testRoundTrippingLegacyChimeMessage() throws IOException { + LegacyChimeMessage message = new LegacyChimeMessage.Builder("custom_webhook") + .withMessage("Hello world") + .withUrl("https://amazon.com") + .build(); + BytesStreamOutput out = new BytesStreamOutput(); + message.writeTo(out); + + StreamInput in = StreamInput.wrap(out.bytes().toBytesRef().bytes); + LegacyChimeMessage newMessage = new LegacyChimeMessage(in); + + assertEquals(newMessage.destinationName, message.destinationName); + assertEquals(newMessage.getChannelType(), message.getChannelType()); + assertEquals(newMessage.getMessageContent(), message.getMessageContent()); + assertEquals(newMessage.url, message.url); + } + + @Test + public void testContentMissingMessage() { + try { + new LegacyChimeMessage.Builder("custom_webhook").withUrl("https://amazon.com").build(); + fail("Building legacy chime message without message should fail"); + } catch (IllegalArgumentException e) { + assertEquals("Message content is missing", e.getMessage()); + } + } + + @Test + public void testUrlMissingMessage() { + try { + new LegacyChimeMessage.Builder("custom_webhook").withMessage("Hello world").build(); + fail("Building legacy chime message without url should fail"); + } catch (IllegalArgumentException e) { + assertEquals("url is invalid or empty", e.getMessage()); + } + } + + @Test + public void testMissingDestinationName() { + try { + new LegacyChimeMessage.Builder(null).withMessage("Hello world").withUrl("https://amazon.com").build(); + fail("Building legacy chime message with null destination name should fail"); + } catch (IllegalArgumentException e) { + assertEquals("Channel name must be defined", e.getMessage()); + } + } +} diff --git a/src/test/java/org/opensearch/commons/destination/message/LegacyCustomWebhookMessageTest.java b/src/test/java/org/opensearch/commons/destination/message/LegacyCustomWebhookMessageTest.java new file mode 100644 index 00000000..fba614fd --- /dev/null +++ b/src/test/java/org/opensearch/commons/destination/message/LegacyCustomWebhookMessageTest.java @@ -0,0 +1,177 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + * + * Modifications Copyright OpenSearch Contributors. See + * GitHub history for details. + */ + +/* + * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package org.opensearch.commons.destination.message; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.fail; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpPost; +import org.junit.jupiter.api.Test; +import org.opensearch.common.io.stream.BytesStreamOutput; +import org.opensearch.common.io.stream.StreamInput; + +public class LegacyCustomWebhookMessageTest { + + @Test + public void testBuildingLegacyCustomWebhookMessage() { + LegacyCustomWebhookMessage message = new LegacyCustomWebhookMessage.Builder("custom_webhook") + .withMessage("Hello world") + .withUrl("https://amazon.com") + .build(); + + assertEquals("custom_webhook", message.destinationName); + assertEquals(LegacyDestinationType.LEGACY_CUSTOM_WEBHOOK, message.getChannelType()); + assertEquals("Hello world", message.getMessageContent()); + assertEquals("https://amazon.com", message.getUrl()); + } + + @Test + public void testRoundTrippingLegacyCustomWebhookMessageWithUrl() throws IOException { + LegacyCustomWebhookMessage message = new LegacyCustomWebhookMessage.Builder("custom_webhook") + .withMessage("Hello world") + .withUrl("https://amazon.com") + .build(); + BytesStreamOutput out = new BytesStreamOutput(); + message.writeTo(out); + + StreamInput in = StreamInput.wrap(out.bytes().toBytesRef().bytes); + LegacyCustomWebhookMessage newMessage = new LegacyCustomWebhookMessage(in); + + assertEquals(newMessage.destinationName, message.destinationName); + assertEquals(newMessage.getChannelType(), message.getChannelType()); + assertEquals(newMessage.getMessageContent(), message.getMessageContent()); + assertEquals(newMessage.getUrl(), message.getUrl()); + } + + @Test + public void testRoundTrippingLegacyCustomWebhookMessageWithHostFails() throws IOException { + Map queryParams = new HashMap(); + queryParams.put("token", "sometoken"); + Map headers = new HashMap(); + headers.put("x-token", "sometoken"); + LegacyCustomWebhookMessage message = new LegacyCustomWebhookMessage.Builder("custom_webhook") + .withMessage("Hello world") + .withHost("hooks.chime.aws") + .withPath("incomingwebhooks/abc") + .withMethod(HttpPost.METHOD_NAME) + .withQueryParams(queryParams) + .withHeaderParams(headers) + .withPort(8000) + .withScheme("https") + .build(); + BytesStreamOutput out = new BytesStreamOutput(); + try { + message.writeTo(out); + fail("Writing LegacyCustomWebhookMessage with host instead of url to stream output should fail"); + } catch (IllegalStateException e) { + assertEquals("Cannot use LegacyCustomWebhookMessage across transport wire without defining full url.", e.getMessage()); + } + } + + @Test + public void testContentMissingMessage() { + try { + new LegacyCustomWebhookMessage.Builder("custom_webhook").withUrl("https://amazon.com").build(); + fail("Building legacy custom webhook message without message should fail"); + } catch (IllegalArgumentException e) { + assertEquals("Message content is missing", e.getMessage()); + } + } + + @Test + public void testMissingDestinationName() { + try { + new LegacyCustomWebhookMessage.Builder(null).withMessage("Hello world").withUrl("https://amazon.com").build(); + fail("Building legacy custom webhook message with null destination name should fail"); + } catch (IllegalArgumentException e) { + assertEquals("Channel name must be defined", e.getMessage()); + } + } + + @Test + public void testUnsupportedHttpMethods() { + try { + new LegacyCustomWebhookMessage.Builder("custom_webhook") + .withMessage("Hello world") + .withUrl("https://amazon.com") + .withMethod(HttpGet.METHOD_NAME) + .build(); + fail("Building legacy custom webhook message with unsupported http methods should fail"); + } catch (IllegalArgumentException e) { + assertEquals("Invalid method supplied. Only POST, PUT and PATCH are allowed", e.getMessage()); + } + } + + @Test + public void testURLandHostNameMissingOrEmpty() { + try { + new LegacyCustomWebhookMessage.Builder("custom_webhook").withMessage("Hello world").withMethod(HttpGet.METHOD_NAME).build(); + fail("Building legacy custom webhook message missing or empty url and host name should fail"); + } catch (IllegalArgumentException e) { + assertEquals("Either fully qualified URL or host name should be provided", e.getMessage()); + } + + try { + new LegacyCustomWebhookMessage.Builder("custom_webhook") + .withMessage("Hello world") + .withUrl("") + .withMethod(HttpGet.METHOD_NAME) + .build(); + fail("Building legacy custom webhook message with missing or empty url and host name should fail"); + } catch (IllegalArgumentException e) { + assertEquals("Either fully qualified URL or host name should be provided", e.getMessage()); + } + + try { + new LegacyCustomWebhookMessage.Builder("custom_webhook") + .withMessage("Hello world") + .withHost("") + .withMethod(HttpGet.METHOD_NAME) + .build(); + fail("Building legacy custom webhook message with missing or empty url and host name should fail"); + } catch (IllegalArgumentException e) { + assertEquals("Either fully qualified URL or host name should be provided", e.getMessage()); + } + + try { + new LegacyCustomWebhookMessage.Builder("custom_webhook") + .withMessage("Hello world") + .withUrl("") + .withHost("") + .withMethod(HttpGet.METHOD_NAME) + .build(); + fail("Building legacy custom webhook message with missing or empty url and host name should fail"); + } catch (IllegalArgumentException e) { + assertEquals("Either fully qualified URL or host name should be provided", e.getMessage()); + } + } +} diff --git a/src/test/java/org/opensearch/commons/destination/message/LegacySlackMessageTest.java b/src/test/java/org/opensearch/commons/destination/message/LegacySlackMessageTest.java new file mode 100644 index 00000000..a520fc8e --- /dev/null +++ b/src/test/java/org/opensearch/commons/destination/message/LegacySlackMessageTest.java @@ -0,0 +1,110 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + * + * Modifications Copyright OpenSearch Contributors. See + * GitHub history for details. + */ + +/* + * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package org.opensearch.commons.destination.message; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.fail; + +import java.io.IOException; + +import org.junit.jupiter.api.Test; +import org.opensearch.common.io.stream.BytesStreamOutput; +import org.opensearch.common.io.stream.StreamInput; + +public class LegacySlackMessageTest { + + @Test + public void testBuildingLegacySlackMessage() { + LegacySlackMessage message = new LegacySlackMessage.Builder("custom_webhook") + .withMessage("Hello world") + .withUrl("https://amazon.com") + .build(); + + assertEquals("custom_webhook", message.destinationName); + assertEquals(LegacyDestinationType.LEGACY_SLACK, message.getChannelType()); + assertEquals("Hello world", message.getMessageContent()); + assertEquals("https://amazon.com", message.url); + } + + @Test + public void testRoundTrippingLegacySlackMessage() throws IOException { + LegacySlackMessage message = new LegacySlackMessage.Builder("custom_webhook") + .withMessage("Hello world") + .withUrl("https://amazon.com") + .build(); + BytesStreamOutput out = new BytesStreamOutput(); + message.writeTo(out); + + StreamInput in = StreamInput.wrap(out.bytes().toBytesRef().bytes); + LegacySlackMessage newMessage = new LegacySlackMessage(in); + + assertEquals(newMessage.destinationName, message.destinationName); + assertEquals(newMessage.getChannelType(), message.getChannelType()); + assertEquals(newMessage.getMessageContent(), message.getMessageContent()); + assertEquals(newMessage.url, message.url); + } + + @Test + public void testContentMissingMessage() { + try { + new LegacySlackMessage.Builder("custom_webhook").withUrl("https://amazon.com").build(); + fail("Building legacy slack message without message should fail"); + } catch (IllegalArgumentException e) { + assertEquals("Message content is missing", e.getMessage()); + } + } + + @Test + public void testUrlMissingMessage() { + try { + new LegacySlackMessage.Builder("custom_webhook").withMessage("Hello world").build(); + fail("Building legacy slack message without url should fail"); + } catch (IllegalArgumentException e) { + assertEquals("url is invalid or empty", e.getMessage()); + } + } + + @Test + public void testMissingDestinationName() { + try { + new LegacySlackMessage.Builder(null).withMessage("Hello world").withUrl("https://amazon.com").build(); + fail("Building legacy slack message with null destination name should fail"); + } catch (IllegalArgumentException e) { + assertEquals("Channel name must be defined", e.getMessage()); + } + } + + @Test + public void testUrlEmptyMessage() { + try { + new LegacySlackMessage.Builder("custom_webhook").withMessage("Hello world").withUrl("").build(); + fail("Building legacy slack message with empty url should fail"); + } catch (IllegalArgumentException e) { + assertEquals("Fully qualified URL is missing/invalid: ", e.getMessage()); + } + } +} diff --git a/src/test/java/org/opensearch/commons/destination/response/LegacyDestinationResponseTest.java b/src/test/java/org/opensearch/commons/destination/response/LegacyDestinationResponseTest.java new file mode 100644 index 00000000..6175827e --- /dev/null +++ b/src/test/java/org/opensearch/commons/destination/response/LegacyDestinationResponseTest.java @@ -0,0 +1,82 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + * + * Modifications Copyright OpenSearch Contributors. See + * GitHub history for details. + */ + +/* + * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package org.opensearch.commons.destination.response; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.fail; + +import java.io.IOException; + +import org.junit.jupiter.api.Test; +import org.opensearch.common.io.stream.BytesStreamOutput; +import org.opensearch.common.io.stream.StreamInput; + +public class LegacyDestinationResponseTest { + + @Test + public void testBuildingLegacyDestinationResponse() { + LegacyDestinationResponse res = new LegacyDestinationResponse.Builder() + .withStatusCode(200) + .withResponseContent("Hello world") + .build(); + + assertEquals(200, res.statusCode); + assertEquals("Hello world", res.getResponseContent()); + } + + @Test + public void testRoundTrippingLegacyDestinationResponse() throws IOException { + LegacyDestinationResponse res = new LegacyDestinationResponse.Builder() + .withStatusCode(200) + .withResponseContent("Hello world") + .build(); + BytesStreamOutput out = new BytesStreamOutput(); + res.writeTo(out); + + StreamInput in = StreamInput.wrap(out.bytes().toBytesRef().bytes); + LegacyDestinationResponse newRes = new LegacyDestinationResponse(in); + + assertEquals(res.statusCode, newRes.statusCode, "Round tripping doesn't work"); + assertEquals(res.getResponseContent(), newRes.getResponseContent(), "Round tripping doesn't work"); + } + + @Test + public void testMissingLegacyDestinationResponse() { + try { + new LegacyDestinationResponse.Builder().withStatusCode(200).build(); + fail("Creating LegacyDestinationResponse without response content should fail"); + } catch (IllegalArgumentException ignored) {} + } + + @Test + public void testMissingLegacyDestinationStatusCode() { + try { + new LegacyDestinationResponse.Builder().withResponseContent("Hello world").build(); + fail("Creating LegacyDestinationResponse without status code should fail"); + } catch (IllegalArgumentException ignored) {} + } +} diff --git a/src/test/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterfaceTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterfaceTests.kt index cf4f8420..343fecbd 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterfaceTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterfaceTests.kt @@ -25,7 +25,9 @@ import org.mockito.junit.jupiter.MockitoExtension import org.opensearch.action.ActionListener import org.opensearch.action.ActionType import org.opensearch.client.node.NodeClient +import org.opensearch.commons.destination.response.LegacyDestinationResponse import org.opensearch.commons.notifications.NotificationConstants.FEATURE_ALERTING +import org.opensearch.commons.notifications.NotificationConstants.FEATURE_INDEX_MANAGEMENT import org.opensearch.commons.notifications.NotificationConstants.FEATURE_REPORTS import org.opensearch.commons.notifications.action.CreateNotificationConfigRequest import org.opensearch.commons.notifications.action.CreateNotificationConfigResponse @@ -39,6 +41,8 @@ import org.opensearch.commons.notifications.action.GetNotificationEventRequest import org.opensearch.commons.notifications.action.GetNotificationEventResponse import org.opensearch.commons.notifications.action.GetPluginFeaturesRequest import org.opensearch.commons.notifications.action.GetPluginFeaturesResponse +import org.opensearch.commons.notifications.action.LegacyPublishNotificationRequest +import org.opensearch.commons.notifications.action.LegacyPublishNotificationResponse import org.opensearch.commons.notifications.action.SendNotificationResponse import org.opensearch.commons.notifications.action.UpdateNotificationConfigRequest import org.opensearch.commons.notifications.action.UpdateNotificationConfigResponse @@ -223,6 +227,26 @@ internal class NotificationsPluginInterfaceTests { verify(listener, times(1)).onResponse(eq(response)) } + @Test + fun publishLegacyNotification() { + val request = mock(LegacyPublishNotificationRequest::class.java) + val res = LegacyPublishNotificationResponse(LegacyDestinationResponse.Builder().withStatusCode(200).withResponseContent("Nice!").build()) + val l: ActionListener = + mock(ActionListener::class.java) as ActionListener + + doAnswer { + (it.getArgument(2) as ActionListener) + .onResponse(res) + }.whenever(client).execute(any(ActionType::class.java), any(), any()) + + doAnswer { + FEATURE_INDEX_MANAGEMENT + }.whenever(request).feature + + NotificationsPluginInterface.publishLegacyNotification(client, request, l) + verify(l, times(1)).onResponse(eq(res)) + } + private fun mockGetNotificationConfigResponse(): GetNotificationConfigResponse { val sampleSlack = Slack("https://domain.com/sample_url#1234567890") val sampleConfig = NotificationConfig( diff --git a/src/test/kotlin/org/opensearch/commons/notifications/action/LegacyPublishNotificationRequestTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/action/LegacyPublishNotificationRequestTests.kt new file mode 100644 index 00000000..349a1c14 --- /dev/null +++ b/src/test/kotlin/org/opensearch/commons/notifications/action/LegacyPublishNotificationRequestTests.kt @@ -0,0 +1,42 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + * + * Modifications Copyright OpenSearch Contributors. See + * GitHub history for details. + */ + +package org.opensearch.commons.notifications.action + +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.Assertions.assertNull +import org.junit.jupiter.api.Test +import org.opensearch.commons.destination.message.LegacyChimeMessage +import org.opensearch.commons.notifications.NotificationConstants.FEATURE_INDEX_MANAGEMENT +import org.opensearch.commons.utils.recreateObject + +internal class LegacyPublishNotificationRequestTests { + + private fun assertRequestEquals( + expected: LegacyPublishNotificationRequest, + actual: LegacyPublishNotificationRequest + ) { + assertEquals(expected.baseMessage.channelName, actual.baseMessage.channelName) + assertEquals(expected.baseMessage.channelType, actual.baseMessage.channelType) + assertEquals(expected.baseMessage.messageContent, actual.baseMessage.messageContent) + assertEquals(expected.baseMessage.url, actual.baseMessage.url) + assertEquals(expected.feature, actual.feature) + assertNull(actual.validate()) + } + + @Test + fun `publish request serialize and deserialize transport object should be equal`() { + val baseMessage = LegacyChimeMessage.Builder("chime_message").withMessage("Hello world").withUrl("https://amazon.com").build() + val request = LegacyPublishNotificationRequest(baseMessage, FEATURE_INDEX_MANAGEMENT) + val recreatedObject = recreateObject(request) { LegacyPublishNotificationRequest(it) } + assertRequestEquals(request, recreatedObject) + } +} diff --git a/src/test/kotlin/org/opensearch/commons/notifications/action/LegacyPublishNotificationResponseTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/action/LegacyPublishNotificationResponseTests.kt new file mode 100644 index 00000000..4b6f8e0b --- /dev/null +++ b/src/test/kotlin/org/opensearch/commons/notifications/action/LegacyPublishNotificationResponseTests.kt @@ -0,0 +1,29 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + * + * Modifications Copyright OpenSearch Contributors. See + * GitHub history for details. + */ + +package org.opensearch.commons.notifications.action + +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.Test +import org.opensearch.commons.destination.response.LegacyDestinationResponse +import org.opensearch.commons.utils.recreateObject + +internal class LegacyPublishNotificationResponseTests { + + @Test + fun `Create response serialize and deserialize transport object should be equal`() { + val res = LegacyDestinationResponse.Builder().withStatusCode(200).withResponseContent("Hello world").build() + val configResponse = LegacyPublishNotificationResponse(res) + val recreatedObject = recreateObject(configResponse) { LegacyPublishNotificationResponse(it) } + assertEquals(configResponse.destinationResponse.statusCode, recreatedObject.destinationResponse.statusCode) + assertEquals(configResponse.destinationResponse.responseContent, recreatedObject.destinationResponse.responseContent) + } +} From 13591ced48f6b2625b049263a7658322ff2514db Mon Sep 17 00:00:00 2001 From: Vacha Date: Mon, 16 Aug 2021 07:36:21 -0700 Subject: [PATCH 080/140] Using 1.1 snapshot version for OpenSearch (#57) Signed-off-by: Vacha Signed-off-by: Zelin Hao --- .github/workflows/ci.yml | 6 +++--- build.gradle | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4f0adf94..1872eb2a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -34,16 +34,16 @@ jobs: ref: 'main' - name: Build OpenSearch working-directory: ./OpenSearch - run: ./gradlew publishToMavenLocal -Dbuild.snapshot=false + run: ./gradlew publishToMavenLocal # common-utils - name: Build and Test run: | - ./gradlew build -Dopensearch.version=1.1.0 + ./gradlew build -Dopensearch.version=1.1.0-SNAPSHOT - name: Publish to Maven Local run: | - ./gradlew publishToMavenLocal -Dopensearch.version=1.1.0 + ./gradlew publishToMavenLocal -Dopensearch.version=1.1.0-SNAPSHOT - name: Upload Coverage Report uses: codecov/codecov-action@v1 diff --git a/build.gradle b/build.gradle index 0f2b241a..4917e428 100644 --- a/build.gradle +++ b/build.gradle @@ -12,7 +12,7 @@ buildscript { ext { opensearch_group = "org.opensearch" - opensearch_version = System.getProperty("opensearch.version", "1.1.0") + opensearch_version = System.getProperty("opensearch.version", "1.1.0-SNAPSHOT") kotlin_version = System.getProperty("kotlin.version", "1.4.32") } From e05ba9a957d2b80e1d42ab5f47d0eafdf4bd58fb Mon Sep 17 00:00:00 2001 From: Miki Date: Mon, 16 Aug 2021 07:42:06 -0700 Subject: [PATCH 081/140] Add themed logo to README (#41) Signed-off-by: Miki Signed-off-by: Zelin Hao --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 237509c1..b2778b5d 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ - + - [OpenSearch Common Utils](#opensearch-common-utils) - [Contributing](#contributing) From 8e64257be1d26787fc3585a1e0e463f798a21c15 Mon Sep 17 00:00:00 2001 From: "Daniel Doubrovkine (dB.)" Date: Mon, 16 Aug 2021 11:25:48 -0400 Subject: [PATCH 082/140] Build snapshot build by default with the same version as OpenSearch. (#58) Signed-off-by: dblock Signed-off-by: Zelin Hao --- .github/workflows/ci.yml | 2 +- build.gradle | 14 +++++++++++--- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1872eb2a..53c3d9b6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -31,7 +31,7 @@ jobs: with: repository: 'opensearch-project/OpenSearch' path: OpenSearch - ref: 'main' + ref: '1.x' - name: Build OpenSearch working-directory: ./OpenSearch run: ./gradlew publishToMavenLocal diff --git a/build.gradle b/build.gradle index 4917e428..d443ddf4 100644 --- a/build.gradle +++ b/build.gradle @@ -44,7 +44,17 @@ repositories { jcenter() } -group 'org.opensearch.commons' +ext { + isSnapshot = "true" == System.getProperty("build.snapshot", "true") +} + +allprojects { + group 'org.opensearch.commons' + version = opensearch_version - '-SNAPSHOT' + '.0' + if (isSnapshot) { + version += "-SNAPSHOT" + } +} sourceCompatibility = 1.8 @@ -146,8 +156,6 @@ task javadocJar(type: Jar) { from javadoc.destinationDir } -version '1.1.0.0' - publishing { publications { shadow(MavenPublication) { From 6985356b57785af53cbfc754b5db0dec9a80db82 Mon Sep 17 00:00:00 2001 From: Anantha Krishna Bhatta <31894175+akbhatta@users.noreply.github.com> Date: Mon, 16 Aug 2021 15:49:54 -0700 Subject: [PATCH 083/140] BugFix: Allow null values for role_arn in json parsing (#60) Signed-off-by: @akbhatta Signed-off-by: Zelin Hao --- .../commons/notifications/model/SesAccount.kt | 5 +-- .../notifications/model/SesAccountTests.kt | 35 +++++++++++++++++++ 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/SesAccount.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/SesAccount.kt index d529b407..aa9aca26 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/SesAccount.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/SesAccount.kt @@ -22,6 +22,7 @@ import org.opensearch.common.xcontent.XContentParserUtils import org.opensearch.commons.notifications.NotificationConstants.FROM_ADDRESS_TAG import org.opensearch.commons.notifications.NotificationConstants.REGION_TAG import org.opensearch.commons.notifications.NotificationConstants.ROLE_ARN_TAG +import org.opensearch.commons.utils.fieldIfNotNull import org.opensearch.commons.utils.logger import org.opensearch.commons.utils.validateEmail import org.opensearch.commons.utils.validateIamRoleArn @@ -74,7 +75,7 @@ data class SesAccount( parser.nextToken() when (fieldName) { REGION_TAG -> awsRegion = parser.text() - ROLE_ARN_TAG -> roleArn = parser.text() + ROLE_ARN_TAG -> roleArn = parser.textOrNull() FROM_ADDRESS_TAG -> fromAddress = parser.text() else -> { parser.skipChildren() @@ -98,7 +99,7 @@ data class SesAccount( override fun toXContent(builder: XContentBuilder?, params: ToXContent.Params?): XContentBuilder { return builder!!.startObject() .field(REGION_TAG, awsRegion) - .field(ROLE_ARN_TAG, roleArn) + .fieldIfNotNull(ROLE_ARN_TAG, roleArn) .field(FROM_ADDRESS_TAG, fromAddress) .endObject() } diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/SesAccountTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/SesAccountTests.kt index c99506fd..e999e534 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/SesAccountTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/SesAccountTests.kt @@ -82,6 +82,14 @@ internal class SesAccountTests { assertEquals(sesAccount, recreatedObject) } + @Test + fun `SES serialize and deserialize using json object should be equal with null roleArn`() { + val sesAccount = SesAccount("us-east-1", null, "from@domain.com") + val jsonString = getJsonString(sesAccount) + val recreatedObject = createObjectFromJsonString(jsonString) { SesAccount.parse(it) } + assertEquals(sesAccount, recreatedObject) + } + @Test fun `SES should deserialize json object using parser`() { val sesAccount = SesAccount("us-east-1", "arn:aws:iam::012345678912:role/iam-test", "from@domain.com") @@ -96,6 +104,33 @@ internal class SesAccountTests { assertEquals(sesAccount, recreatedObject) } + @Test + fun `SES should deserialize json object will null role_arn using parser`() { + val sesAccount = SesAccount("us-east-1", null, "from@domain.com") + val jsonString = """ + { + "region":"${sesAccount.awsRegion}", + "role_arn":null, + "from_address":"${sesAccount.fromAddress}" + } + """.trimIndent() + val recreatedObject = createObjectFromJsonString(jsonString) { SesAccount.parse(it) } + assertEquals(sesAccount, recreatedObject) + } + + @Test + fun `SES should deserialize json object will missing role_arn using parser`() { + val sesAccount = SesAccount("us-east-1", null, "from@domain.com") + val jsonString = """ + { + "region":"${sesAccount.awsRegion}", + "from_address":"${sesAccount.fromAddress}" + } + """.trimIndent() + val recreatedObject = createObjectFromJsonString(jsonString) { SesAccount.parse(it) } + assertEquals(sesAccount, recreatedObject) + } + @Test fun `SES should throw exception when invalid json object is passed`() { val jsonString = "sample message" From 4082e33e6a9b43d20d9899c45759ffb1551c518e Mon Sep 17 00:00:00 2001 From: Anantha Krishna Bhatta <31894175+akbhatta@users.noreply.github.com> Date: Fri, 17 Sep 2021 11:34:55 -0700 Subject: [PATCH 084/140] Removed tenant information from the models (#73) * Removed tenant information from the models [Tests] Updated unit tests Signed-off-by: @akbhatta * Updated OpenSearch branch to 1.1 Signed-off-by: @akbhatta Signed-off-by: Zelin Hao --- .github/workflows/ci.yml | 2 +- .../notifications/NotificationConstants.kt | 1 - .../action/GetFeatureChannelListRequest.kt | 3 - .../model/NotificationConfigInfo.kt | 9 --- .../model/NotificationEventInfo.kt | 9 --- .../NotificationsPluginInterfaceTests.kt | 2 - .../GetNotificationConfigResponseTests.kt | 13 +--- .../GetNotificationEventResponseTests.kt | 15 +---- .../model/NotificationConfigInfoTests.kt | 50 +------------- .../NotificationConfigSearchResultsTests.kt | 15 +---- .../model/NotificationEventInfoTests.kt | 67 +------------------ .../NotificationEventSearchResultTests.kt | 19 +----- 12 files changed, 7 insertions(+), 198 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 53c3d9b6..8f83153e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -31,7 +31,7 @@ jobs: with: repository: 'opensearch-project/OpenSearch' path: OpenSearch - ref: '1.x' + ref: '1.1' - name: Build OpenSearch working-directory: ./OpenSearch run: ./gradlew publishToMavenLocal diff --git a/src/main/kotlin/org/opensearch/commons/notifications/NotificationConstants.kt b/src/main/kotlin/org/opensearch/commons/notifications/NotificationConstants.kt index 55dc9a44..dc16a39f 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/NotificationConstants.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/NotificationConstants.kt @@ -51,7 +51,6 @@ object NotificationConstants { const val FROM_ADDRESS_TAG = "from_address" const val UPDATED_TIME_TAG = "last_updated_time_ms" const val CREATED_TIME_TAG = "created_time_ms" - const val TENANT_TAG = "tenant" const val CONFIG_LIST_TAG = "config_list" const val EVENT_LIST_TAG = "event_list" const val FEATURE_CONFIG_LIST_TAG = "feature_channel_list" diff --git a/src/main/kotlin/org/opensearch/commons/notifications/action/GetFeatureChannelListRequest.kt b/src/main/kotlin/org/opensearch/commons/notifications/action/GetFeatureChannelListRequest.kt index 309a31bc..ba6e3b19 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/action/GetFeatureChannelListRequest.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/action/GetFeatureChannelListRequest.kt @@ -42,9 +42,6 @@ import java.io.IOException /** * This request is plugin-only call. i.e. REST interface is not exposed. - * Also the library will remove the user context while making this call - * so that user making this call need not have to set permission to this API. - * Hence the request also contains tenant info for space isolation. */ class GetFeatureChannelListRequest : ActionRequest, ToXContentObject { val feature: String diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationConfigInfo.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationConfigInfo.kt index 7a949bbb..3c17a28c 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationConfigInfo.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationConfigInfo.kt @@ -37,7 +37,6 @@ import org.opensearch.common.xcontent.XContentParserUtils import org.opensearch.commons.notifications.NotificationConstants.CONFIG_ID_TAG import org.opensearch.commons.notifications.NotificationConstants.CONFIG_TAG import org.opensearch.commons.notifications.NotificationConstants.CREATED_TIME_TAG -import org.opensearch.commons.notifications.NotificationConstants.TENANT_TAG import org.opensearch.commons.notifications.NotificationConstants.UPDATED_TIME_TAG import org.opensearch.commons.utils.logger import java.io.IOException @@ -50,7 +49,6 @@ data class NotificationConfigInfo( val configId: String, val lastUpdatedTime: Instant, val createdTime: Instant, - val tenant: String, val notificationConfig: NotificationConfig ) : BaseModel { @@ -76,7 +74,6 @@ data class NotificationConfigInfo( var configId: String? = null var lastUpdatedTime: Instant? = null var createdTime: Instant? = null - var tenant: String? = null var notificationConfig: NotificationConfig? = null XContentParserUtils.ensureExpectedToken( @@ -91,7 +88,6 @@ data class NotificationConfigInfo( CONFIG_ID_TAG -> configId = parser.text() UPDATED_TIME_TAG -> lastUpdatedTime = Instant.ofEpochMilli(parser.longValue()) CREATED_TIME_TAG -> createdTime = Instant.ofEpochMilli(parser.longValue()) - TENANT_TAG -> tenant = parser.text() CONFIG_TAG -> notificationConfig = NotificationConfig.parse(parser) else -> { parser.skipChildren() @@ -102,13 +98,11 @@ data class NotificationConfigInfo( configId ?: throw IllegalArgumentException("$CONFIG_ID_TAG field absent") lastUpdatedTime ?: throw IllegalArgumentException("$UPDATED_TIME_TAG field absent") createdTime ?: throw IllegalArgumentException("$CREATED_TIME_TAG field absent") - tenant = tenant ?: "" notificationConfig ?: throw IllegalArgumentException("$CONFIG_TAG field absent") return NotificationConfigInfo( configId, lastUpdatedTime, createdTime, - tenant, notificationConfig ) } @@ -122,7 +116,6 @@ data class NotificationConfigInfo( configId = input.readString(), lastUpdatedTime = input.readInstant(), createdTime = input.readInstant(), - tenant = input.readString(), notificationConfig = NotificationConfig.reader.read(input) ) @@ -133,7 +126,6 @@ data class NotificationConfigInfo( output.writeString(configId) output.writeInstant(lastUpdatedTime) output.writeInstant(createdTime) - output.writeString(tenant) notificationConfig.writeTo(output) } @@ -146,7 +138,6 @@ data class NotificationConfigInfo( .field(CONFIG_ID_TAG, configId) .field(UPDATED_TIME_TAG, lastUpdatedTime.toEpochMilli()) .field(CREATED_TIME_TAG, createdTime.toEpochMilli()) - .field(TENANT_TAG, tenant) .field(CONFIG_TAG, notificationConfig) .endObject() } diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationEventInfo.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationEventInfo.kt index 27f9d0ad..3e4ff552 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationEventInfo.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationEventInfo.kt @@ -37,7 +37,6 @@ import org.opensearch.common.xcontent.XContentParserUtils import org.opensearch.commons.notifications.NotificationConstants.CREATED_TIME_TAG import org.opensearch.commons.notifications.NotificationConstants.EVENT_ID_TAG import org.opensearch.commons.notifications.NotificationConstants.EVENT_TAG -import org.opensearch.commons.notifications.NotificationConstants.TENANT_TAG import org.opensearch.commons.notifications.NotificationConstants.UPDATED_TIME_TAG import org.opensearch.commons.utils.logger import java.io.IOException @@ -50,7 +49,6 @@ data class NotificationEventInfo( val eventId: String, val lastUpdatedTime: Instant, val createdTime: Instant, - val tenant: String, val notificationEvent: NotificationEvent ) : BaseModel { @@ -76,7 +74,6 @@ data class NotificationEventInfo( var eventId: String? = null var lastUpdatedTime: Instant? = null var createdTime: Instant? = null - var tenant: String? = null var notificationEvent: NotificationEvent? = null XContentParserUtils.ensureExpectedToken( @@ -91,7 +88,6 @@ data class NotificationEventInfo( EVENT_ID_TAG -> eventId = parser.text() UPDATED_TIME_TAG -> lastUpdatedTime = Instant.ofEpochMilli(parser.longValue()) CREATED_TIME_TAG -> createdTime = Instant.ofEpochMilli(parser.longValue()) - TENANT_TAG -> tenant = parser.text() EVENT_TAG -> notificationEvent = NotificationEvent.parse(parser) else -> { parser.skipChildren() @@ -102,13 +98,11 @@ data class NotificationEventInfo( eventId ?: throw IllegalArgumentException("$EVENT_ID_TAG field absent") lastUpdatedTime ?: throw IllegalArgumentException("$UPDATED_TIME_TAG field absent") createdTime ?: throw IllegalArgumentException("$CREATED_TIME_TAG field absent") - tenant = tenant ?: "" notificationEvent ?: throw IllegalArgumentException("$EVENT_TAG field absent") return NotificationEventInfo( eventId, lastUpdatedTime, createdTime, - tenant, notificationEvent ) } @@ -123,7 +117,6 @@ data class NotificationEventInfo( .field(EVENT_ID_TAG, eventId) .field(UPDATED_TIME_TAG, lastUpdatedTime.toEpochMilli()) .field(CREATED_TIME_TAG, createdTime.toEpochMilli()) - .field(TENANT_TAG, tenant) .field(EVENT_TAG, notificationEvent) .endObject() } @@ -136,7 +129,6 @@ data class NotificationEventInfo( eventId = input.readString(), lastUpdatedTime = input.readInstant(), createdTime = input.readInstant(), - tenant = input.readString(), notificationEvent = NotificationEvent.reader.read(input) ) @@ -147,7 +139,6 @@ data class NotificationEventInfo( output.writeString(eventId) output.writeInstant(lastUpdatedTime) output.writeInstant(createdTime) - output.writeString(tenant) notificationEvent.writeTo(output) } } diff --git a/src/test/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterfaceTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterfaceTests.kt index 343fecbd..77d12ff2 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterfaceTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterfaceTests.kt @@ -260,7 +260,6 @@ internal class NotificationsPluginInterfaceTests { "config_id", Instant.now(), Instant.now(), - "tenant", sampleConfig ) return GetNotificationConfigResponse(NotificationConfigSearchResult(configInfo)) @@ -284,7 +283,6 @@ internal class NotificationsPluginInterfaceTests { "event_id", Instant.now(), Instant.now(), - "tenant", sampleEvent ) return GetNotificationEventResponse(NotificationEventSearchResult(eventInfo)) diff --git a/src/test/kotlin/org/opensearch/commons/notifications/action/GetNotificationConfigResponseTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/action/GetNotificationConfigResponseTests.kt index 2ec08913..8cc66d80 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/action/GetNotificationConfigResponseTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/action/GetNotificationConfigResponseTests.kt @@ -70,7 +70,6 @@ internal class GetNotificationConfigResponseTests { "config_id", Instant.now(), Instant.now(), - "tenant", sampleConfig ) val searchResult = NotificationConfigSearchResult(configInfo) @@ -92,7 +91,6 @@ internal class GetNotificationConfigResponseTests { "config_id1", Instant.now(), Instant.now(), - "tenant", sampleConfig1 ) val sampleConfig2 = NotificationConfig( @@ -106,7 +104,6 @@ internal class GetNotificationConfigResponseTests { "config_id2", Instant.now(), Instant.now(), - "tenant", sampleConfig2 ) val searchResult = NotificationConfigSearchResult( @@ -136,7 +133,6 @@ internal class GetNotificationConfigResponseTests { "config_id", lastUpdatedTimeMs, createdTimeMs, - "tenant", sampleConfig ) val searchResult = NotificationConfigSearchResult(configInfo) @@ -161,7 +157,6 @@ internal class GetNotificationConfigResponseTests { "config_id1", lastUpdatedTimeMs, createdTimeMs, - "tenant", sampleConfig1 ) val sampleConfig2 = NotificationConfig( @@ -175,7 +170,6 @@ internal class GetNotificationConfigResponseTests { "config_id2", lastUpdatedTimeMs, createdTimeMs, - "tenant", sampleConfig2 ) val searchResult = NotificationConfigSearchResult( @@ -207,7 +201,6 @@ internal class GetNotificationConfigResponseTests { "config-Id", lastUpdatedTimeMs, createdTimeMs, - "selectedTenant", sampleConfig ) val searchResult = NotificationConfigSearchResult(configInfo) @@ -221,7 +214,6 @@ internal class GetNotificationConfigResponseTests { "config_id":"config-Id", "last_updated_time_ms":"${lastUpdatedTimeMs.toEpochMilli()}", "created_time_ms":"${createdTimeMs.toEpochMilli()}", - "tenant":"selectedTenant", "config":{ "name":"name", "description":"description", @@ -258,7 +250,6 @@ internal class GetNotificationConfigResponseTests { "config-Id", lastUpdatedTimeMs, createdTimeMs, - "selectedTenant", sampleConfig ) val searchResult = NotificationConfigSearchResult(configInfo) @@ -269,7 +260,6 @@ internal class GetNotificationConfigResponseTests { "config_id":"config-Id", "last_updated_time_ms":"${lastUpdatedTimeMs.toEpochMilli()}", "created_time_ms":"${createdTimeMs.toEpochMilli()}", - "tenant":"selectedTenant", "config":{ "name":"name", "description":"description", @@ -299,8 +289,7 @@ internal class GetNotificationConfigResponseTests { { "config_id":"config-Id", "last_updated_time_ms":"${lastUpdatedTimeMs.toEpochMilli()}", - "created_time_ms":"${createdTimeMs.toEpochMilli()}", - "tenant":"selectedTenant" + "created_time_ms":"${createdTimeMs.toEpochMilli()}" } ] } diff --git a/src/test/kotlin/org/opensearch/commons/notifications/action/GetNotificationEventResponseTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/action/GetNotificationEventResponseTests.kt index 1895d1d3..be6af960 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/action/GetNotificationEventResponseTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/action/GetNotificationEventResponseTests.kt @@ -77,7 +77,6 @@ internal class GetNotificationEventResponseTests { "event_id", Instant.now(), Instant.now(), - "tenant", sampleEvent ) val searchResult = NotificationEventSearchResult(eventInfo) @@ -116,28 +115,24 @@ internal class GetNotificationEventResponseTests { "event_id1", Instant.now(), Instant.now(), - "tenant", NotificationEvent(eventSource1, listOf(status1)) ) val eventInfo2 = NotificationEventInfo( "event_id2", Instant.now(), Instant.now(), - "tenant", NotificationEvent(eventSource2, listOf(status2)) ) val eventInfo3 = NotificationEventInfo( "event_id3", Instant.now(), Instant.now(), - "tenant", NotificationEvent(eventSource1, listOf(status1, status2)) ) val eventInfo4 = NotificationEventInfo( "event_id4", Instant.now(), Instant.now(), - "tenant", NotificationEvent(eventSource2, listOf(status1, status2)) ) val searchResult = NotificationEventSearchResult( @@ -172,7 +167,6 @@ internal class GetNotificationEventResponseTests { "event_id", lastUpdatedTimeMs, createdTimeMs, - "tenant", sampleEvent ) val searchResult = NotificationEventSearchResult(eventInfo) @@ -214,14 +208,12 @@ internal class GetNotificationEventResponseTests { "event_id1", lastUpdatedTimeMs, createdTimeMs, - "tenant", NotificationEvent(eventSource1, listOf(status1)) ) val eventInfo2 = NotificationEventInfo( "event_id2", lastUpdatedTimeMs, createdTimeMs, - "tenant", NotificationEvent(eventSource2, listOf(status2)) ) val searchResult = NotificationEventSearchResult( @@ -257,7 +249,6 @@ internal class GetNotificationEventResponseTests { "event_id", lastUpdatedTimeMs, createdTimeMs, - "selectedTenant", sampleEvent ) val searchResult = NotificationEventSearchResult(eventInfo) @@ -271,7 +262,6 @@ internal class GetNotificationEventResponseTests { "event_id":"event_id", "last_updated_time_ms":"${lastUpdatedTimeMs.toEpochMilli()}", "created_time_ms":"${createdTimeMs.toEpochMilli()}", - "tenant":"selectedTenant", "event":{ "event_source":{ "title":"title", @@ -325,7 +315,6 @@ internal class GetNotificationEventResponseTests { "event_id", lastUpdatedTimeMs, createdTimeMs, - "selectedTenant", sampleEvent ) val searchResult = NotificationEventSearchResult(eventInfo) @@ -336,7 +325,6 @@ internal class GetNotificationEventResponseTests { "event_id":"event_id", "last_updated_time_ms":"${lastUpdatedTimeMs.toEpochMilli()}", "created_time_ms":"${createdTimeMs.toEpochMilli()}", - "tenant":"selectedTenant", "event":{ "event_source":{ "title":"title", @@ -379,8 +367,7 @@ internal class GetNotificationEventResponseTests { { "event_id":"event_id", "last_updated_time_ms":"${lastUpdatedTimeMs.toEpochMilli()}", - "created_time_ms":"${createdTimeMs.toEpochMilli()}", - "tenant":"selectedTenant" + "created_time_ms":"${createdTimeMs.toEpochMilli()}" } ] } diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationConfigInfoTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationConfigInfoTests.kt index 409decd7..6f532fb0 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationConfigInfoTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationConfigInfoTests.kt @@ -52,7 +52,6 @@ internal class NotificationConfigInfoTests { "config_id", Instant.now(), Instant.now(), - "tenant", sampleConfig ) val recreatedObject = recreateObject(configInfo) { NotificationConfigInfo(it) } @@ -75,7 +74,6 @@ internal class NotificationConfigInfoTests { "config_id", lastUpdatedTimeMs, createdTimeMs, - "tenant", sampleConfig ) val jsonString = getJsonString(configInfo) @@ -83,45 +81,6 @@ internal class NotificationConfigInfoTests { assertEquals(configInfo, recreatedObject) } - @Test - fun `Config info should take default tenant when field is absent in json object`() { - val lastUpdatedTimeMs = Instant.ofEpochMilli(Instant.now().toEpochMilli()) - val createdTimeMs = lastUpdatedTimeMs.minusSeconds(1000) - val sampleSlack = Slack("https://domain.com/sample_slack_url#1234567890") - val sampleConfig = NotificationConfig( - "name", - "description", - ConfigType.SLACK, - setOf(FEATURE_INDEX_MANAGEMENT), - isEnabled = true, - configData = sampleSlack - ) - val configInfo = NotificationConfigInfo( - "config-Id", - lastUpdatedTimeMs, - createdTimeMs, - "", // Default tenant - sampleConfig - ) - val jsonString = """ - { - "config_id":"config-Id", - "last_updated_time_ms":"${lastUpdatedTimeMs.toEpochMilli()}", - "created_time_ms":"${createdTimeMs.toEpochMilli()}", - "config":{ - "name":"name", - "description":"description", - "config_type":"slack", - "feature_list":["index_management"], - "is_enabled":true, - "slack":{"url":"https://domain.com/sample_slack_url#1234567890"} - } - } - """.trimIndent() - val recreatedObject = createObjectFromJsonString(jsonString) { NotificationConfigInfo.parse(it) } - assertEquals(configInfo, recreatedObject) - } - @Test fun `Config info should safely ignore extra field in json object`() { val lastUpdatedTimeMs = Instant.ofEpochMilli(Instant.now().toEpochMilli()) @@ -139,7 +98,6 @@ internal class NotificationConfigInfoTests { "config-Id", lastUpdatedTimeMs, createdTimeMs, - "selectedTenant", sampleConfig ) val jsonString = """ @@ -147,7 +105,6 @@ internal class NotificationConfigInfoTests { "config_id":"config-Id", "last_updated_time_ms":"${lastUpdatedTimeMs.toEpochMilli()}", "created_time_ms":"${createdTimeMs.toEpochMilli()}", - "tenant":"selectedTenant", "config":{ "name":"name", "description":"description", @@ -180,7 +137,6 @@ internal class NotificationConfigInfoTests { "", Instant.now(), Instant.now(), - "tenant", sampleConfig ) } @@ -194,7 +150,6 @@ internal class NotificationConfigInfoTests { { "last_updated_time_ms":"${lastUpdatedTimeMs.toEpochMilli()}", "created_time_ms":"${createdTimeMs.toEpochMilli()}", - "tenant":"selectedTenant", "config":{ "name":"name", "description":"description", @@ -218,7 +173,6 @@ internal class NotificationConfigInfoTests { { "config_id":"config-Id", "created_time_ms":"${createdTimeMs.toEpochMilli()}", - "tenant":"selectedTenant", "config":{ "name":"name", "description":"description", @@ -241,7 +195,6 @@ internal class NotificationConfigInfoTests { { "config_id":"config-Id", "last_updated_time_ms":"${lastUpdatedTimeMs.toEpochMilli()}", - "tenant":"selectedTenant", "config":{ "name":"name", "description":"description", @@ -265,8 +218,7 @@ internal class NotificationConfigInfoTests { { "config_id":"config-Id", "last_updated_time_ms":"${lastUpdatedTimeMs.toEpochMilli()}", - "created_time_ms":"${createdTimeMs.toEpochMilli()}", - "tenant":"selectedTenant" + "created_time_ms":"${createdTimeMs.toEpochMilli()}" } """.trimIndent() Assertions.assertThrows(IllegalArgumentException::class.java) { diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationConfigSearchResultsTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationConfigSearchResultsTests.kt index 6a10935f..dab33090 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationConfigSearchResultsTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationConfigSearchResultsTests.kt @@ -64,7 +64,6 @@ internal class NotificationConfigSearchResultsTests { "config_id", Instant.now(), Instant.now(), - "tenant", sampleConfig ) val searchResult = NotificationConfigSearchResult(configInfo) @@ -85,7 +84,6 @@ internal class NotificationConfigSearchResultsTests { "config_id1", Instant.now(), Instant.now(), - "tenant", sampleConfig1 ) val sampleConfig2 = NotificationConfig( @@ -99,7 +97,6 @@ internal class NotificationConfigSearchResultsTests { "config_id2", Instant.now(), Instant.now(), - "tenant", sampleConfig2 ) val searchResult = NotificationConfigSearchResult(listOf(configInfo1, configInfo2)) @@ -126,7 +123,6 @@ internal class NotificationConfigSearchResultsTests { "config_id1", Instant.now(), Instant.now(), - "tenant", sampleConfig1 ) val sampleConfig2 = NotificationConfig( @@ -140,7 +136,6 @@ internal class NotificationConfigSearchResultsTests { "config_id2", Instant.now(), Instant.now(), - "tenant", sampleConfig2 ) val searchResult = NotificationConfigSearchResult( @@ -169,7 +164,6 @@ internal class NotificationConfigSearchResultsTests { "config_id", lastUpdatedTimeMs, createdTimeMs, - "tenant", sampleConfig ) val searchResult = NotificationConfigSearchResult(configInfo) @@ -193,7 +187,6 @@ internal class NotificationConfigSearchResultsTests { "config_id1", lastUpdatedTimeMs, createdTimeMs, - "tenant", sampleConfig1 ) val sampleConfig2 = NotificationConfig( @@ -207,7 +200,6 @@ internal class NotificationConfigSearchResultsTests { "config_id2", lastUpdatedTimeMs, createdTimeMs, - "tenant", sampleConfig2 ) val searchResult = NotificationConfigSearchResult( @@ -238,7 +230,6 @@ internal class NotificationConfigSearchResultsTests { "config-Id", lastUpdatedTimeMs, createdTimeMs, - "selectedTenant", sampleConfig ) val searchResult = NotificationConfigSearchResult(configInfo) @@ -252,7 +243,6 @@ internal class NotificationConfigSearchResultsTests { "config_id":"config-Id", "last_updated_time_ms":"${lastUpdatedTimeMs.toEpochMilli()}", "created_time_ms":"${createdTimeMs.toEpochMilli()}", - "tenant":"selectedTenant", "config":{ "name":"name", "description":"description", @@ -289,7 +279,6 @@ internal class NotificationConfigSearchResultsTests { "config-Id", lastUpdatedTimeMs, createdTimeMs, - "selectedTenant", sampleConfig ) val searchResult = NotificationConfigSearchResult(configInfo) @@ -300,7 +289,6 @@ internal class NotificationConfigSearchResultsTests { "config_id":"config-Id", "last_updated_time_ms":"${lastUpdatedTimeMs.toEpochMilli()}", "created_time_ms":"${createdTimeMs.toEpochMilli()}", - "tenant":"selectedTenant", "config":{ "name":"name", "description":"description", @@ -330,8 +318,7 @@ internal class NotificationConfigSearchResultsTests { { "config_id":"config-Id", "last_updated_time_ms":"${lastUpdatedTimeMs.toEpochMilli()}", - "created_time_ms":"${createdTimeMs.toEpochMilli()}", - "tenant":"selectedTenant" + "created_time_ms":"${createdTimeMs.toEpochMilli()}" } ] } diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationEventInfoTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationEventInfoTests.kt index 9f45fbb0..3937c252 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationEventInfoTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationEventInfoTests.kt @@ -56,7 +56,6 @@ internal class NotificationEventInfoTests { "event_id", Instant.now(), Instant.now(), - "tenant", sampleEvent ) val recreatedObject = recreateObject(eventInfo) { NotificationEventInfo(it) } @@ -84,7 +83,6 @@ internal class NotificationEventInfoTests { "event_id", lastUpdatedTimeMs, createdTimeMs, - "tenant", sampleEvent ) val jsonString = getJsonString(eventInfo) @@ -92,63 +90,6 @@ internal class NotificationEventInfoTests { assertEquals(eventInfo, recreatedObject) } - @Test - fun `Event info should take default tenant when field is absent in json object`() { - val lastUpdatedTimeMs = Instant.ofEpochMilli(Instant.now().toEpochMilli()) - val createdTimeMs = lastUpdatedTimeMs.minusSeconds(1000) - val sampleEventSource = EventSource( - "title", - "reference_id", - FEATURE_ALERTING, - severity = SeverityType.INFO - ) - val sampleStatus = EventStatus( - "config_id", - "name", - ConfigType.SLACK, - deliveryStatus = DeliveryStatus("200", "success") - ) - val sampleEvent = NotificationEvent(sampleEventSource, listOf(sampleStatus)) - val eventInfo = NotificationEventInfo( - "event_id", - lastUpdatedTimeMs, - createdTimeMs, - "tenant", - sampleEvent - ) - val jsonString = """ - { - "event_id":"event_id", - "last_updated_time_ms":"${lastUpdatedTimeMs.toEpochMilli()}", - "created_time_ms":"${createdTimeMs.toEpochMilli()}", - "tenant":"tenant", - "event":{ - "event_source":{ - "title":"title", - "reference_id":"reference_id", - "feature":"alerting", - "severity":"info", - "tags":[] - }, - "status_list":[ - { - "config_id":"config_id", - "config_type":"slack", - "config_name":"name", - "delivery_status": - { - "status_code":"200", - "status_text":"success" - } - } - ] - } - } - """.trimIndent() - val recreatedObject = createObjectFromJsonString(jsonString) { NotificationEventInfo.parse(it) } - assertEquals(eventInfo, recreatedObject) - } - @Test fun `Event info should safely ignore extra field in json object`() { val lastUpdatedTimeMs = Instant.ofEpochMilli(Instant.now().toEpochMilli()) @@ -170,7 +111,6 @@ internal class NotificationEventInfoTests { "event_id", lastUpdatedTimeMs, createdTimeMs, - "tenant", sampleEvent ) val jsonString = """ @@ -178,7 +118,6 @@ internal class NotificationEventInfoTests { "event_id":"event_id", "last_updated_time_ms":"${lastUpdatedTimeMs.toEpochMilli()}", "created_time_ms":"${createdTimeMs.toEpochMilli()}", - "tenant":"tenant", "event":{ "event_source":{ "title":"title", @@ -231,7 +170,6 @@ internal class NotificationEventInfoTests { "", lastUpdatedTimeMs, createdTimeMs, - "tenant", sampleEvent ) } @@ -281,7 +219,6 @@ internal class NotificationEventInfoTests { { "event_id":"event_id", "created_time_ms":"${createdTimeMs.toEpochMilli()}", - "tenant":"selectedTenant", "event":{ "event_source":{ "title":"title", @@ -317,7 +254,6 @@ internal class NotificationEventInfoTests { { "event_id":"event_id", "last_updated_time_ms":"${lastUpdatedTimeMs.toEpochMilli()}", - "tenant":"selectedTenant", "event":{ "event_source":{ "title":"title", @@ -354,8 +290,7 @@ internal class NotificationEventInfoTests { { "event_id":"event_id", "last_updated_time_ms":"${lastUpdatedTimeMs.toEpochMilli()}", - "created_time_ms":"${createdTimeMs.toEpochMilli()}", - "tenant":"selectedTenant" + "created_time_ms":"${createdTimeMs.toEpochMilli()}" } """.trimIndent() Assertions.assertThrows(IllegalArgumentException::class.java) { diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationEventSearchResultTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationEventSearchResultTests.kt index 078d4910..c0e9786d 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationEventSearchResultTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationEventSearchResultTests.kt @@ -69,7 +69,6 @@ internal class NotificationEventSearchResultTests { "event_id", Instant.now(), Instant.now(), - "tenant", sampleEvent ) val searchResult = NotificationEventSearchResult(eventInfo) @@ -107,28 +106,24 @@ internal class NotificationEventSearchResultTests { "event_id1", Instant.now(), Instant.now(), - "tenant", NotificationEvent(eventSource1, listOf(status1)) ) val eventInfo2 = NotificationEventInfo( "event_id2", Instant.now(), Instant.now(), - "tenant", NotificationEvent(eventSource2, listOf(status2)) ) val eventInfo3 = NotificationEventInfo( "event_id3", Instant.now(), Instant.now(), - "tenant", NotificationEvent(eventSource1, listOf(status1, status2)) ) val eventInfo4 = NotificationEventInfo( "event_id4", Instant.now(), Instant.now(), - "tenant", NotificationEvent(eventSource2, listOf(status1, status2)) ) val searchResult = NotificationEventSearchResult( @@ -174,28 +169,24 @@ internal class NotificationEventSearchResultTests { "event_id1", Instant.now(), Instant.now(), - "tenant", NotificationEvent(eventSource1, listOf(status1)) ) val eventInfo2 = NotificationEventInfo( "event_id2", Instant.now(), Instant.now(), - "tenant", NotificationEvent(eventSource2, listOf(status2)) ) val eventInfo3 = NotificationEventInfo( "event_id3", Instant.now(), Instant.now(), - "tenant", NotificationEvent(eventSource1, listOf(status1, status2)) ) val eventInfo4 = NotificationEventInfo( "event_id4", Instant.now(), Instant.now(), - "tenant", NotificationEvent(eventSource2, listOf(status1, status2)) ) val searchResult = NotificationEventSearchResult( @@ -229,7 +220,6 @@ internal class NotificationEventSearchResultTests { "event_id", lastUpdatedTimeMs, createdTimeMs, - "tenant", sampleEvent ) val searchResult = NotificationEventSearchResult(eventInfo) @@ -270,14 +260,12 @@ internal class NotificationEventSearchResultTests { "event_id1", lastUpdatedTimeMs, createdTimeMs, - "tenant", NotificationEvent(eventSource1, listOf(status1)) ) val eventInfo2 = NotificationEventInfo( "event_id2", lastUpdatedTimeMs, createdTimeMs, - "tenant", NotificationEvent(eventSource2, listOf(status2)) ) val searchResult = NotificationEventSearchResult( @@ -312,7 +300,6 @@ internal class NotificationEventSearchResultTests { "event_id", lastUpdatedTimeMs, createdTimeMs, - "selectedTenant", sampleEvent ) val searchResult = NotificationEventSearchResult(eventInfo) @@ -326,7 +313,6 @@ internal class NotificationEventSearchResultTests { "event_id":"event_id", "last_updated_time_ms":"${lastUpdatedTimeMs.toEpochMilli()}", "created_time_ms":"${createdTimeMs.toEpochMilli()}", - "tenant":"selectedTenant", "event":{ "event_source":{ "title":"title", @@ -380,7 +366,6 @@ internal class NotificationEventSearchResultTests { "event_id", lastUpdatedTimeMs, createdTimeMs, - "selectedTenant", sampleEvent ) val searchResult = NotificationEventSearchResult(eventInfo) @@ -391,7 +376,6 @@ internal class NotificationEventSearchResultTests { "event_id":"event_id", "last_updated_time_ms":"${lastUpdatedTimeMs.toEpochMilli()}", "created_time_ms":"${createdTimeMs.toEpochMilli()}", - "tenant":"selectedTenant", "event":{ "event_source":{ "title":"title", @@ -434,8 +418,7 @@ internal class NotificationEventSearchResultTests { { "event_id":"event_id", "last_updated_time_ms":"${lastUpdatedTimeMs.toEpochMilli()}", - "created_time_ms":"${createdTimeMs.toEpochMilli()}", - "tenant":"selectedTenant" + "created_time_ms":"${createdTimeMs.toEpochMilli()}" } ] } From 8ca20ff57b886232722fe11a456191aa37e8f611 Mon Sep 17 00:00:00 2001 From: Anantha Krishna Bhatta <31894175+akbhatta@users.noreply.github.com> Date: Thu, 23 Sep 2021 15:48:16 -0700 Subject: [PATCH 085/140] Updated the plugin feature response with allowed config features (#74) [Tests] Updated the unit tests Signed-off-by: @akbhatta Signed-off-by: Zelin Hao --- .../notifications/NotificationConstants.kt | 3 +- .../action/GetPluginFeaturesResponse.kt | 38 +++++++++++++------ .../NotificationsPluginInterfaceTests.kt | 1 + .../action/GetPluginFeaturesResponseTests.kt | 31 +++++++++++++-- 4 files changed, 56 insertions(+), 17 deletions(-) diff --git a/src/main/kotlin/org/opensearch/commons/notifications/NotificationConstants.kt b/src/main/kotlin/org/opensearch/commons/notifications/NotificationConstants.kt index dc16a39f..7a958154 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/NotificationConstants.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/NotificationConstants.kt @@ -66,7 +66,8 @@ object NotificationConstants { const val TOTAL_HIT_RELATION_TAG = "total_hit_relation" const val QUERY_TAG = "query" const val COMPACT_TAG = "compact" - const val CONFIG_TYPE_LIST_TAG = "config_type_list" + const val ALLOWED_CONFIG_TYPE_LIST_TAG = "allowed_config_type_list" + const val ALLOWED_CONFIG_FEATURE_LIST_TAG = "allowed_config_feature_list" const val PLUGIN_FEATURES_TAG = "plugin_features" const val FEATURE_ALERTING = "alerting" diff --git a/src/main/kotlin/org/opensearch/commons/notifications/action/GetPluginFeaturesResponse.kt b/src/main/kotlin/org/opensearch/commons/notifications/action/GetPluginFeaturesResponse.kt index 681b943e..dde25709 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/action/GetPluginFeaturesResponse.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/action/GetPluginFeaturesResponse.kt @@ -33,7 +33,8 @@ import org.opensearch.common.xcontent.ToXContent import org.opensearch.common.xcontent.XContentBuilder import org.opensearch.common.xcontent.XContentParser import org.opensearch.common.xcontent.XContentParserUtils -import org.opensearch.commons.notifications.NotificationConstants.CONFIG_TYPE_LIST_TAG +import org.opensearch.commons.notifications.NotificationConstants.ALLOWED_CONFIG_FEATURE_LIST_TAG +import org.opensearch.commons.notifications.NotificationConstants.ALLOWED_CONFIG_TYPE_LIST_TAG import org.opensearch.commons.notifications.NotificationConstants.PLUGIN_FEATURES_TAG import org.opensearch.commons.utils.STRING_READER import org.opensearch.commons.utils.STRING_WRITER @@ -45,7 +46,8 @@ import java.io.IOException * Action Response for getting notification plugin features. */ class GetPluginFeaturesResponse : BaseResponse { - val configTypeList: List + val allowedConfigTypeList: List + val allowedConfigFeatureList: List val pluginFeatures: Map companion object { @@ -63,7 +65,8 @@ class GetPluginFeaturesResponse : BaseResponse { @JvmStatic @Throws(IOException::class) fun parse(parser: XContentParser): GetPluginFeaturesResponse { - var configTypeList: List? = null + var allowedConfigTypeList: List? = null + var allowedConfigFeatureList: List? = null var pluginFeatures: Map? = null XContentParserUtils.ensureExpectedToken( @@ -75,7 +78,8 @@ class GetPluginFeaturesResponse : BaseResponse { val fieldName = parser.currentName() parser.nextToken() when (fieldName) { - CONFIG_TYPE_LIST_TAG -> configTypeList = parser.stringList() + ALLOWED_CONFIG_TYPE_LIST_TAG -> allowedConfigTypeList = parser.stringList() + ALLOWED_CONFIG_FEATURE_LIST_TAG -> allowedConfigFeatureList = parser.stringList() PLUGIN_FEATURES_TAG -> pluginFeatures = parser.mapStrings() else -> { parser.skipChildren() @@ -83,9 +87,10 @@ class GetPluginFeaturesResponse : BaseResponse { } } } - configTypeList ?: throw IllegalArgumentException("$CONFIG_TYPE_LIST_TAG field absent") + allowedConfigTypeList ?: throw IllegalArgumentException("$ALLOWED_CONFIG_TYPE_LIST_TAG field absent") + allowedConfigFeatureList ?: throw IllegalArgumentException("$ALLOWED_CONFIG_TYPE_LIST_TAG field absent") pluginFeatures ?: throw IllegalArgumentException("$PLUGIN_FEATURES_TAG field absent") - return GetPluginFeaturesResponse(configTypeList, pluginFeatures) + return GetPluginFeaturesResponse(allowedConfigTypeList, allowedConfigFeatureList, pluginFeatures) } } @@ -94,18 +99,25 @@ class GetPluginFeaturesResponse : BaseResponse { */ override fun toXContent(builder: XContentBuilder?, params: ToXContent.Params?): XContentBuilder { return builder!!.startObject() - .field(CONFIG_TYPE_LIST_TAG, configTypeList) + .field(ALLOWED_CONFIG_TYPE_LIST_TAG, allowedConfigTypeList) + .field(ALLOWED_CONFIG_FEATURE_LIST_TAG, allowedConfigFeatureList) .field(PLUGIN_FEATURES_TAG, pluginFeatures) .endObject() } /** * constructor for creating the class - * @param configTypeList the list of config types supported by plugin + * @param allowedConfigTypeList the list of config types supported by plugin + * @param allowedConfigFeatureList the list of config features supported by plugin * @param pluginFeatures the map of plugin features supported to its value */ - constructor(configTypeList: List, pluginFeatures: Map) { - this.configTypeList = configTypeList + constructor( + allowedConfigTypeList: List, + allowedConfigFeatureList: List, + pluginFeatures: Map + ) { + this.allowedConfigTypeList = allowedConfigTypeList + this.allowedConfigFeatureList = allowedConfigFeatureList this.pluginFeatures = pluginFeatures } @@ -114,7 +126,8 @@ class GetPluginFeaturesResponse : BaseResponse { */ @Throws(IOException::class) constructor(input: StreamInput) : super(input) { - configTypeList = input.readStringList() + allowedConfigTypeList = input.readStringList() + allowedConfigFeatureList = input.readStringList() pluginFeatures = input.readMap(STRING_READER, STRING_READER) } @@ -123,7 +136,8 @@ class GetPluginFeaturesResponse : BaseResponse { */ @Throws(IOException::class) override fun writeTo(output: StreamOutput) { - output.writeStringCollection(configTypeList) + output.writeStringCollection(allowedConfigTypeList) + output.writeStringCollection(allowedConfigFeatureList) output.writeMap(pluginFeatures, STRING_WRITER, STRING_WRITER) } } diff --git a/src/test/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterfaceTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterfaceTests.kt index 77d12ff2..31d47bba 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterfaceTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterfaceTests.kt @@ -156,6 +156,7 @@ internal class NotificationsPluginInterfaceTests { val request = mock(GetPluginFeaturesRequest::class.java) val response = GetPluginFeaturesResponse( listOf("config_type_1", "config_type_2", "config_type_3"), + listOf("config_feature_1", "config_feature_2", "config_feature_3"), mapOf( Pair("FeatureKey1", "FeatureValue1"), Pair("FeatureKey2", "FeatureValue2"), diff --git a/src/test/kotlin/org/opensearch/commons/notifications/action/GetPluginFeaturesResponseTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/action/GetPluginFeaturesResponseTests.kt index 3103825f..930d430f 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/action/GetPluginFeaturesResponseTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/action/GetPluginFeaturesResponseTests.kt @@ -39,7 +39,7 @@ internal class GetPluginFeaturesResponseTests { expected: GetPluginFeaturesResponse, actual: GetPluginFeaturesResponse ) { - assertEquals(expected.configTypeList, actual.configTypeList) + assertEquals(expected.allowedConfigTypeList, actual.allowedConfigTypeList) assertEquals(expected.pluginFeatures, actual.pluginFeatures) } @@ -47,6 +47,7 @@ internal class GetPluginFeaturesResponseTests { fun `Get Response serialize and deserialize transport object should be equal`() { val response = GetPluginFeaturesResponse( listOf("config_type_1", "config_type_2", "config_type_3"), + listOf("config_feature_1", "config_feature_2", "config_feature_3"), mapOf( Pair("FeatureKey1", "FeatureValue1"), Pair("FeatureKey2", "FeatureValue2"), @@ -61,6 +62,7 @@ internal class GetPluginFeaturesResponseTests { fun `Get Response serialize and deserialize using json config object should be equal`() { val response = GetPluginFeaturesResponse( listOf("config_type_1", "config_type_2", "config_type_3"), + listOf("config_feature_1", "config_feature_2", "config_feature_3"), mapOf( Pair("FeatureKey1", "FeatureValue1"), Pair("FeatureKey2", "FeatureValue2"), @@ -76,6 +78,7 @@ internal class GetPluginFeaturesResponseTests { fun `Get Response should safely ignore extra field in json object`() { val response = GetPluginFeaturesResponse( listOf("config_type_1", "config_type_2", "config_type_3"), + listOf("config_feature_1", "config_feature_2", "config_feature_3"), mapOf( Pair("FeatureKey1", "FeatureValue1"), Pair("FeatureKey2", "FeatureValue2"), @@ -84,7 +87,8 @@ internal class GetPluginFeaturesResponseTests { ) val jsonString = """ { - "config_type_list":["config_type_1", "config_type_2", "config_type_3"], + "allowed_config_type_list":["config_type_1", "config_type_2", "config_type_3"], + "allowed_config_feature_list":["config_feature_1", "config_feature_2", "config_feature_3"], "plugin_features":{ "FeatureKey1":"FeatureValue1", "FeatureKey2":"FeatureValue2", @@ -100,9 +104,27 @@ internal class GetPluginFeaturesResponseTests { } @Test - fun `Get Response should throw exception if config_type_list is absent in json`() { + fun `Get Response should throw exception if allowed_config_type_list is absent in json`() { val jsonString = """ { + "allowed_config_feature_list":["config_feature_1", "config_feature_2", "config_feature_3"], + "plugin_features":{ + "FeatureKey1":"FeatureValue1", + "FeatureKey2":"FeatureValue2", + "FeatureKey3":"FeatureValue3" + } + } + """.trimIndent() + Assertions.assertThrows(IllegalArgumentException::class.java) { + createObjectFromJsonString(jsonString) { GetPluginFeaturesResponse.parse(it) } + } + } + + @Test + fun `Get Response should throw exception if allowed_config_feature_list is absent in json`() { + val jsonString = """ + { + "allowed_config_type_list":["config_type_1", "config_type_2", "config_type_3"], "plugin_features":{ "FeatureKey1":"FeatureValue1", "FeatureKey2":"FeatureValue2", @@ -119,7 +141,8 @@ internal class GetPluginFeaturesResponseTests { fun `Get Response should throw exception if plugin_features is absent in json`() { val jsonString = """ { - "config_type_list":["config_type_1", "config_type_2", "config_type_3"] + "config_type_list":["config_type_1", "config_type_2", "config_type_3"], + "allowed_config_feature_list":["config_feature_1", "config_feature_2", "config_feature_3"] } """.trimIndent() Assertions.assertThrows(IllegalArgumentException::class.java) { From 8d390f472defc6ed22cd03e336b9684d43d9d586 Mon Sep 17 00:00:00 2001 From: Clay Downs <89109232+downsrob@users.noreply.github.com> Date: Thu, 30 Sep 2021 17:41:03 -0700 Subject: [PATCH 086/140] Updates common-utils version to 1.2 (#77) * Updates common-utils version to 1.2 and Uses Maven for 1.2 dependencies Signed-off-by: Clay Downs Signed-off-by: Zelin Hao --- .github/workflows/ci.yml | 15 ++------------- build.gradle | 4 +++- 2 files changed, 5 insertions(+), 14 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8f83153e..52eea2f1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -25,25 +25,14 @@ jobs: with: java-version: ${{ matrix.java }} - # dependencies: OpenSearch - - name: Checkout OpenSearch - uses: actions/checkout@v2 - with: - repository: 'opensearch-project/OpenSearch' - path: OpenSearch - ref: '1.1' - - name: Build OpenSearch - working-directory: ./OpenSearch - run: ./gradlew publishToMavenLocal - # common-utils - name: Build and Test run: | - ./gradlew build -Dopensearch.version=1.1.0-SNAPSHOT + ./gradlew build -Dopensearch.version=1.2.0-SNAPSHOT - name: Publish to Maven Local run: | - ./gradlew publishToMavenLocal -Dopensearch.version=1.1.0-SNAPSHOT + ./gradlew publishToMavenLocal -Dopensearch.version=1.2.0-SNAPSHOT - name: Upload Coverage Report uses: codecov/codecov-action@v1 diff --git a/build.gradle b/build.gradle index d443ddf4..dc33b6d9 100644 --- a/build.gradle +++ b/build.gradle @@ -12,7 +12,7 @@ buildscript { ext { opensearch_group = "org.opensearch" - opensearch_version = System.getProperty("opensearch.version", "1.1.0-SNAPSHOT") + opensearch_version = System.getProperty("opensearch.version", "1.2.0-SNAPSHOT") kotlin_version = System.getProperty("kotlin.version", "1.4.32") } @@ -21,6 +21,7 @@ buildscript { mavenCentral() maven { url "https://plugins.gradle.org/m2/" } jcenter() + maven { url "https://aws.oss.sonatype.org/content/repositories/snapshots" } } dependencies { @@ -42,6 +43,7 @@ repositories { mavenCentral() maven { url "https://plugins.gradle.org/m2/" } jcenter() + maven { url "https://aws.oss.sonatype.org/content/repositories/snapshots" } } ext { From c7f9a5f97095ffab78b7d500255d04b0218c2c7d Mon Sep 17 00:00:00 2001 From: "Daniel Doubrovkine (dB.)" Date: Wed, 6 Oct 2021 13:43:20 -0400 Subject: [PATCH 087/140] Publish .md5 and .sha1 signatures. (#79) (#80) * Publish .md5 and .sha1 signatures. Signed-off-by: dblock * Use OpenSearch 1.1. Signed-off-by: dblock Signed-off-by: Zelin Hao --- .github/workflows/push-common-utils-jar.yml | 44 --------------- build.gradle | 10 ++-- scripts/build.sh | 61 +++++++++++++++++++++ 3 files changed, 66 insertions(+), 49 deletions(-) delete mode 100644 .github/workflows/push-common-utils-jar.yml create mode 100755 scripts/build.sh diff --git a/.github/workflows/push-common-utils-jar.yml b/.github/workflows/push-common-utils-jar.yml deleted file mode 100644 index 6a4bc703..00000000 --- a/.github/workflows/push-common-utils-jar.yml +++ /dev/null @@ -1,44 +0,0 @@ -name: Upload Common-Utils Jar to Maven - -on: - push: - tags: - - v* -jobs: - upload-common-utils-jar: - runs-on: [ubuntu-16.04] - name: Upload common-utils Jar to Maven - steps: - - name: Checkout Repo - uses: actions/checkout@v2 - - - name: Configure AWS CLI - uses: aws-actions/configure-aws-credentials@v1 - with: - aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} - aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} - aws-region: us-east-1 - - - name: Setup Java - uses: actions/setup-java@v1 - with: - java-version: '14' - - - name: Upload common-utils Jar to Maven - env: - passphrase: ${{ secrets.PASSPHRASE }} - run: | - cd .. - export JAVA14_HOME=$JAVA_HOME - aws s3 cp s3://opendistro-docs/github-actions/pgp-public-key . - aws s3 cp s3://opendistro-docs/github-actions/pgp-private-key . - - gpg --import pgp-public-key - gpg --allow-secret-key-import --import pgp-private-key - - mkdir /home/runner/.gradle - aws s3 cp s3://opendistro-docs/github-actions/gradle.properties /home/runner/.gradle/ - - cd common-utils - - ./gradlew publishShadowPublicationToSonatype-stagingRepository -Dcompiler.java=14 -Dbuild.snapshot=false -Djavax.net.ssl.trustStore=$JAVA_HOME/lib/security/cacerts diff --git a/build.gradle b/build.gradle index dc33b6d9..b0a720cf 100644 --- a/build.gradle +++ b/build.gradle @@ -148,6 +148,11 @@ shadowJar { classifier = null } +shadowJar.doLast { + ant.checksum algorithm: 'md5', file: it.archivePath + ant.checksum algorithm: 'sha1', file: it.archivePath +} + task sourcesJar(type: Jar) { classifier = 'sources' from sourceSets.main.allJava @@ -197,9 +202,4 @@ publishing { gradle.startParameter.setShowStacktrace(ShowStacktrace.ALWAYS) gradle.startParameter.setLogLevel(LogLevel.DEBUG) - - signing { - required { gradle.taskGraph.hasTask("publishShadowPublicationToSonatype-stagingRepository") } - sign publishing.publications.shadow - } } diff --git a/scripts/build.sh b/scripts/build.sh new file mode 100755 index 00000000..fdc9be57 --- /dev/null +++ b/scripts/build.sh @@ -0,0 +1,61 @@ +#!/bin/bash + +# Copyright OpenSearch Contributors. +# SPDX-License-Identifier: Apache-2.0 + +set -ex + +function usage() { + echo "Usage: $0 [args]" + echo "" + echo "Arguments:" + echo -e "-v VERSION\t[Required] OpenSearch version." + echo -e "-s SNAPSHOT\t[Optional] Build a snapshot, default is 'false'." + echo -e "-a ARCHITECTURE\t[Optional] Build architecture, ignored." + echo -e "-o OUTPUT\t[Optional] Output path, default is 'artifacts'." + echo -e "-h help" +} + +while getopts ":h:v:s:o:a:" arg; do + case $arg in + h) + usage + exit 1 + ;; + v) + VERSION=$OPTARG + ;; + s) + SNAPSHOT=$OPTARG + ;; + o) + OUTPUT=$OPTARG + ;; + a) + ARCHITECTURE=$OPTARG + ;; + :) + echo "Error: -${OPTARG} requires an argument" + usage + exit 1 + ;; + ?) + echo "Invalid option: -${arg}" + exit 1 + ;; + esac +done + +if [ -z "$VERSION" ]; then + echo "Error: You must specify the OpenSearch version" + usage + exit 1 +fi + +[[ "$SNAPSHOT" == "true" ]] && VERSION=$VERSION-SNAPSHOT +[ -z "$OUTPUT" ] && OUTPUT=artifacts + +./gradlew build -Dopensearch.version=$VERSION -Dbuild.snapshot=$SNAPSHOT +./gradlew publishShadowPublicationToMavenLocal -Dopensearch.version=$VERSION -Dbuild.snapshot=$SNAPSHOT +mkdir -p $OUTPUT/maven/org/opensearch +cp -r ./build/libs $OUTPUT/maven/org/opensearch/common-utils From 7f75cbbf61d3e839988993e17b990dbe66d3046e Mon Sep 17 00:00:00 2001 From: "Daniel Doubrovkine (dB.)" Date: Wed, 6 Oct 2021 17:10:21 -0400 Subject: [PATCH 088/140] Publish source and javadoc checksums. (#81) Signed-off-by: dblock Signed-off-by: Zelin Hao --- build.gradle | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/build.gradle b/build.gradle index b0a720cf..92f71cc5 100644 --- a/build.gradle +++ b/build.gradle @@ -148,11 +148,6 @@ shadowJar { classifier = null } -shadowJar.doLast { - ant.checksum algorithm: 'md5', file: it.archivePath - ant.checksum algorithm: 'sha1', file: it.archivePath -} - task sourcesJar(type: Jar) { classifier = 'sources' from sourceSets.main.allJava @@ -163,6 +158,15 @@ task javadocJar(type: Jar) { from javadoc.destinationDir } +tasks.withType(Jar) { task -> + task.doLast { + ant.checksum algorithm: 'md5', file: it.archivePath + ant.checksum algorithm: 'sha1', file: it.archivePath + ant.checksum algorithm: 'sha-256', file: it.archivePath, fileext: '.sha256' + ant.checksum algorithm: 'sha-512', file: it.archivePath, fileext: '.sha512' + } +} + publishing { publications { shadow(MavenPublication) { From 45913ea913d0f588dd7647300f111220dd4e917c Mon Sep 17 00:00:00 2001 From: Anantha Krishna Bhatta <31894175+akbhatta@users.noreply.github.com> Date: Wed, 13 Oct 2021 12:28:34 -0700 Subject: [PATCH 089/140] Email recipients made nested for backward compatibility with Alerting (#83) [Tests] Unit tests added/updated Signed-off-by: @akbhatta Signed-off-by: Zelin Hao --- .../commons/notifications/model/Email.kt | 15 +- .../commons/notifications/model/EmailGroup.kt | 19 +-- .../notifications/model/EmailRecipient.kt | 119 +++++++++++++++ .../CreateNotificationConfigRequestTests.kt | 18 ++- .../action/GetPluginFeaturesResponseTests.kt | 1 + .../UpdateNotificationConfigRequestTests.kt | 18 ++- .../notifications/model/EmailGroupTests.kt | 90 +++++------ .../model/EmailRecipientTests.kt | 142 ++++++++++++++++++ .../commons/notifications/model/EmailTests.kt | 69 +++------ .../model/NotificationConfigTests.kt | 8 +- .../model/config/ConfigPropertiesTests.kt | 3 +- 11 files changed, 361 insertions(+), 141 deletions(-) create mode 100644 src/main/kotlin/org/opensearch/commons/notifications/model/EmailRecipient.kt create mode 100644 src/test/kotlin/org/opensearch/commons/notifications/model/EmailRecipientTests.kt diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/Email.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/Email.kt index c8da0f85..86d5f67a 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/Email.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/Email.kt @@ -38,8 +38,8 @@ import org.opensearch.commons.notifications.NotificationConstants.EMAIL_ACCOUNT_ import org.opensearch.commons.notifications.NotificationConstants.EMAIL_GROUP_ID_LIST_TAG import org.opensearch.commons.notifications.NotificationConstants.RECIPIENT_LIST_TAG import org.opensearch.commons.utils.logger +import org.opensearch.commons.utils.objectList import org.opensearch.commons.utils.stringList -import org.opensearch.commons.utils.validateEmail import java.io.IOException /** @@ -47,15 +47,12 @@ import java.io.IOException */ data class Email( val emailAccountID: String, - val recipients: List, + val recipients: List, val emailGroupIds: List ) : BaseConfigData { init { require(!Strings.isNullOrEmpty(emailAccountID)) { "emailAccountID is null or empty" } - recipients.forEach { - validateEmail(it) - } } companion object { @@ -79,7 +76,7 @@ data class Email( @Throws(IOException::class) fun parse(parser: XContentParser): Email { var emailAccountID: String? = null - var recipients: List = listOf() + var recipients: List = listOf() var emailGroupIds: List = listOf() XContentParserUtils.ensureExpectedToken( @@ -92,7 +89,7 @@ data class Email( parser.nextToken() when (fieldName) { EMAIL_ACCOUNT_ID_TAG -> emailAccountID = parser.text() - RECIPIENT_LIST_TAG -> recipients = parser.stringList() + RECIPIENT_LIST_TAG -> recipients = parser.objectList { EmailRecipient.parse(it) } EMAIL_GROUP_ID_LIST_TAG -> emailGroupIds = parser.stringList() else -> { parser.skipChildren() @@ -111,7 +108,7 @@ data class Email( */ constructor(input: StreamInput) : this( emailAccountID = input.readString(), - recipients = input.readStringList(), + recipients = input.readList(EmailRecipient.reader), emailGroupIds = input.readStringList() ) @@ -120,7 +117,7 @@ data class Email( */ override fun writeTo(output: StreamOutput) { output.writeString(emailAccountID) - output.writeStringCollection(recipients) + output.writeList(recipients) output.writeStringCollection(emailGroupIds) } diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/EmailGroup.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/EmailGroup.kt index f3beecd8..4940cc39 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/EmailGroup.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/EmailGroup.kt @@ -35,23 +35,16 @@ import org.opensearch.common.xcontent.XContentParser import org.opensearch.common.xcontent.XContentParserUtils import org.opensearch.commons.notifications.NotificationConstants.RECIPIENT_LIST_TAG import org.opensearch.commons.utils.logger -import org.opensearch.commons.utils.stringList -import org.opensearch.commons.utils.validateEmail +import org.opensearch.commons.utils.objectList import java.io.IOException /** * Data class representing Email group. */ data class EmailGroup( - val recipients: List + val recipients: List ) : BaseConfigData { - init { - recipients.forEach { - validateEmail(it) - } - } - companion object { private val log by logger(EmailGroup::class.java) @@ -72,7 +65,7 @@ data class EmailGroup( @JvmStatic @Throws(IOException::class) fun parse(parser: XContentParser): EmailGroup { - var recipients: List? = null + var recipients: List? = null XContentParserUtils.ensureExpectedToken( XContentParser.Token.START_OBJECT, @@ -83,7 +76,7 @@ data class EmailGroup( val fieldName = parser.currentName() parser.nextToken() when (fieldName) { - RECIPIENT_LIST_TAG -> recipients = parser.stringList() + RECIPIENT_LIST_TAG -> recipients = parser.objectList { EmailRecipient.parse(it) } else -> { parser.skipChildren() log.info("Unexpected field: $fieldName, while parsing EmailGroup") @@ -100,14 +93,14 @@ data class EmailGroup( * @param input StreamInput stream to deserialize data from. */ constructor(input: StreamInput) : this( - recipients = input.readStringList() + recipients = input.readList(EmailRecipient.reader) ) /** * {@inheritDoc} */ override fun writeTo(output: StreamOutput) { - output.writeStringCollection(recipients) + output.writeList(recipients) } /** diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/EmailRecipient.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/EmailRecipient.kt new file mode 100644 index 00000000..78c4ae59 --- /dev/null +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/EmailRecipient.kt @@ -0,0 +1,119 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + * + * Modifications Copyright OpenSearch Contributors. See + * GitHub history for details. + */ + +/* + * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + * + */ +package org.opensearch.commons.notifications.model + +import org.opensearch.common.io.stream.StreamInput +import org.opensearch.common.io.stream.StreamOutput +import org.opensearch.common.io.stream.Writeable +import org.opensearch.common.xcontent.ToXContent +import org.opensearch.common.xcontent.XContentBuilder +import org.opensearch.common.xcontent.XContentParser +import org.opensearch.common.xcontent.XContentParserUtils +import org.opensearch.commons.notifications.NotificationConstants.RECIPIENT_TAG +import org.opensearch.commons.utils.logger +import org.opensearch.commons.utils.validateEmail +import java.io.IOException + +/** + * Data class representing Email recipient. + */ +data class EmailRecipient( + val recipient: String +) : BaseConfigData { + + init { + validateEmail(recipient) + } + + companion object { + private val log by logger(EmailRecipient::class.java) + + /** + * reader to create instance of class from writable. + */ + val reader = Writeable.Reader { EmailRecipient(it) } + + /** + * Parser to parse xContent + */ + val xParser = XParser { parse(it) } + + /** + * Creator used in REST communication. + * @param parser XContentParser to deserialize data from. + */ + @JvmStatic + @Throws(IOException::class) + fun parse(parser: XContentParser): EmailRecipient { + var recipient: String? = null + + XContentParserUtils.ensureExpectedToken( + XContentParser.Token.START_OBJECT, + parser.currentToken(), + parser + ) + while (parser.nextToken() != XContentParser.Token.END_OBJECT) { + val fieldName = parser.currentName() + parser.nextToken() + when (fieldName) { + RECIPIENT_TAG -> recipient = parser.text() + else -> { + parser.skipChildren() + log.info("Unexpected field: $fieldName, while parsing EmailRecipient") + } + } + } + recipient ?: throw IllegalArgumentException("$RECIPIENT_TAG field absent") + return EmailRecipient(recipient) + } + } + + /** + * Constructor used in transport action communication. + * @param input StreamInput stream to deserialize data from. + */ + constructor(input: StreamInput) : this( + recipient = input.readString() + ) + + /** + * {@inheritDoc} + */ + override fun writeTo(output: StreamOutput) { + output.writeString(recipient) + } + + /** + * {@inheritDoc} + */ + override fun toXContent(builder: XContentBuilder?, params: ToXContent.Params?): XContentBuilder { + builder!! + return builder.startObject() + .field(RECIPIENT_TAG, recipient) + .endObject() + } +} diff --git a/src/test/kotlin/org/opensearch/commons/notifications/action/CreateNotificationConfigRequestTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/action/CreateNotificationConfigRequestTests.kt index f190e7f6..28f337b8 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/action/CreateNotificationConfigRequestTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/action/CreateNotificationConfigRequestTests.kt @@ -36,6 +36,7 @@ import org.opensearch.commons.notifications.model.Chime import org.opensearch.commons.notifications.model.ConfigType import org.opensearch.commons.notifications.model.Email import org.opensearch.commons.notifications.model.EmailGroup +import org.opensearch.commons.notifications.model.EmailRecipient import org.opensearch.commons.notifications.model.MethodType import org.opensearch.commons.notifications.model.NotificationConfig import org.opensearch.commons.notifications.model.Slack @@ -84,7 +85,7 @@ internal class CreateNotificationConfigRequestTests { } private fun createEmailGroupContentConfigObject(): NotificationConfig { - val sampleEmailGroup = EmailGroup(listOf("dummy@company.com")) + val sampleEmailGroup = EmailGroup(listOf(EmailRecipient("dummy@company.com"))) return NotificationConfig( "name", "description", @@ -98,7 +99,7 @@ internal class CreateNotificationConfigRequestTests { private fun createEmailContentConfigObject(): NotificationConfig { val sampleEmail = Email( emailAccountID = "sample_1@dummy.com", - recipients = listOf("sample_2@dummy.com"), + recipients = listOf(EmailRecipient("sample_2@dummy.com")), emailGroupIds = listOf("sample_3@dummy.com") ) return NotificationConfig( @@ -365,7 +366,7 @@ internal class CreateNotificationConfigRequestTests { @Test fun `Create config should deserialize json object using parser Email Group`() { - val sampleEmailGroup = EmailGroup(listOf("dummy@company.com")) + val sampleEmailGroup = EmailGroup(listOf(EmailRecipient("dummy@company.com"))) val config = NotificationConfig( "name", "description", @@ -384,7 +385,7 @@ internal class CreateNotificationConfigRequestTests { "config_type":"email_group", "feature_list":["index_management"], "is_enabled":true, - "email_group":{"recipient_list":["dummy@company.com"]} + "email_group":{"recipient_list":[{"recipient":"dummy@company.com"}]} } } """.trimIndent() @@ -396,7 +397,7 @@ internal class CreateNotificationConfigRequestTests { fun `Update config should deserialize json object using parser Email`() { val sampleEmail = Email( emailAccountID = "sample_1@dummy.com", - recipients = listOf("sample_2@dummy.com"), + recipients = listOf(EmailRecipient("sample_2@dummy.com")), emailGroupIds = listOf("sample_3@dummy.com") ) val config = NotificationConfig( @@ -417,8 +418,11 @@ internal class CreateNotificationConfigRequestTests { "config_type":"email", "feature_list":["index_management"], "is_enabled":true, - "email":{"email_account_id":"sample_1@dummy.com","recipient_list":["sample_2@dummy.com"], - "email_group_id_list":["sample_3@dummy.com"] } + "email":{ + "email_account_id":"sample_1@dummy.com", + "recipient_list":[{"recipient":"sample_2@dummy.com"}], + "email_group_id_list":["sample_3@dummy.com"] + } } } """.trimIndent() diff --git a/src/test/kotlin/org/opensearch/commons/notifications/action/GetPluginFeaturesResponseTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/action/GetPluginFeaturesResponseTests.kt index 930d430f..c9924269 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/action/GetPluginFeaturesResponseTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/action/GetPluginFeaturesResponseTests.kt @@ -40,6 +40,7 @@ internal class GetPluginFeaturesResponseTests { actual: GetPluginFeaturesResponse ) { assertEquals(expected.allowedConfigTypeList, actual.allowedConfigTypeList) + assertEquals(expected.allowedConfigFeatureList, actual.allowedConfigFeatureList) assertEquals(expected.pluginFeatures, actual.pluginFeatures) } diff --git a/src/test/kotlin/org/opensearch/commons/notifications/action/UpdateNotificationConfigRequestTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/action/UpdateNotificationConfigRequestTests.kt index 2dfcff69..9599d60e 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/action/UpdateNotificationConfigRequestTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/action/UpdateNotificationConfigRequestTests.kt @@ -36,6 +36,7 @@ import org.opensearch.commons.notifications.model.Chime import org.opensearch.commons.notifications.model.ConfigType import org.opensearch.commons.notifications.model.Email import org.opensearch.commons.notifications.model.EmailGroup +import org.opensearch.commons.notifications.model.EmailRecipient import org.opensearch.commons.notifications.model.MethodType import org.opensearch.commons.notifications.model.NotificationConfig import org.opensearch.commons.notifications.model.Slack @@ -84,7 +85,7 @@ internal class UpdateNotificationConfigRequestTests { } private fun createEmailGroupContentConfigObject(): NotificationConfig { - val sampleEmailGroup = EmailGroup(listOf("dummy@company.com")) + val sampleEmailGroup = EmailGroup(listOf(EmailRecipient("dummy@company.com"))) return NotificationConfig( "name", "description", @@ -98,7 +99,7 @@ internal class UpdateNotificationConfigRequestTests { private fun createEmailContentConfigObject(): NotificationConfig { val sampleEmail = Email( emailAccountID = "sample_1@dummy.com", - recipients = listOf("sample_2@dummy.com"), + recipients = listOf(EmailRecipient("sample_2@dummy.com")), emailGroupIds = listOf("sample_3@dummy.com") ) return NotificationConfig( @@ -334,7 +335,7 @@ internal class UpdateNotificationConfigRequestTests { @Test fun `Update config should deserialize json object using parser Email Group`() { - val sampleEmailGroup = EmailGroup(listOf("dummy@company.com")) + val sampleEmailGroup = EmailGroup(listOf(EmailRecipient("dummy@company.com"))) val config = NotificationConfig( "name", "description", @@ -353,7 +354,7 @@ internal class UpdateNotificationConfigRequestTests { "config_type":"email_group", "feature_list":["index_management"], "is_enabled":true, - "email_group":{"recipient_list":["dummy@company.com"]} + "email_group":{"recipient_list":[{"recipient":"dummy@company.com"}]} } } """.trimIndent() @@ -366,7 +367,7 @@ internal class UpdateNotificationConfigRequestTests { fun `Update config should deserialize json object using parser Email`() { val sampleEmail = Email( emailAccountID = "sample_1@dummy.com", - recipients = listOf("sample_2@dummy.com"), + recipients = listOf(EmailRecipient("sample_2@dummy.com")), emailGroupIds = listOf("sample_3@dummy.com") ) val config = NotificationConfig( @@ -387,8 +388,11 @@ internal class UpdateNotificationConfigRequestTests { "config_type":"email", "feature_list":["index_management"], "is_enabled":true, - "email":{"email_account_id":"sample_1@dummy.com","recipient_list":["sample_2@dummy.com"], - "email_group_id_list":["sample_3@dummy.com"] } + "email":{ + "email_account_id":"sample_1@dummy.com", + "recipient_list":[{"recipient":"sample_2@dummy.com"}], + "email_group_id_list":["sample_3@dummy.com"] + } } } """.trimIndent() diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/EmailGroupTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/EmailGroupTests.kt index 5146d785..dbf2f77b 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/EmailGroupTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/EmailGroupTests.kt @@ -29,7 +29,6 @@ package org.opensearch.commons.notifications.model import com.fasterxml.jackson.core.JsonParseException import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Test -import org.junit.jupiter.api.assertDoesNotThrow import org.junit.jupiter.api.assertThrows import org.opensearch.commons.utils.createObjectFromJsonString import org.opensearch.commons.utils.getJsonString @@ -37,56 +36,26 @@ import org.opensearch.commons.utils.recreateObject internal class EmailGroupTests { - private fun checkValidEmailAddress(emailAddress: String) { - assertDoesNotThrow("should accept $emailAddress") { - EmailGroup(listOf(emailAddress)) - } - } - - private fun checkInvalidEmailAddress(emailAddress: String) { - assertThrows("Should throw an Exception for invalid email $emailAddress") { - EmailGroup(listOf(emailAddress)) - } - } - - @Test - fun `EmailGroup should accept valid email address`() { - checkValidEmailAddress("email1234@email.com") - checkValidEmailAddress("email+1234@email.com") - checkValidEmailAddress("email-1234@email.com") - checkValidEmailAddress("email_1234@email.com") - checkValidEmailAddress("email.1234@email.com") - checkValidEmailAddress("e.ma_il-1+2@test-email-domain.co.uk") - checkValidEmailAddress("email-.+_=#|@domain.com") - checkValidEmailAddress("e@mail.com") - } - - @Test - fun `EmailGroup should throw exception for invalid email address`() { - checkInvalidEmailAddress("email") - checkInvalidEmailAddress("email@") - checkInvalidEmailAddress("email@1234@email.com") - checkInvalidEmailAddress(".email@email.com") - checkInvalidEmailAddress("email.@email.com") - checkInvalidEmailAddress("email..1234@email.com") - checkInvalidEmailAddress("email@email..com") - checkInvalidEmailAddress("email@.com") - checkInvalidEmailAddress("email@email.com.") - checkInvalidEmailAddress("email@.email.com") - checkInvalidEmailAddress("email@email.com-") - checkInvalidEmailAddress("email@email_domain.com") - } - @Test fun `EmailGroup serialize and deserialize transport object should be equal`() { - val sampleEmailGroup = EmailGroup(listOf("email1@email.com", "email2@email.com")) + val sampleEmailGroup = EmailGroup( + listOf( + EmailRecipient("email1@email.com"), + EmailRecipient("email2@email.com") + ) + ) val recreatedObject = recreateObject(sampleEmailGroup) { EmailGroup(it) } assertEquals(sampleEmailGroup, recreatedObject) } @Test fun `EmailGroup serialize and deserialize using json object should be equal`() { - val sampleEmailGroup = EmailGroup(listOf("email1@email.com", "email2@email.com")) + val sampleEmailGroup = EmailGroup( + listOf( + EmailRecipient("email1@email.com"), + EmailRecipient("email2@email.com") + ) + ) val jsonString = getJsonString(sampleEmailGroup) val recreatedObject = createObjectFromJsonString(jsonString) { EmailGroup.parse(it) } assertEquals(sampleEmailGroup, recreatedObject) @@ -94,12 +63,17 @@ internal class EmailGroupTests { @Test fun `EmailGroup should deserialize json object using parser`() { - val sampleEmailGroup = EmailGroup(listOf("email1@email.com", "email2@email.com")) + val sampleEmailGroup = EmailGroup( + listOf( + EmailRecipient("email1@email.com"), + EmailRecipient("email2@email.com") + ) + ) val jsonString = """ { "recipient_list":[ - "${sampleEmailGroup.recipients[0]}", - "${sampleEmailGroup.recipients[1]}" + {"recipient":"${sampleEmailGroup.recipients[0].recipient}"}, + {"recipient":"${sampleEmailGroup.recipients[1].recipient}"} ] }" """.trimIndent() @@ -117,12 +91,17 @@ internal class EmailGroupTests { @Test fun `EmailGroup should throw exception when recipients is replaced with recipients2 in json object`() { - val sampleEmailGroup = EmailGroup(listOf("email1@email.com", "email2@email.com")) + val sampleEmailGroup = EmailGroup( + listOf( + EmailRecipient("email1@email.com"), + EmailRecipient("email2@email.com") + ) + ) val jsonString = """ { "recipient_list2":[ - "${sampleEmailGroup.recipients[0]}", - "${sampleEmailGroup.recipients[1]}" + {"recipient":"${sampleEmailGroup.recipients[0]}"}, + {"recipient":"${sampleEmailGroup.recipients[1]}"} ] }" """.trimIndent() @@ -133,8 +112,17 @@ internal class EmailGroupTests { @Test fun `EmailGroup should safely ignore extra field in json object`() { - val sampleEmailGroup = EmailGroup(listOf("email@email.com")) - val jsonString = "{\"recipient_list\":[\"${sampleEmailGroup.recipients[0]}\"], \"another\":\"field\"}" + val sampleEmailGroup = EmailGroup(listOf(EmailRecipient("email1@email.com"))) + val jsonString = """ + { + "recipient_list":[ + {"recipient":"${sampleEmailGroup.recipients[0].recipient}"} + ], + "extra_field_1":["extra", "value"], + "extra_field_2":{"extra":"value"}, + "extra_field_3":"extra value 3" + }" + """.trimIndent() val recreatedObject = createObjectFromJsonString(jsonString) { EmailGroup.parse(it) } assertEquals(sampleEmailGroup, recreatedObject) } diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/EmailRecipientTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/EmailRecipientTests.kt new file mode 100644 index 00000000..c2f2d36d --- /dev/null +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/EmailRecipientTests.kt @@ -0,0 +1,142 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + * + * Modifications Copyright OpenSearch Contributors. See + * GitHub history for details. + */ + +/* + * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + * + */ +package org.opensearch.commons.notifications.model + +import com.fasterxml.jackson.core.JsonParseException +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.assertDoesNotThrow +import org.junit.jupiter.api.assertThrows +import org.opensearch.commons.utils.createObjectFromJsonString +import org.opensearch.commons.utils.getJsonString +import org.opensearch.commons.utils.recreateObject + +internal class EmailRecipientTests { + + private fun checkValidEmailAddress(emailAddress: String) { + assertDoesNotThrow("should accept $emailAddress") { + EmailRecipient(emailAddress) + } + } + + private fun checkInvalidEmailAddress(emailAddress: String) { + assertThrows("Should throw an Exception for invalid email $emailAddress") { + EmailRecipient(emailAddress) + } + } + + @Test + fun `EmailRecipient should accept valid email address`() { + checkValidEmailAddress("email1234@email.com") + checkValidEmailAddress("email+1234@email.com") + checkValidEmailAddress("email-1234@email.com") + checkValidEmailAddress("email_1234@email.com") + checkValidEmailAddress("email.1234@email.com") + checkValidEmailAddress("e.ma_il-1+2@test-email-domain.co.uk") + checkValidEmailAddress("email-.+_=#|@domain.com") + checkValidEmailAddress("e@mail.com") + } + + @Test + fun `EmailRecipient should throw exception for invalid email address`() { + checkInvalidEmailAddress("email") + checkInvalidEmailAddress("email@") + checkInvalidEmailAddress("email@1234@email.com") + checkInvalidEmailAddress(".email@email.com") + checkInvalidEmailAddress("email.@email.com") + checkInvalidEmailAddress("email..1234@email.com") + checkInvalidEmailAddress("email@email..com") + checkInvalidEmailAddress("email@.com") + checkInvalidEmailAddress("email@email.com.") + checkInvalidEmailAddress("email@.email.com") + checkInvalidEmailAddress("email@email.com-") + checkInvalidEmailAddress("email@email_domain.com") + } + + @Test + fun `EmailRecipient serialize and deserialize transport object should be equal`() { + val sampleEmailRecipient = EmailRecipient("email1@email.com") + val recreatedObject = recreateObject(sampleEmailRecipient) { EmailRecipient(it) } + assertEquals(sampleEmailRecipient, recreatedObject) + } + + @Test + fun `EmailRecipient serialize and deserialize using json object should be equal`() { + val sampleEmailRecipient = EmailRecipient("email1@email.com") + val jsonString = getJsonString(sampleEmailRecipient) + val recreatedObject = createObjectFromJsonString(jsonString) { EmailRecipient.parse(it) } + assertEquals(sampleEmailRecipient, recreatedObject) + } + + @Test + fun `EmailRecipient should deserialize json object using parser`() { + val sampleEmailRecipient = EmailRecipient("email1@email.com") + val jsonString = """ + { + "recipient": "${sampleEmailRecipient.recipient}" + }" + """.trimIndent() + val recreatedObject = createObjectFromJsonString(jsonString) { EmailRecipient.parse(it) } + assertEquals(sampleEmailRecipient, recreatedObject) + } + + @Test + fun `EmailRecipient should throw exception when invalid json object is passed`() { + val jsonString = "sample message" + assertThrows { + createObjectFromJsonString(jsonString) { EmailRecipient.parse(it) } + } + } + + @Test + fun `EmailRecipient should throw exception when recipients is replaced with recipients2 in json object`() { + val sampleEmailRecipient = EmailRecipient("email1@email.com") + val jsonString = """ + { + "recipient2": "${sampleEmailRecipient.recipient}" + }" + """.trimIndent() + assertThrows { + createObjectFromJsonString(jsonString) { EmailRecipient.parse(it) } + } + } + + @Test + fun `EmailRecipient should safely ignore extra field in json object`() { + val sampleEmailRecipient = EmailRecipient("email@email.com") + val jsonString = """ + { + "recipient": "${sampleEmailRecipient.recipient}", + "extra_field_1":["extra", "value"], + "extra_field_2":{"extra":"value"}, + "extra_field_3":"extra value 3" + }" + """.trimIndent() + val recreatedObject = createObjectFromJsonString(jsonString) { EmailRecipient.parse(it) } + assertEquals(sampleEmailRecipient, recreatedObject) + } +} diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/EmailTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/EmailTests.kt index 6590f08e..8e4772f5 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/EmailTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/EmailTests.kt @@ -29,7 +29,6 @@ package org.opensearch.commons.notifications.model import com.fasterxml.jackson.core.JsonParseException import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Test -import org.junit.jupiter.api.assertDoesNotThrow import org.junit.jupiter.api.assertThrows import org.opensearch.commons.utils.createObjectFromJsonString import org.opensearch.commons.utils.getJsonString @@ -37,51 +36,14 @@ import org.opensearch.commons.utils.recreateObject internal class EmailTests { - private fun checkValidEmailAddress(emailAddress: String) { - assertDoesNotThrow("should accept $emailAddress") { - Email("sampleId", listOf(emailAddress), listOf()) - } - } - - private fun checkInvalidEmailAddress(emailAddress: String) { - assertThrows("Should throw an Exception for invalid email $emailAddress") { - Email("sampleId", listOf(emailAddress), listOf()) - } - } - - @Test - fun `Email should accept valid email address`() { - checkValidEmailAddress("email1234@email.com") - checkValidEmailAddress("email+1234@email.com") - checkValidEmailAddress("email-1234@email.com") - checkValidEmailAddress("email_1234@email.com") - checkValidEmailAddress("email.1234@email.com") - checkValidEmailAddress("e.ma_il-1+2@test-email-domain.co.uk") - checkValidEmailAddress("email-.+_=#|@domain.com") - checkValidEmailAddress("e@mail.com") - } - - @Test - fun `Email should throw exception for invalid email address`() { - checkInvalidEmailAddress("email") - checkInvalidEmailAddress("email@") - checkInvalidEmailAddress("email@1234@email.com") - checkInvalidEmailAddress(".email@email.com") - checkInvalidEmailAddress("email.@email.com") - checkInvalidEmailAddress("email..1234@email.com") - checkInvalidEmailAddress("email@email..com") - checkInvalidEmailAddress("email@.com") - checkInvalidEmailAddress("email@email.com.") - checkInvalidEmailAddress("email@.email.com") - checkInvalidEmailAddress("email@email.com-") - checkInvalidEmailAddress("email@email_domain.com") - } - @Test fun `Email serialize and deserialize transport object should be equal`() { val sampleEmail = Email( "sampleAccountId", - listOf("email1@email.com", "email2@email.com"), + listOf( + EmailRecipient("email1@email.com"), + EmailRecipient("email2@email.com") + ), listOf("sample_group_id_1", "sample_group_id_2") ) val recreatedObject = recreateObject(sampleEmail) { Email(it) } @@ -92,7 +54,10 @@ internal class EmailTests { fun `Email serialize and deserialize using json object should be equal`() { val sampleEmail = Email( "sampleAccountId", - listOf("email1@email.com", "email2@email.com"), + listOf( + EmailRecipient("email1@email.com"), + EmailRecipient("email2@email.com") + ), listOf("sample_group_id_1", "sample_group_id_2") ) val jsonString = getJsonString(sampleEmail) @@ -104,15 +69,18 @@ internal class EmailTests { fun `Email should deserialize json object using parser`() { val sampleEmail = Email( "sampleAccountId", - listOf("email1@email.com", "email2@email.com"), + listOf( + EmailRecipient("email1@email.com"), + EmailRecipient("email2@email.com") + ), listOf("sample_group_id_1", "sample_group_id_2") ) val jsonString = """ { "email_account_id":"${sampleEmail.emailAccountID}", "recipient_list":[ - "${sampleEmail.recipients[0]}", - "${sampleEmail.recipients[1]}" + {"recipient":"${sampleEmail.recipients[0].recipient}"}, + {"recipient":"${sampleEmail.recipients[1].recipient}"} ], "email_group_id_list":[ "${sampleEmail.emailGroupIds[0]}", @@ -136,15 +104,18 @@ internal class EmailTests { fun `Email should throw exception when emailAccountID is replaced with emailAccountID2 in json object`() { val sampleEmail = Email( "sampleAccountId", - listOf("email1@email.com", "email2@email.com"), + listOf( + EmailRecipient("email1@email.com"), + EmailRecipient("email2@email.com") + ), listOf("sample_group_id_1", "sample_group_id_2") ) val jsonString = """ { "email_account_id2":"${sampleEmail.emailAccountID}", "recipient_list":[ - "${sampleEmail.recipients[0]}", - "${sampleEmail.recipients[1]}" + {"recipient":"${sampleEmail.recipients[0]}"}, + {"recipient":"${sampleEmail.recipients[1]}"} ], "email_group_id_list":[ "${sampleEmail.emailGroupIds[0]}", diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationConfigTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationConfigTests.kt index c7126ab0..0a96c8ed 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationConfigTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationConfigTests.kt @@ -126,7 +126,7 @@ internal class NotificationConfigTests { @Test fun `Config serialize and deserialize with email object should be equal`() { - val sampleEmail = Email("id_1234567890", listOf("email@domain.com"), listOf("groupId")) + val sampleEmail = Email("id_1234567890", listOf(EmailRecipient("email@domain.com")), listOf("groupId")) val sampleConfig = NotificationConfig( "name", "description", @@ -140,7 +140,7 @@ internal class NotificationConfigTests { @Test fun `Config serialize and deserialize with json email object should be equal`() { - val sampleEmail = Email("id_1234567890", listOf("email@domain.com"), listOf("groupId")) + val sampleEmail = Email("id_1234567890", listOf(EmailRecipient("email@domain.com")), listOf("groupId")) val sampleConfig = NotificationConfig( "name", "description", @@ -184,7 +184,7 @@ internal class NotificationConfigTests { @Test fun `Config serialize and deserialize with json emailGroup object should be equal`() { - val sampleEmailGroup = EmailGroup(listOf("email@domain.com")) + val sampleEmailGroup = EmailGroup(listOf(EmailRecipient("email@domain.com"))) val sampleConfig = NotificationConfig( "name", "description", @@ -199,7 +199,7 @@ internal class NotificationConfigTests { @Test fun `Config serialize and deserialize with emailGroup object should be equal`() { - val sampleEmailGroup = EmailGroup(listOf("email@domain.com")) + val sampleEmailGroup = EmailGroup(listOf(EmailRecipient("email@domain.com"))) val sampleConfig = NotificationConfig( "name", "description", diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/config/ConfigPropertiesTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/config/ConfigPropertiesTests.kt index 0217c53f..80a20b88 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/config/ConfigPropertiesTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/config/ConfigPropertiesTests.kt @@ -5,6 +5,7 @@ import org.opensearch.commons.notifications.model.Chime import org.opensearch.commons.notifications.model.ConfigType import org.opensearch.commons.notifications.model.Email import org.opensearch.commons.notifications.model.EmailGroup +import org.opensearch.commons.notifications.model.EmailRecipient import org.opensearch.commons.notifications.model.MethodType import org.opensearch.commons.notifications.model.Slack import org.opensearch.commons.notifications.model.SmtpAccount @@ -72,7 +73,7 @@ internal class ConfigPropertiesTests { @Test fun `Validate config data parse EmailGroup`() { - val sampleEmailGroup = EmailGroup(listOf("email1@email.com", "email2@email.com")) + val sampleEmailGroup = EmailGroup(listOf(EmailRecipient("email1@email.com"), EmailRecipient("email2@email.com"))) val jsonString = getJsonString(sampleEmailGroup) val recreatedObject = createObjectFromJsonString(jsonString) { createConfigData(ConfigType.EMAIL_GROUP, it) } assertEquals(sampleEmailGroup, recreatedObject) From ccbaef74a6bd0b0ff393fd40f84c6a861589a5c9 Mon Sep 17 00:00:00 2001 From: Mohammad Qureshi <47198598+qreshi@users.noreply.github.com> Date: Tue, 2 Nov 2021 15:13:11 -0700 Subject: [PATCH 090/140] Update copyright notice (#90) Signed-off-by: Mohammad Qureshi Signed-off-by: Zelin Hao --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b2778b5d..fc95f76e 100644 --- a/README.md +++ b/README.md @@ -44,4 +44,4 @@ This project is licensed under the [Apache v2.0 License](LICENSE.txt). ## Copyright -Copyright 2020-2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. +Copyright OpenSearch Contributors. See [NOTICE](NOTICE.txt) for details. From b39f8e15e4db1d2e913f808c0ccd48a7faf8a8f5 Mon Sep 17 00:00:00 2001 From: Marc Handalian Date: Thu, 4 Nov 2021 07:16:42 -0700 Subject: [PATCH 091/140] Update maven publication to include cksums. (#91) This change adds a local staging repo task that will include cksums. It will also update build.sh to use this new task and copy the contents of the staging repo to the output directory. The maven publish plugin will not include these cksums when publishing to maven local but will when published to a separate folder. Signed-off-by: Marc Handalian Signed-off-by: Zelin Hao --- build.gradle | 16 ++++++---------- scripts/build.sh | 3 ++- 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/build.gradle b/build.gradle index 92f71cc5..92e442ca 100644 --- a/build.gradle +++ b/build.gradle @@ -157,17 +157,13 @@ task javadocJar(type: Jar) { classifier = 'javadoc' from javadoc.destinationDir } - -tasks.withType(Jar) { task -> - task.doLast { - ant.checksum algorithm: 'md5', file: it.archivePath - ant.checksum algorithm: 'sha1', file: it.archivePath - ant.checksum algorithm: 'sha-256', file: it.archivePath, fileext: '.sha256' - ant.checksum algorithm: 'sha-512', file: it.archivePath, fileext: '.sha512' - } -} - publishing { + repositories { + maven { + name = 'staging' + url = "${rootProject.buildDir}/local-staging-repo" + } + } publications { shadow(MavenPublication) { project.shadow.component(it) diff --git a/scripts/build.sh b/scripts/build.sh index fdc9be57..891e27fc 100755 --- a/scripts/build.sh +++ b/scripts/build.sh @@ -57,5 +57,6 @@ fi ./gradlew build -Dopensearch.version=$VERSION -Dbuild.snapshot=$SNAPSHOT ./gradlew publishShadowPublicationToMavenLocal -Dopensearch.version=$VERSION -Dbuild.snapshot=$SNAPSHOT +./gradlew publishShadowPublicationToStagingRepository -Dopensearch.version=$VERSION -Dbuild.snapshot=$SNAPSHOT mkdir -p $OUTPUT/maven/org/opensearch -cp -r ./build/libs $OUTPUT/maven/org/opensearch/common-utils +cp -r ./build/local-staging-repo/org/opensearch/common-utils $OUTPUT/maven/org/opensearch/common-utils From d3366bdb5cdaaed26998142a319df41bf47bf885 Mon Sep 17 00:00:00 2001 From: Ashish Agrawal Date: Fri, 5 Nov 2021 16:24:52 -0700 Subject: [PATCH 092/140] Add release notes for version 1.2.0.0 (#92) * Add release notes for version 1.2.0.0 Signed-off-by: Ashish Agrawal Signed-off-by: Zelin Hao --- ...pensearch-common-utils.release-notes-1.2.0.0.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 release-notes/opensearch-common-utils.release-notes-1.2.0.0.md diff --git a/release-notes/opensearch-common-utils.release-notes-1.2.0.0.md b/release-notes/opensearch-common-utils.release-notes-1.2.0.0.md new file mode 100644 index 00000000..afb92873 --- /dev/null +++ b/release-notes/opensearch-common-utils.release-notes-1.2.0.0.md @@ -0,0 +1,14 @@ +## Version 1.2.0.0 2021-11-05 + +Compatible with OpenSearch 1.2.0 + +### Infrastructure + + * Updates common-utils version to 1.2 ([#77](https://github.com/opensearch-project/common-utils/pull/77)) + * Update maven publication to include cksums. ([#91](https://github.com/opensearch-project/common-utils/pull/91)) + +### Documentation + + * Add themed logo to README ([#41](https://github.com/opensearch-project/common-utils/pull/41)) + * Update copyright notice ([#90](https://github.com/opensearch-project/common-utils/pull/90)) + * Add release notes for version 1.2.0.0 ([#92](https://github.com/opensearch-project/common-utils/pull/92)) \ No newline at end of file From ca28652edd25c08a41df6de055e18852dc79a1bc Mon Sep 17 00:00:00 2001 From: Ashish Agrawal Date: Mon, 8 Nov 2021 16:06:09 -0800 Subject: [PATCH 093/140] Fix copyright notice and add DCO check workflow (#94) Signed-off-by: Ashish Agrawal Signed-off-by: Zelin Hao --- .github/workflows/dco.yml | 18 ++++++++++++++ CONTRIBUTING.md | 49 ++++++++++++++++++++++++++++++++++++++- NOTICE | 4 ++-- 3 files changed, 68 insertions(+), 3 deletions(-) create mode 100644 .github/workflows/dco.yml diff --git a/.github/workflows/dco.yml b/.github/workflows/dco.yml new file mode 100644 index 00000000..53ed5304 --- /dev/null +++ b/.github/workflows/dco.yml @@ -0,0 +1,18 @@ +name: Developer Certificate of Origin Check + +on: [pull_request] + +jobs: + check: + runs-on: ubuntu-latest + + steps: + - name: Get PR Commits + id: 'get-pr-commits' + uses: tim-actions/get-pr-commits@v1.1.0 + with: + token: ${{ secrets.GITHUB_TOKEN }} + - name: DCO Check + uses: tim-actions/dco@v1.1.0 + with: + commits: ${{ steps.get-pr-commits.outputs.commits }} \ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c970f9d3..c25787ad 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,4 +1,51 @@ ## Contributing to this Project OpenSearch is a community project that is built and maintained by people just like **you**. -[This document](https://github.com/opensearch-project/.github/blob/main/CONTRIBUTING.md) explains how you can contribute to this and related projects. \ No newline at end of file +[This document](https://github.com/opensearch-project/.github/blob/main/CONTRIBUTING.md) explains how you can contribute to this and related projects. + +## Developer Certificate of Origin + +OpenSearch is an open source product released under the Apache 2.0 license (see either [the Apache site](https://www.apache.org/licenses/LICENSE-2.0) or the [LICENSE.txt file](LICENSE.txt)). The Apache 2.0 license allows you to freely use, modify, distribute, and sell your own products that include Apache 2.0 licensed software. + +We respect intellectual property rights of others and we want to make sure all incoming contributions are correctly attributed and licensed. A Developer Certificate of Origin (DCO) is a lightweight mechanism to do that. + +The DCO is a declaration attached to every contribution made by every developer. In the commit message of the contribution, the developer simply adds a `Signed-off-by` statement and thereby agrees to the DCO, which you can find below or at [DeveloperCertificate.org](http://developercertificate.org/). + +``` +Developer's Certificate of Origin 1.1 + +By making a contribution to this project, I certify that: + +(a) The contribution was created in whole or in part by me and I + have the right to submit it under the open source license + indicated in the file; or + +(b) The contribution is based upon previous work that, to the + best of my knowledge, is covered under an appropriate open + source license and I have the right under that license to + submit that work with modifications, whether created in whole + or in part by me, under the same open source license (unless + I am permitted to submit under a different license), as + Indicated in the file; or + +(c) The contribution was provided directly to me by some other + person who certified (a), (b) or (c) and I have not modified + it. + +(d) I understand and agree that this project and the contribution + are public and that a record of the contribution (including + all personal information I submit with it, including my + sign-off) is maintained indefinitely and may be redistributed + consistent with this project or the open source license(s) + involved. + ``` + +We require that every contribution to OpenSearch is signed with a Developer Certificate of Origin. Additionally, please use your real name. We do not accept anonymous contributors nor those utilizing pseudonyms. + +Each commit must include a DCO which looks like this + +``` +Signed-off-by: Jane Smith +``` + +You may type this line on your own when writing your commit messages. However, if your user.name and user.email are set in your git configs, you can use `-s` or `– – signoff` to add the `Signed-off-by` line to the end of the commit message. \ No newline at end of file diff --git a/NOTICE b/NOTICE index be83767d..6c7dc983 100644 --- a/NOTICE +++ b/NOTICE @@ -1,5 +1,5 @@ -OpenSearch -Copyright 2021 OpenSearch Contributors +OpenSearch (https://opensearch.org/) +Copyright OpenSearch Contributors This product includes software developed by Elasticsearch (http://www.elastic.co). From 6c1f2a9c316bb2dd3e271494f5deaa8a777812ed Mon Sep 17 00:00:00 2001 From: Marc Handalian Date: Fri, 12 Nov 2021 06:29:39 -0800 Subject: [PATCH 094/140] Update build.sh script to include optional platform param. (#95) Signed-off-by: Marc Handalian Signed-off-by: Zelin Hao --- scripts/build.sh | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/scripts/build.sh b/scripts/build.sh index 891e27fc..f68dc52e 100755 --- a/scripts/build.sh +++ b/scripts/build.sh @@ -11,12 +11,13 @@ function usage() { echo "Arguments:" echo -e "-v VERSION\t[Required] OpenSearch version." echo -e "-s SNAPSHOT\t[Optional] Build a snapshot, default is 'false'." + echo -e "-p PLATFORM\t[Optional] Platform, ignored." echo -e "-a ARCHITECTURE\t[Optional] Build architecture, ignored." echo -e "-o OUTPUT\t[Optional] Output path, default is 'artifacts'." echo -e "-h help" } -while getopts ":h:v:s:o:a:" arg; do +while getopts ":h:v:s:o:p:a:" arg; do case $arg in h) usage @@ -31,6 +32,9 @@ while getopts ":h:v:s:o:a:" arg; do o) OUTPUT=$OPTARG ;; + p) + PLATFORM=$OPTARG + ;; a) ARCHITECTURE=$OPTARG ;; From 22337869886331c6d39bf3113050b48b38556108 Mon Sep 17 00:00:00 2001 From: Ryan Bogan <10944539+ryanbogan@users.noreply.github.com> Date: Fri, 12 Nov 2021 17:37:12 -0500 Subject: [PATCH 095/140] Add codeowners support for repo (#96) Signed-off-by: Ryan Bogan Signed-off-by: Zelin Hao --- .github/CODEOWNERS | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 .github/CODEOWNERS diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 00000000..b57ed5c8 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,2 @@ +# This should match the owning team set up in https://github.com/orgs/opensearch-project/teams +* @opensearch-project/common-utils \ No newline at end of file From 0ecb54b7f04f5b5ff35546665a16d4a263b30772 Mon Sep 17 00:00:00 2001 From: Ashish Agrawal Date: Wed, 1 Dec 2021 16:48:53 -0800 Subject: [PATCH 096/140] Bump version to 1.3 (#99) Signed-off-by: Ashish Agrawal Signed-off-by: Zelin Hao --- .github/workflows/ci.yml | 4 ++-- build.gradle | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 52eea2f1..badeafda 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -28,11 +28,11 @@ jobs: # common-utils - name: Build and Test run: | - ./gradlew build -Dopensearch.version=1.2.0-SNAPSHOT + ./gradlew build -Dopensearch.version=1.3.0-SNAPSHOT - name: Publish to Maven Local run: | - ./gradlew publishToMavenLocal -Dopensearch.version=1.2.0-SNAPSHOT + ./gradlew publishToMavenLocal -Dopensearch.version=1.3.0-SNAPSHOT - name: Upload Coverage Report uses: codecov/codecov-action@v1 diff --git a/build.gradle b/build.gradle index 92e442ca..9b97f0ac 100644 --- a/build.gradle +++ b/build.gradle @@ -12,7 +12,7 @@ buildscript { ext { opensearch_group = "org.opensearch" - opensearch_version = System.getProperty("opensearch.version", "1.2.0-SNAPSHOT") + opensearch_version = System.getProperty("opensearch.version", "1.3.0-SNAPSHOT") kotlin_version = System.getProperty("kotlin.version", "1.4.32") } From c87ee436357159725753f0a045c24d8b78711c95 Mon Sep 17 00:00:00 2001 From: "Daniel Doubrovkine (dB.)" Date: Tue, 4 Jan 2022 19:26:01 +0000 Subject: [PATCH 097/140] Auto-increment version on new release tags. (#106) Signed-off-by: dblock Signed-off-by: Zelin Hao --- .github/workflows/ci.yml | 4 ++-- .github/workflows/version.yml | 42 +++++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 2 deletions(-) create mode 100644 .github/workflows/version.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index badeafda..c35e0c0a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -28,11 +28,11 @@ jobs: # common-utils - name: Build and Test run: | - ./gradlew build -Dopensearch.version=1.3.0-SNAPSHOT + ./gradlew build - name: Publish to Maven Local run: | - ./gradlew publishToMavenLocal -Dopensearch.version=1.3.0-SNAPSHOT + ./gradlew publishToMavenLocal - name: Upload Coverage Report uses: codecov/codecov-action@v1 diff --git a/.github/workflows/version.yml b/.github/workflows/version.yml new file mode 100644 index 00000000..196a690d --- /dev/null +++ b/.github/workflows/version.yml @@ -0,0 +1,42 @@ +name: Increment Version + +on: + push: + tags: + - '*.*.*.*' + +jobs: + build: + runs-on: ubuntu-latest + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + steps: + - uses: actions/checkout@v2 + - name: Fetch Tag and Version Information + run: | + TAG=$(echo "${GITHUB_REF#refs/*/}") + CURRENT_VERSION_ARRAY=($(echo "$TAG" | tr . '\n')) + BASE=$(IFS=. ; echo "${CURRENT_VERSION_ARRAY[*]:0:2}") + CURRENT_VERSION=$(IFS=. ; echo "${CURRENT_VERSION_ARRAY[*]:0:3}") + CURRENT_VERSION_ARRAY[2]=$((CURRENT_VERSION_ARRAY[2]+1)) + NEXT_VERSION=$(IFS=. ; echo "${CURRENT_VERSION_ARRAY[*]:0:3}") + echo "TAG=$TAG" >> $GITHUB_ENV + echo "BASE=$BASE" >> $GITHUB_ENV + echo "CURRENT_VERSION=$CURRENT_VERSION" >> $GITHUB_ENV + echo "NEXT_VERSION=$NEXT_VERSION" >> $GITHUB_ENV + - uses: actions/checkout@v2 + with: + ref: ${{ env.BASE }} + - name: Increment Version + run: | + echo Incrementing $CURRENT_VERSION to $NEXT_VERSION + sed -i "s/$CURRENT_VERSION-SNAPSHOT/$NEXT_VERSION-SNAPSHOT/g" build.gradle + - name: Create Pull Request + uses: peter-evans/create-pull-request@v3 + with: + base: ${{ env.BASE }} + commit-message: Incremented version to ${{ env.NEXT_VERSION }} + delete-branch: true + title: '[AUTO] Incremented version to ${{ env.NEXT_VERSION }}.' + body: | + I've noticed that a new tag ${{ env.TAG }} was pushed, and incremented the version from ${{ env.CURRENT_VERSION }} to ${{ env.NEXT_VERSION }}. From 2d29b49f4c81d1dae3bb9ad748fb62b760088d4c Mon Sep 17 00:00:00 2001 From: Peter Nied Date: Thu, 17 Feb 2022 15:53:56 -0600 Subject: [PATCH 098/140] Remove jcenter repository (#115) Signed-off-by: Zelin Hao --- build.gradle | 1 - 1 file changed, 1 deletion(-) diff --git a/build.gradle b/build.gradle index 9b97f0ac..43974b0b 100644 --- a/build.gradle +++ b/build.gradle @@ -20,7 +20,6 @@ buildscript { mavenLocal() mavenCentral() maven { url "https://plugins.gradle.org/m2/" } - jcenter() maven { url "https://aws.oss.sonatype.org/content/repositories/snapshots" } } From c5476b66347f8ec227282456a7930e98c3833177 Mon Sep 17 00:00:00 2001 From: Vacha Shah Date: Fri, 18 Feb 2022 17:30:12 -0800 Subject: [PATCH 099/140] Using Github App token to trigger CI for version increment PRs (#116) Signed-off-by: Vacha Shah Signed-off-by: Zelin Hao --- .github/workflows/version.yml | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/.github/workflows/version.yml b/.github/workflows/version.yml index 196a690d..8ca31d8e 100644 --- a/.github/workflows/version.yml +++ b/.github/workflows/version.yml @@ -8,9 +8,15 @@ on: jobs: build: runs-on: ubuntu-latest - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} steps: + - name: GitHub App token + id: github_app_token + uses: tibdex/github-app-token@v1.5.0 + with: + app_id: ${{ secrets.APP_ID }} + private_key: ${{ secrets.APP_PRIVATE_KEY }} + installation_id: 22958780 + - uses: actions/checkout@v2 - name: Fetch Tag and Version Information run: | @@ -27,13 +33,17 @@ jobs: - uses: actions/checkout@v2 with: ref: ${{ env.BASE }} + token: ${{ steps.github_app_token.outputs.token }} + - name: Increment Version run: | echo Incrementing $CURRENT_VERSION to $NEXT_VERSION sed -i "s/$CURRENT_VERSION-SNAPSHOT/$NEXT_VERSION-SNAPSHOT/g" build.gradle + - name: Create Pull Request uses: peter-evans/create-pull-request@v3 with: + token: ${{ steps.github_app_token.outputs.token }} base: ${{ env.BASE }} commit-message: Incremented version to ${{ env.NEXT_VERSION }} delete-branch: true From 822e4fb5983be4917ac609917f5ca27ec5a2f56e Mon Sep 17 00:00:00 2001 From: Drew Baugher <46505179+dbbaughe@users.noreply.github.com> Date: Mon, 21 Feb 2022 11:08:03 -0800 Subject: [PATCH 100/140] Fixes copyright headers (#117) Signed-off-by: Drew Baugher <46505179+dbbaughe@users.noreply.github.com> Signed-off-by: Zelin Hao --- build.gradle | 8 +------ detekt.yml | 8 +------ settings.gradle | 8 +------ spotless.license.java | 23 +----------------- .../opensearch/commons/ConfigConstants.java | 23 +----------------- .../opensearch/commons/InjectSecurity.java | 23 +----------------- .../authuser/AuthUserRequestBuilder.java | 23 +----------------- .../org/opensearch/commons/authuser/User.java | 23 +----------------- .../message/LegacyBaseMessage.java | 23 +----------------- .../message/LegacyChimeMessage.java | 23 +----------------- .../message/LegacyCustomWebhookMessage.java | 23 +----------------- .../message/LegacyDestinationType.java | 23 +----------------- .../message/LegacySlackMessage.java | 23 +----------------- .../response/LegacyBaseResponse.java | 23 +----------------- .../response/LegacyDestinationResponse.java | 23 +----------------- .../commons/rest/SecureRestClientBuilder.java | 23 +----------------- .../opensearch/commons/rest/TrustStore.java | 23 +----------------- .../NotificationsPluginInterface.kt | 24 +------------------ .../notifications/action/BaseResponse.kt | 24 +------------------ .../action/CreateNotificationConfigRequest.kt | 24 +------------------ .../CreateNotificationConfigResponse.kt | 24 +------------------ .../action/DeleteNotificationConfigRequest.kt | 24 +------------------ .../DeleteNotificationConfigResponse.kt | 24 +------------------ .../action/GetFeatureChannelListRequest.kt | 24 +------------------ .../action/GetFeatureChannelListResponse.kt | 24 +------------------ .../action/GetNotificationConfigRequest.kt | 24 +------------------ .../action/GetNotificationConfigResponse.kt | 24 +------------------ .../action/GetNotificationEventRequest.kt | 24 +------------------ .../action/GetNotificationEventResponse.kt | 24 +------------------ .../action/GetPluginFeaturesRequest.kt | 24 +------------------ .../action/GetPluginFeaturesResponse.kt | 24 +------------------ .../LegacyPublishNotificationRequest.kt | 8 +------ .../LegacyPublishNotificationResponse.kt | 8 +------ .../action/NotificationsActions.kt | 24 +------------------ .../action/SendNotificationRequest.kt | 24 +------------------ .../action/SendNotificationResponse.kt | 24 +------------------ .../action/UpdateNotificationConfigRequest.kt | 24 +------------------ .../UpdateNotificationConfigResponse.kt | 24 +------------------ .../commons/notifications/model/Attachment.kt | 24 +------------------ .../notifications/model/BaseConfigData.kt | 24 +------------------ .../commons/notifications/model/BaseModel.kt | 24 +------------------ .../notifications/model/ChannelMessage.kt | 24 +------------------ .../commons/notifications/model/Chime.kt | 24 +------------------ .../commons/notifications/model/ConfigType.kt | 24 +------------------ .../notifications/model/DeliveryStatus.kt | 24 +------------------ .../commons/notifications/model/Email.kt | 24 +------------------ .../commons/notifications/model/EmailGroup.kt | 24 +------------------ .../notifications/model/EmailRecipient.kt | 24 +------------------ .../model/EmailRecipientStatus.kt | 24 +------------------ .../notifications/model/EventSource.kt | 24 +------------------ .../notifications/model/EventStatus.kt | 24 +------------------ .../notifications/model/FeatureChannel.kt | 24 +------------------ .../notifications/model/FeatureChannelList.kt | 24 +------------------ .../notifications/model/NotificationConfig.kt | 24 +------------------ .../model/NotificationConfigInfo.kt | 23 +----------------- .../model/NotificationConfigSearchResult.kt | 24 +------------------ .../notifications/model/NotificationEvent.kt | 24 +------------------ .../model/NotificationEventInfo.kt | 24 +------------------ .../model/NotificationEventSearchResult.kt | 24 +------------------ .../notifications/model/SearchResults.kt | 24 +------------------ .../commons/notifications/model/SesAccount.kt | 8 +------ .../notifications/model/SeverityType.kt | 24 +------------------ .../commons/notifications/model/Slack.kt | 24 +------------------ .../notifications/model/SmtpAccount.kt | 24 +------------------ .../commons/notifications/model/Sns.kt | 9 ++----- .../commons/notifications/model/Webhook.kt | 24 +------------------ .../commons/notifications/model/XParser.kt | 24 +------------------ .../model/config/ConfigDataProperties.kt | 24 +------------------ .../opensearch/commons/utils/EnumHelpers.kt | 24 +------------------ .../opensearch/commons/utils/EnumParser.kt | 24 +------------------ .../org/opensearch/commons/utils/Helpers.kt | 24 +------------------ .../commons/utils/OpenForTesting.kt | 24 +------------------ .../commons/utils/SecureClientWrapper.kt | 24 +------------------ .../commons/utils/TransportHelpers.kt | 24 +------------------ .../commons/utils/ValidationHelpers.kt | 24 +------------------ .../commons/utils/XContentHelpers.kt | 24 +------------------ .../commons/InjectSecurityTest.java | 23 +----------------- .../opensearch/commons/authuser/UserTest.java | 23 +----------------- .../message/LegacyChimeMessageTest.java | 23 +----------------- .../LegacyCustomWebhookMessageTest.java | 23 +----------------- .../message/LegacySlackMessageTest.java | 23 +----------------- .../LegacyDestinationResponseTest.java | 23 +----------------- .../commons/rest/IntegrationTests.java | 23 +----------------- .../rest/SecureRestClientBuilderTest.java | 23 +----------------- .../commons/rest/TrustStoreTest.java | 23 +----------------- .../NotificationsPluginInterfaceTests.kt | 9 ++----- .../CreateNotificationConfigRequestTests.kt | 24 +------------------ .../CreateNotificationConfigResponseTests.kt | 24 +------------------ .../DeleteNotificationConfigRequestTests.kt | 24 +------------------ .../DeleteNotificationConfigResponseTests.kt | 24 +------------------ .../GetFeatureChannelListRequestTests.kt | 24 +------------------ .../GetFeatureChannelListResponseTests.kt | 24 +------------------ .../GetNotificationConfigRequestTests.kt | 24 +------------------ .../GetNotificationConfigResponseTests.kt | 24 +------------------ .../GetNotificationEventRequestTests.kt | 24 +------------------ .../GetNotificationEventResponseTests.kt | 24 +------------------ .../action/GetPluginFeaturesRequestTests.kt | 24 +------------------ .../action/GetPluginFeaturesResponseTests.kt | 24 +------------------ .../LegacyPublishNotificationRequestTests.kt | 8 +------ .../LegacyPublishNotificationResponseTests.kt | 8 +------ .../action/SendNotificationRequestTests.kt | 24 +------------------ .../action/SendNotificationResponseTests.kt | 24 +------------------ .../UpdateNotificationConfigRequestTests.kt | 24 +------------------ .../UpdateNotificationConfigResponseTests.kt | 24 +------------------ .../notifications/model/AttachmentTests.kt | 24 +------------------ .../model/ChannelMessageTests.kt | 24 +------------------ .../commons/notifications/model/ChimeTests.kt | 24 +------------------ .../notifications/model/ConfigTypeTests.kt | 24 +------------------ .../model/DeliveryStatusTests.kt | 24 +------------------ .../notifications/model/EmailGroupTests.kt | 24 +------------------ .../model/EmailRecipientStatusTests.kt | 24 +------------------ .../model/EmailRecipientTests.kt | 24 +------------------ .../commons/notifications/model/EmailTests.kt | 24 +------------------ .../notifications/model/EventSourceTests.kt | 24 +------------------ .../notifications/model/EventStatusTests.kt | 24 +------------------ .../model/FeatureChannelListTests.kt | 24 +------------------ .../model/FeatureChannelTests.kt | 24 +------------------ .../model/FilterConfigListTests.kt | 24 +------------------ .../notifications/model/FilterConfigTests.kt | 24 +------------------ .../notifications/model/MethodTypeTests.kt | 24 +------------------ .../model/NotificationConfigInfoTests.kt | 24 +------------------ .../NotificationConfigSearchResultsTests.kt | 24 +------------------ .../model/NotificationConfigTests.kt | 24 +------------------ .../model/NotificationEventInfoTests.kt | 24 +------------------ .../NotificationEventSearchResultTests.kt | 24 +------------------ .../model/NotificationEventTests.kt | 24 +------------------ .../notifications/model/SesAccountTests.kt | 8 +------ .../notifications/model/SeverityTypeTests.kt | 24 +------------------ .../commons/notifications/model/SlackTests.kt | 24 +------------------ .../notifications/model/SmtpAccountTests.kt | 24 +------------------ .../commons/notifications/model/SnsTests.kt | 8 +------ .../notifications/model/WebhookTests.kt | 24 +------------------ .../opensearch/commons/utils/TestHelpers.kt | 24 +------------------ 133 files changed, 135 insertions(+), 2843 deletions(-) diff --git a/build.gradle b/build.gradle index 43974b0b..07768d30 100644 --- a/build.gradle +++ b/build.gradle @@ -1,12 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. */ buildscript { diff --git a/detekt.yml b/detekt.yml index 34ed3c1e..251da688 100644 --- a/detekt.yml +++ b/detekt.yml @@ -1,14 +1,8 @@ --- # +# Copyright OpenSearch Contributors # SPDX-License-Identifier: Apache-2.0 # -# The OpenSearch Contributors require contributions made to -# this file be licensed under the Apache-2.0 license or a -# compatible open source license. -# -# Modifications Copyright OpenSearch Contributors. See -# GitHub history for details. -# style: ForbiddenComment: diff --git a/settings.gradle b/settings.gradle index 7fa821ef..59d3dd1c 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,12 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. */ rootProject.name = 'common-utils' \ No newline at end of file diff --git a/spotless.license.java b/spotless.license.java index 01b9ea6c..9e182dcd 100644 --- a/spotless.license.java +++ b/spotless.license.java @@ -1,26 +1,5 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. */ diff --git a/src/main/java/org/opensearch/commons/ConfigConstants.java b/src/main/java/org/opensearch/commons/ConfigConstants.java index d7516dbc..6fc6e362 100644 --- a/src/main/java/org/opensearch/commons/ConfigConstants.java +++ b/src/main/java/org/opensearch/commons/ConfigConstants.java @@ -1,27 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. */ package org.opensearch.commons; diff --git a/src/main/java/org/opensearch/commons/InjectSecurity.java b/src/main/java/org/opensearch/commons/InjectSecurity.java index 2240ab60..f2644c29 100644 --- a/src/main/java/org/opensearch/commons/InjectSecurity.java +++ b/src/main/java/org/opensearch/commons/InjectSecurity.java @@ -1,27 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. */ package org.opensearch.commons; diff --git a/src/main/java/org/opensearch/commons/authuser/AuthUserRequestBuilder.java b/src/main/java/org/opensearch/commons/authuser/AuthUserRequestBuilder.java index c4b32e5f..32602744 100644 --- a/src/main/java/org/opensearch/commons/authuser/AuthUserRequestBuilder.java +++ b/src/main/java/org/opensearch/commons/authuser/AuthUserRequestBuilder.java @@ -1,27 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. */ package org.opensearch.commons.authuser; diff --git a/src/main/java/org/opensearch/commons/authuser/User.java b/src/main/java/org/opensearch/commons/authuser/User.java index 017405e9..f698d36b 100644 --- a/src/main/java/org/opensearch/commons/authuser/User.java +++ b/src/main/java/org/opensearch/commons/authuser/User.java @@ -1,27 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. */ package org.opensearch.commons.authuser; diff --git a/src/main/java/org/opensearch/commons/destination/message/LegacyBaseMessage.java b/src/main/java/org/opensearch/commons/destination/message/LegacyBaseMessage.java index b5122f31..96bd06ba 100644 --- a/src/main/java/org/opensearch/commons/destination/message/LegacyBaseMessage.java +++ b/src/main/java/org/opensearch/commons/destination/message/LegacyBaseMessage.java @@ -1,27 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. */ package org.opensearch.commons.destination.message; diff --git a/src/main/java/org/opensearch/commons/destination/message/LegacyChimeMessage.java b/src/main/java/org/opensearch/commons/destination/message/LegacyChimeMessage.java index b457d9aa..31b45d1f 100644 --- a/src/main/java/org/opensearch/commons/destination/message/LegacyChimeMessage.java +++ b/src/main/java/org/opensearch/commons/destination/message/LegacyChimeMessage.java @@ -1,27 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. */ package org.opensearch.commons.destination.message; diff --git a/src/main/java/org/opensearch/commons/destination/message/LegacyCustomWebhookMessage.java b/src/main/java/org/opensearch/commons/destination/message/LegacyCustomWebhookMessage.java index 9645b327..d0421ca9 100644 --- a/src/main/java/org/opensearch/commons/destination/message/LegacyCustomWebhookMessage.java +++ b/src/main/java/org/opensearch/commons/destination/message/LegacyCustomWebhookMessage.java @@ -1,27 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. */ package org.opensearch.commons.destination.message; diff --git a/src/main/java/org/opensearch/commons/destination/message/LegacyDestinationType.java b/src/main/java/org/opensearch/commons/destination/message/LegacyDestinationType.java index 85689510..ab50649b 100644 --- a/src/main/java/org/opensearch/commons/destination/message/LegacyDestinationType.java +++ b/src/main/java/org/opensearch/commons/destination/message/LegacyDestinationType.java @@ -1,27 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. */ package org.opensearch.commons.destination.message; diff --git a/src/main/java/org/opensearch/commons/destination/message/LegacySlackMessage.java b/src/main/java/org/opensearch/commons/destination/message/LegacySlackMessage.java index f426894a..02d30bb4 100644 --- a/src/main/java/org/opensearch/commons/destination/message/LegacySlackMessage.java +++ b/src/main/java/org/opensearch/commons/destination/message/LegacySlackMessage.java @@ -1,27 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. */ package org.opensearch.commons.destination.message; diff --git a/src/main/java/org/opensearch/commons/destination/response/LegacyBaseResponse.java b/src/main/java/org/opensearch/commons/destination/response/LegacyBaseResponse.java index bbdd8d70..4d34b67f 100644 --- a/src/main/java/org/opensearch/commons/destination/response/LegacyBaseResponse.java +++ b/src/main/java/org/opensearch/commons/destination/response/LegacyBaseResponse.java @@ -1,27 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. */ package org.opensearch.commons.destination.response; diff --git a/src/main/java/org/opensearch/commons/destination/response/LegacyDestinationResponse.java b/src/main/java/org/opensearch/commons/destination/response/LegacyDestinationResponse.java index bb927747..d55f5f3d 100644 --- a/src/main/java/org/opensearch/commons/destination/response/LegacyDestinationResponse.java +++ b/src/main/java/org/opensearch/commons/destination/response/LegacyDestinationResponse.java @@ -1,27 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. */ package org.opensearch.commons.destination.response; diff --git a/src/main/java/org/opensearch/commons/rest/SecureRestClientBuilder.java b/src/main/java/org/opensearch/commons/rest/SecureRestClientBuilder.java index 109809a8..96af1540 100644 --- a/src/main/java/org/opensearch/commons/rest/SecureRestClientBuilder.java +++ b/src/main/java/org/opensearch/commons/rest/SecureRestClientBuilder.java @@ -1,27 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. */ package org.opensearch.commons.rest; diff --git a/src/main/java/org/opensearch/commons/rest/TrustStore.java b/src/main/java/org/opensearch/commons/rest/TrustStore.java index 95f23796..52832b32 100644 --- a/src/main/java/org/opensearch/commons/rest/TrustStore.java +++ b/src/main/java/org/opensearch/commons/rest/TrustStore.java @@ -1,27 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. */ package org.opensearch.commons.rest; diff --git a/src/main/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterface.kt b/src/main/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterface.kt index c0646d2d..d406bb00 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterface.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterface.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications diff --git a/src/main/kotlin/org/opensearch/commons/notifications/action/BaseResponse.kt b/src/main/kotlin/org/opensearch/commons/notifications/action/BaseResponse.kt index 4bfa2271..e0659e8f 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/action/BaseResponse.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/action/BaseResponse.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.action diff --git a/src/main/kotlin/org/opensearch/commons/notifications/action/CreateNotificationConfigRequest.kt b/src/main/kotlin/org/opensearch/commons/notifications/action/CreateNotificationConfigRequest.kt index e62e92dd..dfbd1b95 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/action/CreateNotificationConfigRequest.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/action/CreateNotificationConfigRequest.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.action diff --git a/src/main/kotlin/org/opensearch/commons/notifications/action/CreateNotificationConfigResponse.kt b/src/main/kotlin/org/opensearch/commons/notifications/action/CreateNotificationConfigResponse.kt index 742e7be5..e8bce5af 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/action/CreateNotificationConfigResponse.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/action/CreateNotificationConfigResponse.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.action diff --git a/src/main/kotlin/org/opensearch/commons/notifications/action/DeleteNotificationConfigRequest.kt b/src/main/kotlin/org/opensearch/commons/notifications/action/DeleteNotificationConfigRequest.kt index 3699369f..1bcd355a 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/action/DeleteNotificationConfigRequest.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/action/DeleteNotificationConfigRequest.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.action diff --git a/src/main/kotlin/org/opensearch/commons/notifications/action/DeleteNotificationConfigResponse.kt b/src/main/kotlin/org/opensearch/commons/notifications/action/DeleteNotificationConfigResponse.kt index e701daa2..efb68005 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/action/DeleteNotificationConfigResponse.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/action/DeleteNotificationConfigResponse.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.action diff --git a/src/main/kotlin/org/opensearch/commons/notifications/action/GetFeatureChannelListRequest.kt b/src/main/kotlin/org/opensearch/commons/notifications/action/GetFeatureChannelListRequest.kt index ba6e3b19..901b4040 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/action/GetFeatureChannelListRequest.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/action/GetFeatureChannelListRequest.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.action diff --git a/src/main/kotlin/org/opensearch/commons/notifications/action/GetFeatureChannelListResponse.kt b/src/main/kotlin/org/opensearch/commons/notifications/action/GetFeatureChannelListResponse.kt index 455109fc..79bf4435 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/action/GetFeatureChannelListResponse.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/action/GetFeatureChannelListResponse.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.action diff --git a/src/main/kotlin/org/opensearch/commons/notifications/action/GetNotificationConfigRequest.kt b/src/main/kotlin/org/opensearch/commons/notifications/action/GetNotificationConfigRequest.kt index a410fe7e..a78d0d51 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/action/GetNotificationConfigRequest.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/action/GetNotificationConfigRequest.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.action diff --git a/src/main/kotlin/org/opensearch/commons/notifications/action/GetNotificationConfigResponse.kt b/src/main/kotlin/org/opensearch/commons/notifications/action/GetNotificationConfigResponse.kt index a810759b..1825ccca 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/action/GetNotificationConfigResponse.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/action/GetNotificationConfigResponse.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.action diff --git a/src/main/kotlin/org/opensearch/commons/notifications/action/GetNotificationEventRequest.kt b/src/main/kotlin/org/opensearch/commons/notifications/action/GetNotificationEventRequest.kt index 27e20554..66bfba6a 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/action/GetNotificationEventRequest.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/action/GetNotificationEventRequest.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.action diff --git a/src/main/kotlin/org/opensearch/commons/notifications/action/GetNotificationEventResponse.kt b/src/main/kotlin/org/opensearch/commons/notifications/action/GetNotificationEventResponse.kt index 176d95ea..c512aa48 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/action/GetNotificationEventResponse.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/action/GetNotificationEventResponse.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.action diff --git a/src/main/kotlin/org/opensearch/commons/notifications/action/GetPluginFeaturesRequest.kt b/src/main/kotlin/org/opensearch/commons/notifications/action/GetPluginFeaturesRequest.kt index 8b9b81b4..9437f376 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/action/GetPluginFeaturesRequest.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/action/GetPluginFeaturesRequest.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.action diff --git a/src/main/kotlin/org/opensearch/commons/notifications/action/GetPluginFeaturesResponse.kt b/src/main/kotlin/org/opensearch/commons/notifications/action/GetPluginFeaturesResponse.kt index dde25709..1e6fa2b9 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/action/GetPluginFeaturesResponse.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/action/GetPluginFeaturesResponse.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.action diff --git a/src/main/kotlin/org/opensearch/commons/notifications/action/LegacyPublishNotificationRequest.kt b/src/main/kotlin/org/opensearch/commons/notifications/action/LegacyPublishNotificationRequest.kt index e5807102..eb5080cf 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/action/LegacyPublishNotificationRequest.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/action/LegacyPublishNotificationRequest.kt @@ -1,12 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. */ package org.opensearch.commons.notifications.action diff --git a/src/main/kotlin/org/opensearch/commons/notifications/action/LegacyPublishNotificationResponse.kt b/src/main/kotlin/org/opensearch/commons/notifications/action/LegacyPublishNotificationResponse.kt index 60f68e71..f7311da2 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/action/LegacyPublishNotificationResponse.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/action/LegacyPublishNotificationResponse.kt @@ -1,12 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. */ package org.opensearch.commons.notifications.action diff --git a/src/main/kotlin/org/opensearch/commons/notifications/action/NotificationsActions.kt b/src/main/kotlin/org/opensearch/commons/notifications/action/NotificationsActions.kt index d93dd29a..10605cac 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/action/NotificationsActions.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/action/NotificationsActions.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.action diff --git a/src/main/kotlin/org/opensearch/commons/notifications/action/SendNotificationRequest.kt b/src/main/kotlin/org/opensearch/commons/notifications/action/SendNotificationRequest.kt index 9943ed57..9f4d3159 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/action/SendNotificationRequest.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/action/SendNotificationRequest.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.action diff --git a/src/main/kotlin/org/opensearch/commons/notifications/action/SendNotificationResponse.kt b/src/main/kotlin/org/opensearch/commons/notifications/action/SendNotificationResponse.kt index 38338fc5..96599b3a 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/action/SendNotificationResponse.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/action/SendNotificationResponse.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.action diff --git a/src/main/kotlin/org/opensearch/commons/notifications/action/UpdateNotificationConfigRequest.kt b/src/main/kotlin/org/opensearch/commons/notifications/action/UpdateNotificationConfigRequest.kt index dcba7b71..765533be 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/action/UpdateNotificationConfigRequest.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/action/UpdateNotificationConfigRequest.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.action diff --git a/src/main/kotlin/org/opensearch/commons/notifications/action/UpdateNotificationConfigResponse.kt b/src/main/kotlin/org/opensearch/commons/notifications/action/UpdateNotificationConfigResponse.kt index 0e15a69b..7de2e58c 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/action/UpdateNotificationConfigResponse.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/action/UpdateNotificationConfigResponse.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.action diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/Attachment.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/Attachment.kt index 282781f0..7768273d 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/Attachment.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/Attachment.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.model diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/BaseConfigData.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/BaseConfigData.kt index a766d3e0..1b8e59bf 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/BaseConfigData.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/BaseConfigData.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.model diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/BaseModel.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/BaseModel.kt index bdc13931..5ead5594 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/BaseModel.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/BaseModel.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.model diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/ChannelMessage.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/ChannelMessage.kt index 5f70efa7..18a65d39 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/ChannelMessage.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/ChannelMessage.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.model diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/Chime.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/Chime.kt index 2ffb0fd0..f39a3f7a 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/Chime.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/Chime.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.model diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/ConfigType.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/ConfigType.kt index 85c10e35..e9888e2b 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/ConfigType.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/ConfigType.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.model diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/DeliveryStatus.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/DeliveryStatus.kt index e824242b..41009ba7 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/DeliveryStatus.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/DeliveryStatus.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.model diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/Email.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/Email.kt index 86d5f67a..07c055d6 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/Email.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/Email.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.model diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/EmailGroup.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/EmailGroup.kt index 4940cc39..c286b66e 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/EmailGroup.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/EmailGroup.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.model diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/EmailRecipient.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/EmailRecipient.kt index 78c4ae59..aa523346 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/EmailRecipient.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/EmailRecipient.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.model diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/EmailRecipientStatus.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/EmailRecipientStatus.kt index a65224de..12774764 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/EmailRecipientStatus.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/EmailRecipientStatus.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.model diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/EventSource.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/EventSource.kt index 98c46d2a..06b28bee 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/EventSource.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/EventSource.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.model diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/EventStatus.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/EventStatus.kt index bf72836d..b322e401 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/EventStatus.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/EventStatus.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.model diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/FeatureChannel.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/FeatureChannel.kt index a108d2ff..c0e74c56 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/FeatureChannel.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/FeatureChannel.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.model diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/FeatureChannelList.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/FeatureChannelList.kt index 6fc57b22..d5df20a1 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/FeatureChannelList.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/FeatureChannelList.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.model diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationConfig.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationConfig.kt index a0f7f5ad..e80a5497 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationConfig.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationConfig.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.model diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationConfigInfo.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationConfigInfo.kt index 3c17a28c..7867a2d2 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationConfigInfo.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationConfigInfo.kt @@ -1,29 +1,8 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. */ -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * - */ package org.opensearch.commons.notifications.model import org.opensearch.common.Strings diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationConfigSearchResult.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationConfigSearchResult.kt index 48952335..579a16cb 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationConfigSearchResult.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationConfigSearchResult.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.model diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationEvent.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationEvent.kt index c6bf6928..a76f552d 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationEvent.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationEvent.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.model diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationEventInfo.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationEventInfo.kt index 3e4ff552..51921fc8 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationEventInfo.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationEventInfo.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.model diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationEventSearchResult.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationEventSearchResult.kt index 71ed1ba5..e9b68406 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationEventSearchResult.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationEventSearchResult.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.model diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/SearchResults.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/SearchResults.kt index 868cfebe..226f8d5d 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/SearchResults.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/SearchResults.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.model diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/SesAccount.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/SesAccount.kt index aa9aca26..4aea8eb4 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/SesAccount.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/SesAccount.kt @@ -1,12 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. */ package org.opensearch.commons.notifications.model diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/SeverityType.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/SeverityType.kt index 6f84f07b..0fa8a427 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/SeverityType.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/SeverityType.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.model diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/Slack.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/Slack.kt index e5d3c3f6..f022470b 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/Slack.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/Slack.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.model diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/SmtpAccount.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/SmtpAccount.kt index 21e2155e..6022a913 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/SmtpAccount.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/SmtpAccount.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.model diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/Sns.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/Sns.kt index 5e723926..583aec49 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/Sns.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/Sns.kt @@ -1,13 +1,8 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. */ + package org.opensearch.commons.notifications.model import org.opensearch.common.io.stream.StreamInput diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/Webhook.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/Webhook.kt index 09dbfe9d..710a9594 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/Webhook.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/Webhook.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.model diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/XParser.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/XParser.kt index 894b21a9..e019acd7 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/XParser.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/XParser.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.model diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/config/ConfigDataProperties.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/config/ConfigDataProperties.kt index e6844934..7fb4327f 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/config/ConfigDataProperties.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/config/ConfigDataProperties.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.model.config diff --git a/src/main/kotlin/org/opensearch/commons/utils/EnumHelpers.kt b/src/main/kotlin/org/opensearch/commons/utils/EnumHelpers.kt index 3a18407e..39db7949 100644 --- a/src/main/kotlin/org/opensearch/commons/utils/EnumHelpers.kt +++ b/src/main/kotlin/org/opensearch/commons/utils/EnumHelpers.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.utils diff --git a/src/main/kotlin/org/opensearch/commons/utils/EnumParser.kt b/src/main/kotlin/org/opensearch/commons/utils/EnumParser.kt index 2a678f1f..b327d53c 100644 --- a/src/main/kotlin/org/opensearch/commons/utils/EnumParser.kt +++ b/src/main/kotlin/org/opensearch/commons/utils/EnumParser.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.utils diff --git a/src/main/kotlin/org/opensearch/commons/utils/Helpers.kt b/src/main/kotlin/org/opensearch/commons/utils/Helpers.kt index ae08c1d0..c31f0cab 100644 --- a/src/main/kotlin/org/opensearch/commons/utils/Helpers.kt +++ b/src/main/kotlin/org/opensearch/commons/utils/Helpers.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.utils diff --git a/src/main/kotlin/org/opensearch/commons/utils/OpenForTesting.kt b/src/main/kotlin/org/opensearch/commons/utils/OpenForTesting.kt index ccbd1536..1549e2e5 100644 --- a/src/main/kotlin/org/opensearch/commons/utils/OpenForTesting.kt +++ b/src/main/kotlin/org/opensearch/commons/utils/OpenForTesting.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.utils diff --git a/src/main/kotlin/org/opensearch/commons/utils/SecureClientWrapper.kt b/src/main/kotlin/org/opensearch/commons/utils/SecureClientWrapper.kt index 45fa29bd..bc0f0596 100644 --- a/src/main/kotlin/org/opensearch/commons/utils/SecureClientWrapper.kt +++ b/src/main/kotlin/org/opensearch/commons/utils/SecureClientWrapper.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.utils diff --git a/src/main/kotlin/org/opensearch/commons/utils/TransportHelpers.kt b/src/main/kotlin/org/opensearch/commons/utils/TransportHelpers.kt index 4763a48a..049dabdc 100644 --- a/src/main/kotlin/org/opensearch/commons/utils/TransportHelpers.kt +++ b/src/main/kotlin/org/opensearch/commons/utils/TransportHelpers.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.utils diff --git a/src/main/kotlin/org/opensearch/commons/utils/ValidationHelpers.kt b/src/main/kotlin/org/opensearch/commons/utils/ValidationHelpers.kt index 9f9082c4..ab9f7409 100644 --- a/src/main/kotlin/org/opensearch/commons/utils/ValidationHelpers.kt +++ b/src/main/kotlin/org/opensearch/commons/utils/ValidationHelpers.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.utils diff --git a/src/main/kotlin/org/opensearch/commons/utils/XContentHelpers.kt b/src/main/kotlin/org/opensearch/commons/utils/XContentHelpers.kt index 92dee033..e4af6007 100644 --- a/src/main/kotlin/org/opensearch/commons/utils/XContentHelpers.kt +++ b/src/main/kotlin/org/opensearch/commons/utils/XContentHelpers.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.utils diff --git a/src/test/java/org/opensearch/commons/InjectSecurityTest.java b/src/test/java/org/opensearch/commons/InjectSecurityTest.java index a9073d93..5a69de07 100644 --- a/src/test/java/org/opensearch/commons/InjectSecurityTest.java +++ b/src/test/java/org/opensearch/commons/InjectSecurityTest.java @@ -1,27 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. */ package org.opensearch.commons; diff --git a/src/test/java/org/opensearch/commons/authuser/UserTest.java b/src/test/java/org/opensearch/commons/authuser/UserTest.java index ca727e6d..4df30a44 100644 --- a/src/test/java/org/opensearch/commons/authuser/UserTest.java +++ b/src/test/java/org/opensearch/commons/authuser/UserTest.java @@ -1,27 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. */ package org.opensearch.commons.authuser; diff --git a/src/test/java/org/opensearch/commons/destination/message/LegacyChimeMessageTest.java b/src/test/java/org/opensearch/commons/destination/message/LegacyChimeMessageTest.java index 4477789e..191fef30 100644 --- a/src/test/java/org/opensearch/commons/destination/message/LegacyChimeMessageTest.java +++ b/src/test/java/org/opensearch/commons/destination/message/LegacyChimeMessageTest.java @@ -1,27 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. */ package org.opensearch.commons.destination.message; diff --git a/src/test/java/org/opensearch/commons/destination/message/LegacyCustomWebhookMessageTest.java b/src/test/java/org/opensearch/commons/destination/message/LegacyCustomWebhookMessageTest.java index fba614fd..7443d060 100644 --- a/src/test/java/org/opensearch/commons/destination/message/LegacyCustomWebhookMessageTest.java +++ b/src/test/java/org/opensearch/commons/destination/message/LegacyCustomWebhookMessageTest.java @@ -1,27 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. */ package org.opensearch.commons.destination.message; diff --git a/src/test/java/org/opensearch/commons/destination/message/LegacySlackMessageTest.java b/src/test/java/org/opensearch/commons/destination/message/LegacySlackMessageTest.java index a520fc8e..6b04d651 100644 --- a/src/test/java/org/opensearch/commons/destination/message/LegacySlackMessageTest.java +++ b/src/test/java/org/opensearch/commons/destination/message/LegacySlackMessageTest.java @@ -1,27 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. */ package org.opensearch.commons.destination.message; diff --git a/src/test/java/org/opensearch/commons/destination/response/LegacyDestinationResponseTest.java b/src/test/java/org/opensearch/commons/destination/response/LegacyDestinationResponseTest.java index 6175827e..e9189d24 100644 --- a/src/test/java/org/opensearch/commons/destination/response/LegacyDestinationResponseTest.java +++ b/src/test/java/org/opensearch/commons/destination/response/LegacyDestinationResponseTest.java @@ -1,27 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. */ package org.opensearch.commons.destination.response; diff --git a/src/test/java/org/opensearch/commons/rest/IntegrationTests.java b/src/test/java/org/opensearch/commons/rest/IntegrationTests.java index ee465086..0c6b7cfe 100644 --- a/src/test/java/org/opensearch/commons/rest/IntegrationTests.java +++ b/src/test/java/org/opensearch/commons/rest/IntegrationTests.java @@ -1,27 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. */ package org.opensearch.commons.rest; diff --git a/src/test/java/org/opensearch/commons/rest/SecureRestClientBuilderTest.java b/src/test/java/org/opensearch/commons/rest/SecureRestClientBuilderTest.java index 1fe5a51e..4a034f7e 100644 --- a/src/test/java/org/opensearch/commons/rest/SecureRestClientBuilderTest.java +++ b/src/test/java/org/opensearch/commons/rest/SecureRestClientBuilderTest.java @@ -1,27 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. */ package org.opensearch.commons.rest; diff --git a/src/test/java/org/opensearch/commons/rest/TrustStoreTest.java b/src/test/java/org/opensearch/commons/rest/TrustStoreTest.java index bea767d0..108a9e8d 100644 --- a/src/test/java/org/opensearch/commons/rest/TrustStoreTest.java +++ b/src/test/java/org/opensearch/commons/rest/TrustStoreTest.java @@ -1,27 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. */ package org.opensearch.commons.rest; diff --git a/src/test/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterfaceTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterfaceTests.kt index 31d47bba..8147650f 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterfaceTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterfaceTests.kt @@ -1,13 +1,8 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. */ + package org.opensearch.commons.notifications import com.nhaarman.mockitokotlin2.whenever diff --git a/src/test/kotlin/org/opensearch/commons/notifications/action/CreateNotificationConfigRequestTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/action/CreateNotificationConfigRequestTests.kt index 28f337b8..9eb1de1f 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/action/CreateNotificationConfigRequestTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/action/CreateNotificationConfigRequestTests.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.action diff --git a/src/test/kotlin/org/opensearch/commons/notifications/action/CreateNotificationConfigResponseTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/action/CreateNotificationConfigResponseTests.kt index b9f0f4e1..0f580fcd 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/action/CreateNotificationConfigResponseTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/action/CreateNotificationConfigResponseTests.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.action diff --git a/src/test/kotlin/org/opensearch/commons/notifications/action/DeleteNotificationConfigRequestTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/action/DeleteNotificationConfigRequestTests.kt index 4c0c016d..c44d1458 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/action/DeleteNotificationConfigRequestTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/action/DeleteNotificationConfigRequestTests.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.action diff --git a/src/test/kotlin/org/opensearch/commons/notifications/action/DeleteNotificationConfigResponseTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/action/DeleteNotificationConfigResponseTests.kt index 5c479b47..fb574114 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/action/DeleteNotificationConfigResponseTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/action/DeleteNotificationConfigResponseTests.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.action diff --git a/src/test/kotlin/org/opensearch/commons/notifications/action/GetFeatureChannelListRequestTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/action/GetFeatureChannelListRequestTests.kt index 8c5c770f..98d577de 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/action/GetFeatureChannelListRequestTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/action/GetFeatureChannelListRequestTests.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.action diff --git a/src/test/kotlin/org/opensearch/commons/notifications/action/GetFeatureChannelListResponseTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/action/GetFeatureChannelListResponseTests.kt index 149e966f..805f651e 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/action/GetFeatureChannelListResponseTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/action/GetFeatureChannelListResponseTests.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.action diff --git a/src/test/kotlin/org/opensearch/commons/notifications/action/GetNotificationConfigRequestTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/action/GetNotificationConfigRequestTests.kt index cf892209..8873202d 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/action/GetNotificationConfigRequestTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/action/GetNotificationConfigRequestTests.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.action diff --git a/src/test/kotlin/org/opensearch/commons/notifications/action/GetNotificationConfigResponseTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/action/GetNotificationConfigResponseTests.kt index 8cc66d80..7541acb2 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/action/GetNotificationConfigResponseTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/action/GetNotificationConfigResponseTests.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.action diff --git a/src/test/kotlin/org/opensearch/commons/notifications/action/GetNotificationEventRequestTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/action/GetNotificationEventRequestTests.kt index 5e12d5f1..53bb825a 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/action/GetNotificationEventRequestTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/action/GetNotificationEventRequestTests.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.action diff --git a/src/test/kotlin/org/opensearch/commons/notifications/action/GetNotificationEventResponseTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/action/GetNotificationEventResponseTests.kt index be6af960..16139bb1 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/action/GetNotificationEventResponseTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/action/GetNotificationEventResponseTests.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.action diff --git a/src/test/kotlin/org/opensearch/commons/notifications/action/GetPluginFeaturesRequestTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/action/GetPluginFeaturesRequestTests.kt index 3861fdd9..1c85ed70 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/action/GetPluginFeaturesRequestTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/action/GetPluginFeaturesRequestTests.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.action diff --git a/src/test/kotlin/org/opensearch/commons/notifications/action/GetPluginFeaturesResponseTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/action/GetPluginFeaturesResponseTests.kt index c9924269..72b9a49f 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/action/GetPluginFeaturesResponseTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/action/GetPluginFeaturesResponseTests.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.action diff --git a/src/test/kotlin/org/opensearch/commons/notifications/action/LegacyPublishNotificationRequestTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/action/LegacyPublishNotificationRequestTests.kt index 349a1c14..c323ec85 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/action/LegacyPublishNotificationRequestTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/action/LegacyPublishNotificationRequestTests.kt @@ -1,12 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. */ package org.opensearch.commons.notifications.action diff --git a/src/test/kotlin/org/opensearch/commons/notifications/action/LegacyPublishNotificationResponseTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/action/LegacyPublishNotificationResponseTests.kt index 4b6f8e0b..4a75a82e 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/action/LegacyPublishNotificationResponseTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/action/LegacyPublishNotificationResponseTests.kt @@ -1,12 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. */ package org.opensearch.commons.notifications.action diff --git a/src/test/kotlin/org/opensearch/commons/notifications/action/SendNotificationRequestTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/action/SendNotificationRequestTests.kt index 31f6f549..3874190c 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/action/SendNotificationRequestTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/action/SendNotificationRequestTests.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.action diff --git a/src/test/kotlin/org/opensearch/commons/notifications/action/SendNotificationResponseTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/action/SendNotificationResponseTests.kt index 511c5760..ca7f789c 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/action/SendNotificationResponseTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/action/SendNotificationResponseTests.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.action diff --git a/src/test/kotlin/org/opensearch/commons/notifications/action/UpdateNotificationConfigRequestTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/action/UpdateNotificationConfigRequestTests.kt index 9599d60e..725e3c59 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/action/UpdateNotificationConfigRequestTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/action/UpdateNotificationConfigRequestTests.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.action diff --git a/src/test/kotlin/org/opensearch/commons/notifications/action/UpdateNotificationConfigResponseTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/action/UpdateNotificationConfigResponseTests.kt index aa2839c3..ca0b18cc 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/action/UpdateNotificationConfigResponseTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/action/UpdateNotificationConfigResponseTests.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.action diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/AttachmentTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/AttachmentTests.kt index b0873cfe..5aa127fe 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/AttachmentTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/AttachmentTests.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.model diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/ChannelMessageTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/ChannelMessageTests.kt index 7cda9d66..0a9f3f87 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/ChannelMessageTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/ChannelMessageTests.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.model diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/ChimeTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/ChimeTests.kt index da404b28..8e7f434e 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/ChimeTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/ChimeTests.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.model diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/ConfigTypeTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/ConfigTypeTests.kt index 28b1ec7e..6be8d68b 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/ConfigTypeTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/ConfigTypeTests.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.model diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/DeliveryStatusTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/DeliveryStatusTests.kt index 377d2be9..33c42e99 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/DeliveryStatusTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/DeliveryStatusTests.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.model diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/EmailGroupTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/EmailGroupTests.kt index dbf2f77b..15ab3ade 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/EmailGroupTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/EmailGroupTests.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.model diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/EmailRecipientStatusTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/EmailRecipientStatusTests.kt index 31bb80bd..c9bd89af 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/EmailRecipientStatusTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/EmailRecipientStatusTests.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.model diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/EmailRecipientTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/EmailRecipientTests.kt index c2f2d36d..56a5f752 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/EmailRecipientTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/EmailRecipientTests.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.model diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/EmailTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/EmailTests.kt index 8e4772f5..8624b138 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/EmailTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/EmailTests.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.model diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/EventSourceTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/EventSourceTests.kt index 6a87ed3f..2244d0c4 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/EventSourceTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/EventSourceTests.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.model diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/EventStatusTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/EventStatusTests.kt index e9a1634f..65173cfe 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/EventStatusTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/EventStatusTests.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.model diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/FeatureChannelListTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/FeatureChannelListTests.kt index 5bd3db62..8a40aadd 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/FeatureChannelListTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/FeatureChannelListTests.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.model diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/FeatureChannelTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/FeatureChannelTests.kt index d2b8f009..3fa2e4ab 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/FeatureChannelTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/FeatureChannelTests.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.model diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/FilterConfigListTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/FilterConfigListTests.kt index f4ceee7f..9ac569f6 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/FilterConfigListTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/FilterConfigListTests.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.model diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/FilterConfigTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/FilterConfigTests.kt index b5dd66b6..234548a8 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/FilterConfigTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/FilterConfigTests.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.model diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/MethodTypeTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/MethodTypeTests.kt index 75685d53..f9982d7c 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/MethodTypeTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/MethodTypeTests.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.model diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationConfigInfoTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationConfigInfoTests.kt index 6f532fb0..d14b9f34 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationConfigInfoTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationConfigInfoTests.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.model diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationConfigSearchResultsTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationConfigSearchResultsTests.kt index dab33090..835af358 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationConfigSearchResultsTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationConfigSearchResultsTests.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.model diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationConfigTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationConfigTests.kt index 0a96c8ed..47614986 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationConfigTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationConfigTests.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.model diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationEventInfoTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationEventInfoTests.kt index 3937c252..a87e334a 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationEventInfoTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationEventInfoTests.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.model diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationEventSearchResultTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationEventSearchResultTests.kt index c0e9786d..ae3f01a9 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationEventSearchResultTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationEventSearchResultTests.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.model diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationEventTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationEventTests.kt index 92c53fd8..313ffca9 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationEventTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationEventTests.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.model diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/SesAccountTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/SesAccountTests.kt index e999e534..e5a52837 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/SesAccountTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/SesAccountTests.kt @@ -1,12 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. */ package org.opensearch.commons.notifications.model diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/SeverityTypeTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/SeverityTypeTests.kt index 71fe1460..35f7b218 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/SeverityTypeTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/SeverityTypeTests.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.model diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/SlackTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/SlackTests.kt index 98fbc0cd..5c64c6ae 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/SlackTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/SlackTests.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.model diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/SmtpAccountTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/SmtpAccountTests.kt index bc924681..ffdf26c7 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/SmtpAccountTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/SmtpAccountTests.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.model diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/SnsTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/SnsTests.kt index 03d494d2..494f09e9 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/SnsTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/SnsTests.kt @@ -1,12 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. */ package org.opensearch.commons.notifications.model diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/WebhookTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/WebhookTests.kt index 5a717669..3272203d 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/WebhookTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/WebhookTests.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.notifications.model diff --git a/src/test/kotlin/org/opensearch/commons/utils/TestHelpers.kt b/src/test/kotlin/org/opensearch/commons/utils/TestHelpers.kt index 35f5d3b9..81dc33e0 100644 --- a/src/test/kotlin/org/opensearch/commons/utils/TestHelpers.kt +++ b/src/test/kotlin/org/opensearch/commons/utils/TestHelpers.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - * */ package org.opensearch.commons.utils From 2cb20f439c3e18e04b7ce26dc4a13451fa40422e Mon Sep 17 00:00:00 2001 From: Peter Nied Date: Thu, 24 Feb 2022 16:07:40 -0600 Subject: [PATCH 101/140] Remove jcenter repository missed on first pass (#118) Signed-off-by: Peter Nied Signed-off-by: Zelin Hao --- build.gradle | 1 - 1 file changed, 1 deletion(-) diff --git a/build.gradle b/build.gradle index 07768d30..76a5c34e 100644 --- a/build.gradle +++ b/build.gradle @@ -35,7 +35,6 @@ repositories { mavenLocal() mavenCentral() maven { url "https://plugins.gradle.org/m2/" } - jcenter() maven { url "https://aws.oss.sonatype.org/content/repositories/snapshots" } } From aba93a9c0687f67ef989db5b4e07305300e6667d Mon Sep 17 00:00:00 2001 From: "Daniel Doubrovkine (dB.)" Date: Tue, 1 Mar 2022 17:09:12 -0500 Subject: [PATCH 102/140] Run CI/CD on Java 8, 11, 14 and 17. (#121) * Run CI/CD on Java 8, 11, 14 and 17. Signed-off-by: dblock * Add JDK 17. Signed-off-by: dblock Signed-off-by: Zelin Hao --- .github/workflows/ci-17.yml | 40 +++++++++++++++++++ .github/workflows/ci.yml | 6 ++- DEVELOPER_GUIDE.md | 6 +-- .../commons/InjectSecurityTest.java | 14 +++++-- 4 files changed, 58 insertions(+), 8 deletions(-) create mode 100644 .github/workflows/ci-17.yml diff --git a/.github/workflows/ci-17.yml b/.github/workflows/ci-17.yml new file mode 100644 index 00000000..a6a8a1e2 --- /dev/null +++ b/.github/workflows/ci-17.yml @@ -0,0 +1,40 @@ +name: Build and Test +on: + push: + branches: + - "*" + pull_request: + branches: + - "*" + +jobs: + build: + + name: Build and Test (17) + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Setup Java 11 + uses: actions/setup-java@v2 + with: + distribution: 'temurin' + java-version: 11 + + - name: Build + run: | + ./gradlew build --build-cache + + - name: Setup Java 17 + uses: actions/setup-java@v2 + with: + distribution: 'temurin' + java-version: 17 + + - name: Test + run: | + ./gradlew test --build-cache + + diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c35e0c0a..e3e495c4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,7 +11,10 @@ jobs: build: strategy: matrix: - java: [14] + java: + - 8 + - 11 + - 14 name: Build and Test runs-on: ubuntu-latest @@ -25,7 +28,6 @@ jobs: with: java-version: ${{ matrix.java }} - # common-utils - name: Build and Test run: | ./gradlew build diff --git a/DEVELOPER_GUIDE.md b/DEVELOPER_GUIDE.md index d162eccb..27fc15b3 100644 --- a/DEVELOPER_GUIDE.md +++ b/DEVELOPER_GUIDE.md @@ -1,7 +1,7 @@ - [Developer Guide](#developer-guide) - [Forking and Cloning](#forking-and-cloning) - [Install Prerequisites](#install-prerequisites) - - [JDK 14](#jdk-14) + - [JDK 11](#jdk-11) - [Building](#building) - [Using IntelliJ IDEA](#using-intellij-idea) - [Submitting Changes](#submitting-changes) @@ -16,9 +16,9 @@ Fork this repository on GitHub, and clone locally with `git clone`. ### Install Prerequisites -#### JDK 14 +#### JDK 11 -OpenSearch components build using Java 14 at a minimum. This means you must have a JDK 14 installed with the environment variable `JAVA_HOME` referencing the path to Java home for your JDK 14 installation, e.g. `JAVA_HOME=/usr/lib/jvm/jdk-14`. +OpenSearch components build using Java 11 at a minimum. This means you must have a JDK 11 installed with the environment variable `JAVA_HOME` referencing the path to Java home for your JDK 11 installation, e.g. `JAVA_HOME=/usr/lib/jvm/jdk-11`. ### Building diff --git a/src/test/java/org/opensearch/commons/InjectSecurityTest.java b/src/test/java/org/opensearch/commons/InjectSecurityTest.java index 5a69de07..818aa9c7 100644 --- a/src/test/java/org/opensearch/commons/InjectSecurityTest.java +++ b/src/test/java/org/opensearch/commons/InjectSecurityTest.java @@ -15,7 +15,7 @@ import static org.opensearch.commons.ConfigConstants.OPENSEARCH_SECURITY_USE_INJECTED_USER_FOR_PLUGINS; import java.util.Arrays; -import java.util.Map; +import java.util.HashMap; import org.junit.jupiter.api.Test; import org.opensearch.common.settings.Settings; @@ -114,7 +114,11 @@ public void testInjectProperty() { assertTrue(helper.injectProperty("property1", true)); assertTrue(helper.injectProperty("property2", "some value")); assertTrue(helper.injectProperty("property3", "")); - assertTrue(helper.injectProperty("property4", Map.of("key", "value"))); + assertTrue(helper.injectProperty("property4", new HashMap() { + { + put("key", "value"); + } + })); // verify the set properties are not null and equal to what was set assertNull(threadContext.getTransient("property")); assertNotNull(threadContext.getTransient("property1")); @@ -124,7 +128,11 @@ public void testInjectProperty() { assertNotNull(threadContext.getTransient("property3")); assertEquals("", threadContext.getTransient("property3")); assertNotNull(threadContext.getTransient("property4")); - assertEquals(Map.of("key", "value"), threadContext.getTransient("property4")); + assertEquals(new HashMap() { + { + put("key", "value"); + } + }, threadContext.getTransient("property4")); } assertEquals("1", threadContext.getHeader("default")); assertEquals("opendistro", threadContext.getHeader("name")); From 29e7902a04ca10b78a72fff859115ff58f141ff2 Mon Sep 17 00:00:00 2001 From: "whitesource-for-github-com[bot]" <50673670+whitesource-for-github-com[bot]@users.noreply.github.com> Date: Tue, 1 Mar 2022 16:55:00 -0800 Subject: [PATCH 103/140] Add .whitesource configuration file (#109) Co-authored-by: whitesource-for-github-com[bot] <50673670+whitesource-for-github-com[bot]@users.noreply.github.com> Signed-off-by: Zelin Hao --- .whitesource | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 .whitesource diff --git a/.whitesource b/.whitesource new file mode 100644 index 00000000..db4b0fec --- /dev/null +++ b/.whitesource @@ -0,0 +1,15 @@ +{ + "scanSettings": { + "configMode": "AUTO", + "configExternalURL": "", + "projectToken": "", + "baseBranches": [] + }, + "checkRunSettings": { + "vulnerableCheckRunConclusionLevel": "failure", + "displayMode": "diff" + }, + "issueSettings": { + "minSeverityLevel": "LOW" + } +} \ No newline at end of file From e43b05c216d1d2db2ab35231ade823c7997d3fdc Mon Sep 17 00:00:00 2001 From: Ashish Agrawal Date: Wed, 2 Mar 2022 17:09:20 -0800 Subject: [PATCH 104/140] Upgrade to 2.0 (#122) Signed-off-by: Ashish Agrawal Signed-off-by: Zelin Hao --- build.gradle | 2 +- gradle/wrapper/gradle-wrapper.properties | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 76a5c34e..d92e0acf 100644 --- a/build.gradle +++ b/build.gradle @@ -6,7 +6,7 @@ buildscript { ext { opensearch_group = "org.opensearch" - opensearch_version = System.getProperty("opensearch.version", "1.3.0-SNAPSHOT") + opensearch_version = System.getProperty("opensearch.version", "2.0.0-SNAPSHOT") kotlin_version = System.getProperty("kotlin.version", "1.4.32") } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 21a8fe40..f338a880 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -2,4 +2,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.4-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-all.zip From c4e8cbd313cf7afc35011aa98030dec2974f78e2 Mon Sep 17 00:00:00 2001 From: "Daniel Doubrovkine (dB.)" Date: Wed, 9 Mar 2022 14:32:56 -0500 Subject: [PATCH 105/140] Remove JDK8 support and fix JDK17 build. (#129) Signed-off-by: Zelin Hao --- .github/workflows/ci-17.yml | 40 ------------------------------------- .github/workflows/ci.yml | 2 +- build.gradle | 19 +++++++++--------- 3 files changed, 11 insertions(+), 50 deletions(-) delete mode 100644 .github/workflows/ci-17.yml diff --git a/.github/workflows/ci-17.yml b/.github/workflows/ci-17.yml deleted file mode 100644 index a6a8a1e2..00000000 --- a/.github/workflows/ci-17.yml +++ /dev/null @@ -1,40 +0,0 @@ -name: Build and Test -on: - push: - branches: - - "*" - pull_request: - branches: - - "*" - -jobs: - build: - - name: Build and Test (17) - runs-on: ubuntu-latest - - steps: - - name: Checkout - uses: actions/checkout@v2 - - - name: Setup Java 11 - uses: actions/setup-java@v2 - with: - distribution: 'temurin' - java-version: 11 - - - name: Build - run: | - ./gradlew build --build-cache - - - name: Setup Java 17 - uses: actions/setup-java@v2 - with: - distribution: 'temurin' - java-version: 17 - - - name: Test - run: | - ./gradlew test --build-cache - - diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e3e495c4..69e7573d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -12,9 +12,9 @@ jobs: strategy: matrix: java: - - 8 - 11 - 14 + - 17 name: Build and Test runs-on: ubuntu-latest diff --git a/build.gradle b/build.gradle index d92e0acf..5ab47cb4 100644 --- a/build.gradle +++ b/build.gradle @@ -7,7 +7,7 @@ buildscript { ext { opensearch_group = "org.opensearch" opensearch_version = System.getProperty("opensearch.version", "2.0.0-SNAPSHOT") - kotlin_version = System.getProperty("kotlin.version", "1.4.32") + kotlin_version = System.getProperty("kotlin.version", "1.6.10") } repositories { @@ -21,7 +21,7 @@ buildscript { classpath "${opensearch_group}.gradle:build-tools:${opensearch_version}" classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${kotlin_version}" classpath "org.jetbrains.kotlin:kotlin-allopen:${kotlin_version}" - classpath "io.gitlab.arturbosch.detekt:detekt-gradle-plugin:1.17.1" + classpath "io.gitlab.arturbosch.detekt:detekt-gradle-plugin:1.20.0-RC1" } } @@ -50,7 +50,8 @@ allprojects { } } -sourceCompatibility = 1.8 +targetCompatibility = JavaVersion.VERSION_11 +sourceCompatibility = JavaVersion.VERSION_11 apply plugin: 'java' apply plugin: 'jacoco' @@ -70,15 +71,15 @@ dependencies { compileOnly "org.jetbrains.kotlin:kotlin-stdlib:${kotlin_version}" compileOnly "org.jetbrains.kotlin:kotlin-stdlib-common:${kotlin_version}" compileOnly "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.3" // ${kotlin_version} does not work for coroutines - testCompile "org.opensearch.test:framework:${opensearch_version}" - testCompile "org.jetbrains.kotlin:kotlin-test:${kotlin_version}" - testCompile "org.mockito:mockito-core:3.10.0" + testImplementation "org.opensearch.test:framework:${opensearch_version}" + testImplementation "org.jetbrains.kotlin:kotlin-test:${kotlin_version}" + testImplementation "org.mockito:mockito-core:3.10.0" testImplementation 'org.junit.jupiter:junit-jupiter-api:5.7.2' testImplementation 'org.mockito:mockito-junit-jupiter:3.10.0' testImplementation "com.nhaarman.mockitokotlin2:mockito-kotlin:2.2.0" testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.7.2' - ktlint "com.pinterest:ktlint:0.41.0" + ktlint "com.pinterest:ktlint:0.44.0" } test { @@ -126,13 +127,13 @@ task ktlintFormat(type: JavaExec, group: "formatting") { compileKotlin { kotlinOptions { freeCompilerArgs = ['-Xjsr305=strict'] - jvmTarget = "1.8" + jvmTarget = "11" } } compileTestKotlin { kotlinOptions { - jvmTarget = "1.8" + jvmTarget = "11" } } From 6afcf053853fb00b6935fa99ea3c2159fdc179da Mon Sep 17 00:00:00 2001 From: "Daniel Doubrovkine (dB.)" Date: Wed, 9 Mar 2022 20:24:57 -0500 Subject: [PATCH 106/140] Add support for build version qualifier. (#128) Signed-off-by: dblock Signed-off-by: Zelin Hao --- build.gradle | 6 +++++- scripts/build.sh | 12 ++++++++---- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/build.gradle b/build.gradle index 5ab47cb4..16c28922 100644 --- a/build.gradle +++ b/build.gradle @@ -40,11 +40,15 @@ repositories { ext { isSnapshot = "true" == System.getProperty("build.snapshot", "true") + buildVersionQualifier = System.getProperty("build.version_qualifier") } allprojects { group 'org.opensearch.commons' - version = opensearch_version - '-SNAPSHOT' + '.0' + version = opensearch_version.tokenize('-')[0] + '.0' + if (buildVersionQualifier) { + version += "-${buildVersionQualifier}" + } if (isSnapshot) { version += "-SNAPSHOT" } diff --git a/scripts/build.sh b/scripts/build.sh index f68dc52e..1f8b6d4d 100755 --- a/scripts/build.sh +++ b/scripts/build.sh @@ -10,6 +10,7 @@ function usage() { echo "" echo "Arguments:" echo -e "-v VERSION\t[Required] OpenSearch version." + echo -e "-q QUALIFIER\t[Optional] Build qualifier." echo -e "-s SNAPSHOT\t[Optional] Build a snapshot, default is 'false'." echo -e "-p PLATFORM\t[Optional] Platform, ignored." echo -e "-a ARCHITECTURE\t[Optional] Build architecture, ignored." @@ -17,7 +18,7 @@ function usage() { echo -e "-h help" } -while getopts ":h:v:s:o:p:a:" arg; do +while getopts ":h:v:q:s:o:p:a:" arg; do case $arg in h) usage @@ -26,6 +27,9 @@ while getopts ":h:v:s:o:p:a:" arg; do v) VERSION=$OPTARG ;; + q) + QUALIFIER=$OPTARG + ;; s) SNAPSHOT=$OPTARG ;; @@ -59,8 +63,8 @@ fi [[ "$SNAPSHOT" == "true" ]] && VERSION=$VERSION-SNAPSHOT [ -z "$OUTPUT" ] && OUTPUT=artifacts -./gradlew build -Dopensearch.version=$VERSION -Dbuild.snapshot=$SNAPSHOT -./gradlew publishShadowPublicationToMavenLocal -Dopensearch.version=$VERSION -Dbuild.snapshot=$SNAPSHOT -./gradlew publishShadowPublicationToStagingRepository -Dopensearch.version=$VERSION -Dbuild.snapshot=$SNAPSHOT +./gradlew build -Dopensearch.version=$VERSION -Dbuild.snapshot=$SNAPSHOT -Dbuild.version_qualifier=$QUALIFIER +./gradlew publishShadowPublicationToMavenLocal -Dopensearch.version=$VERSION -Dbuild.snapshot=$SNAPSHOT -Dbuild.version_qualifier=$QUALIFIER +./gradlew publishShadowPublicationToStagingRepository -Dopensearch.version=$VERSION -Dbuild.snapshot=$SNAPSHOT -Dbuild.version_qualifier=$QUALIFIER mkdir -p $OUTPUT/maven/org/opensearch cp -r ./build/local-staging-repo/org/opensearch/common-utils $OUTPUT/maven/org/opensearch/common-utils From ab12d89ba5d8e5147f2b40b0cb1e8f30c4f80165 Mon Sep 17 00:00:00 2001 From: Annie Lee Date: Thu, 10 Mar 2022 10:50:04 -0800 Subject: [PATCH 107/140] Add backport and auto delete workflow (#130) Signed-off-by: Annie Lee Signed-off-by: Zelin Hao --- .github/workflows/backport.yml | 29 ++++++++++++++++++++ .github/workflows/delete_backport_branch.yml | 15 ++++++++++ DEVELOPER_GUIDE.md | 6 +++- 3 files changed, 49 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/backport.yml create mode 100644 .github/workflows/delete_backport_branch.yml diff --git a/.github/workflows/backport.yml b/.github/workflows/backport.yml new file mode 100644 index 00000000..e3f96a44 --- /dev/null +++ b/.github/workflows/backport.yml @@ -0,0 +1,29 @@ + +name: Backport +on: + pull_request_target: + types: + - closed + - labeled + +jobs: + backport: + runs-on: ubuntu-latest + permissions: + contents: write + pull-requests: write + name: Backport + steps: + - name: GitHub App token + id: github_app_token + uses: tibdex/github-app-token@v1.5.0 + with: + app_id: ${{ secrets.APP_ID }} + private_key: ${{ secrets.APP_PRIVATE_KEY }} + installation_id: 22958780 + + - name: Backport + uses: VachaShah/backport@v1.1.4 + with: + github_token: ${{ steps.github_app_token.outputs.token }} + branch_name: backport/backport-${{ github.event.number }} diff --git a/.github/workflows/delete_backport_branch.yml b/.github/workflows/delete_backport_branch.yml new file mode 100644 index 00000000..f24f022b --- /dev/null +++ b/.github/workflows/delete_backport_branch.yml @@ -0,0 +1,15 @@ +name: Delete merged branch of the backport PRs +on: + pull_request: + types: + - closed + +jobs: + delete-branch: + runs-on: ubuntu-latest + if: startsWith(github.event.pull_request.head.ref,'backport/') + steps: + - name: Delete merged branch + uses: SvanBoxel/delete-merged-branch@main + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/DEVELOPER_GUIDE.md b/DEVELOPER_GUIDE.md index 27fc15b3..d4a44c46 100644 --- a/DEVELOPER_GUIDE.md +++ b/DEVELOPER_GUIDE.md @@ -36,4 +36,8 @@ Launch Intellij IDEA, choose **Import Project**, and select the `settings.gradle ### Submitting Changes -See [CONTRIBUTING](CONTRIBUTING.md). \ No newline at end of file +See [CONTRIBUTING](CONTRIBUTING.md). + +### Backport + +- [Link to backport documentation](https://github.com/opensearch-project/opensearch-plugins/blob/main/BACKPORT.md) From cad110d440abe9555da4ee5aed72afcacff9dc8c Mon Sep 17 00:00:00 2001 From: Saurabh Singh Date: Fri, 11 Mar 2022 14:40:13 -0800 Subject: [PATCH 108/140] Add release notes for version 1.3.0.0 (#132) Signed-off-by: Saurabh Singh Co-authored-by: Saurabh Singh Signed-off-by: Zelin Hao --- ...pensearch-common-utils.release-notes-1.3.0.0.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 release-notes/opensearch-common-utils.release-notes-1.3.0.0.md diff --git a/release-notes/opensearch-common-utils.release-notes-1.3.0.0.md b/release-notes/opensearch-common-utils.release-notes-1.3.0.0.md new file mode 100644 index 00000000..4f210951 --- /dev/null +++ b/release-notes/opensearch-common-utils.release-notes-1.3.0.0.md @@ -0,0 +1,14 @@ +## Version 1.3.0.0 2022-03-11 + +Compatible with OpenSearch 1.3.0 + +### Infrastructure + + * Updates common-utils version to 1.3 ([#99](https://github.com/opensearch-project/common-utils/pull/99)) + * Update build.sh script to include optional platform param. ([#95](https://github.com/opensearch-project/common-utils/pull/95)) + * Update copyright notice and add DCO check workflow. ([#94](https://github.com/opensearch-project/common-utils/pull/94)) + +### Documentation + + * Update copyright headers ([#117](https://github.com/opensearch-project/common-utils/pull/117)) + * Add release notes for version 1.3.0.0 ([#132](https://github.com/opensearch-project/common-utils/pull/132)) \ No newline at end of file From 6dfd708fa74e55dbff3f85c35402a62bfeb4b8ac Mon Sep 17 00:00:00 2001 From: Ashish Agrawal Date: Mon, 14 Mar 2022 16:54:51 -0700 Subject: [PATCH 109/140] Upgrade gradle artifacts to 7.3.3 (#135) Signed-off-by: Ashish Agrawal Signed-off-by: Zelin Hao --- gradle/wrapper/gradle-wrapper.jar | Bin 56172 -> 59536 bytes gradle/wrapper/gradle-wrapper.properties | 2 +- gradlew | 282 ++++++++++++++--------- gradlew.bat | 43 ++-- 4 files changed, 197 insertions(+), 130 deletions(-) diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 28861d273a5d270fd8f65dd74570c17c9c507736..7454180f2ae8848c63b8b4dea2cb829da983f2fa 100644 GIT binary patch delta 51437 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%0DCB$;CIxFT%Ws?oirIo$=Lq=nDPZE9YO&<7lE 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 BrV#)D delta 48172 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к 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 cc>h-)Mo|U| \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >/dev/null -APP_HOME="`pwd -P`" -cd "$SAVED" >/dev/null + +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit APP_NAME="Gradle" -APP_BASE_NAME=`basename "$0"` +APP_BASE_NAME=${0##*/} # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS="" +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' # Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" +MAX_FD=maximum warn () { echo "$*" -} +} >&2 die () { echo echo "$*" echo exit 1 -} +} >&2 # OS specific support (must be 'true' or 'false'). cygwin=false msys=false darwin=false nonstop=false -case "`uname`" in - CYGWIN* ) - cygwin=true - ;; - Darwin* ) - darwin=true - ;; - MINGW* ) - msys=true - ;; - NONSTOP* ) - nonstop=true - ;; +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; esac CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + # Determine the Java command to use to start the JVM. if [ -n "$JAVA_HOME" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" + JAVACMD=$JAVA_HOME/jre/sh/java else - JAVACMD="$JAVA_HOME/bin/java" + JAVACMD=$JAVA_HOME/bin/java fi if [ ! -x "$JAVACMD" ] ; then die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME @@ -81,7 +132,7 @@ Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi else - JAVACMD="java" + JAVACMD=java which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the @@ -89,84 +140,95 @@ location of your Java installation." fi # Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then - MAX_FD_LIMIT=`ulimit -H -n` - if [ $? -eq 0 ] ; then - if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then - MAX_FD="$MAX_FD_LIMIT" - fi - ulimit -n $MAX_FD - if [ $? -ne 0 ] ; then - warn "Could not set maximum file descriptor limit: $MAX_FD" - fi - else - warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" - fi +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac fi -# For Darwin, add options to specify how the application appears in the dock -if $darwin; then - GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" -fi +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) -# For Cygwin, switch paths to Windows format before running java -if $cygwin ; then - APP_HOME=`cygpath --path --mixed "$APP_HOME"` - CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - JAVACMD=`cygpath --unix "$JAVACMD"` - - # We build the pattern for arguments to be converted via cygpath - ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` - SEP="" - for dir in $ROOTDIRSRAW ; do - ROOTDIRS="$ROOTDIRS$SEP$dir" - SEP="|" - done - OURCYGPATTERN="(^($ROOTDIRS))" - # Add a user-defined pattern to the cygpath arguments - if [ "$GRADLE_CYGPATTERN" != "" ] ; then - OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" - fi # Now convert the arguments - kludge to limit ourselves to /bin/sh - i=0 - for arg in "$@" ; do - CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` - CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option - - if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition - eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` - else - eval `echo args$i`="\"$arg\"" + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) fi - i=$((i+1)) + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg done - case $i in - (0) set -- ;; - (1) set -- "$args0" ;; - (2) set -- "$args0" "$args1" ;; - (3) set -- "$args0" "$args1" "$args2" ;; - (4) set -- "$args0" "$args1" "$args2" "$args3" ;; - (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; - esac fi -# Escape application args -save () { - for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done - echo " " -} -APP_ARGS=$(save "$@") - -# Collect all arguments for the java command, following the shell quoting and substitution rules -eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" - -# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong -if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then - cd "$(dirname "$0")" -fi +# Collect all arguments for the java command; +# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of +# shell script including quotes and variable substitutions, so put them in +# double quotes to make sure that they get re-expanded; and +# * put everything else in single quotes, so that it's not re-expanded. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat index e95643d6..ac1b06f9 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -1,3 +1,19 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + @if "%DEBUG%" == "" @echo off @rem ########################################################################## @rem @@ -13,15 +29,18 @@ if "%DIRNAME%" == "" set DIRNAME=. set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS= +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" @rem Find java.exe if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto init +if "%ERRORLEVEL%" == "0" goto execute echo. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. @@ -35,7 +54,7 @@ goto fail set JAVA_HOME=%JAVA_HOME:"=% set JAVA_EXE=%JAVA_HOME%/bin/java.exe -if exist "%JAVA_EXE%" goto init +if exist "%JAVA_EXE%" goto execute echo. echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% @@ -45,28 +64,14 @@ echo location of your Java installation. goto fail -:init -@rem Get command-line arguments, handling Windows variants - -if not "%OS%" == "Windows_NT" goto win9xME_args - -:win9xME_args -@rem Slurp the command line arguments. -set CMD_LINE_ARGS= -set _SKIP=2 - -:win9xME_args_slurp -if "x%~1" == "x" goto execute - -set CMD_LINE_ARGS=%* - :execute @rem Setup the command line set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + @rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* :end @rem End local scope for the variables with windows NT shell From 64c68b1b3e4283b055a8b760b32e00da1a08f619 Mon Sep 17 00:00:00 2001 From: Mohammad Qureshi <47198598+qreshi@users.noreply.github.com> Date: Thu, 17 Mar 2022 12:44:15 -0700 Subject: [PATCH 110/140] Remove feature and feature_list usage for Notifications (#136) * Remove feature_list from NotificationConfig Signed-off-by: Mohammad Qureshi <47198598+qreshi@users.noreply.github.com> * Remove feature from FeatueChannelsListRequest Signed-off-by: Mohammad Qureshi <47198598+qreshi@users.noreply.github.com> * Remove 'feature' from EventSource Signed-off-by: Mohammad Qureshi <47198598+qreshi@users.noreply.github.com> * Remove feature from LegacyPublishNotification Signed-off-by: Mohammad Qureshi <47198598+qreshi@users.noreply.github.com> * Updated descriptions related to publishLegacyNotification Signed-off-by: Mohammad Qureshi <47198598+qreshi@users.noreply.github.com> Signed-off-by: Zelin Hao --- .../message/LegacyDestinationType.java | 2 +- .../notifications/NotificationConstants.kt | 5 -- .../NotificationsPluginInterface.kt | 8 +- .../action/GetFeatureChannelListRequest.kt | 40 +++++----- .../LegacyPublishNotificationRequest.kt | 8 +- .../action/NotificationsActions.kt | 4 +- .../notifications/model/EventSource.kt | 9 --- .../notifications/model/NotificationConfig.kt | 12 --- .../NotificationsPluginInterfaceTests.kt | 10 --- .../CreateNotificationConfigRequestTests.kt | 74 +++++++------------ .../GetFeatureChannelListRequestTests.kt | 23 +----- .../GetNotificationConfigResponseTests.kt | 20 +---- .../GetNotificationEventResponseTests.kt | 12 --- .../LegacyPublishNotificationRequestTests.kt | 4 +- .../action/SendNotificationRequestTests.kt | 12 --- .../UpdateNotificationConfigRequestTests.kt | 66 +++++++---------- .../notifications/model/EventSourceTests.kt | 18 ++--- .../model/NotificationConfigInfoTests.kt | 10 +-- .../NotificationConfigSearchResultsTests.kt | 20 +---- .../model/NotificationConfigTests.kt | 25 +------ .../model/NotificationEventInfoTests.kt | 5 -- .../NotificationEventSearchResultTests.kt | 12 --- .../model/NotificationEventTests.kt | 9 +-- 23 files changed, 103 insertions(+), 305 deletions(-) diff --git a/src/main/java/org/opensearch/commons/destination/message/LegacyDestinationType.java b/src/main/java/org/opensearch/commons/destination/message/LegacyDestinationType.java index ab50649b..1bad1029 100644 --- a/src/main/java/org/opensearch/commons/destination/message/LegacyDestinationType.java +++ b/src/main/java/org/opensearch/commons/destination/message/LegacyDestinationType.java @@ -6,7 +6,7 @@ package org.opensearch.commons.destination.message; /** - * Supported legacy notification destinations for Index Management + * Supported legacy notification destinations for Alerting and Index Management */ public enum LegacyDestinationType { LEGACY_CHIME, diff --git a/src/main/kotlin/org/opensearch/commons/notifications/NotificationConstants.kt b/src/main/kotlin/org/opensearch/commons/notifications/NotificationConstants.kt index 7a958154..6ebf7889 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/NotificationConstants.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/NotificationConstants.kt @@ -36,7 +36,6 @@ object NotificationConstants { const val NAME_TAG = "name" const val DESCRIPTION_TAG = "description" const val IS_ENABLED_TAG = "is_enabled" - const val FEATURE_LIST_TAG = "feature_list" const val TITLE_TAG = "title" const val SEVERITY_TAG = "severity" const val TAGS_TAG = "tags" @@ -70,9 +69,5 @@ object NotificationConstants { const val ALLOWED_CONFIG_FEATURE_LIST_TAG = "allowed_config_feature_list" const val PLUGIN_FEATURES_TAG = "plugin_features" - const val FEATURE_ALERTING = "alerting" - const val FEATURE_INDEX_MANAGEMENT = "index_management" - const val FEATURE_REPORTS = "reports" - const val DEFAULT_MAX_ITEMS = 1000 } diff --git a/src/main/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterface.kt b/src/main/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterface.kt index d406bb00..b67ec282 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterface.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterface.kt @@ -9,7 +9,6 @@ import org.opensearch.action.ActionResponse import org.opensearch.client.node.NodeClient import org.opensearch.common.io.stream.Writeable import org.opensearch.commons.ConfigConstants.OPENSEARCH_SECURITY_USER_INFO_THREAD_CONTEXT -import org.opensearch.commons.notifications.NotificationConstants.FEATURE_INDEX_MANAGEMENT import org.opensearch.commons.notifications.action.BaseResponse import org.opensearch.commons.notifications.action.CreateNotificationConfigRequest import org.opensearch.commons.notifications.action.CreateNotificationConfigResponse @@ -201,7 +200,7 @@ object NotificationsPluginInterface { /** * Publishes a notification API using the legacy notification implementation. No REST API. - * Internal API only for the Index Management plugin. + * Internal API only for the Alerting and Index Management plugin, other consumers should use [sendNotification]. * @param client Node client for making transport action * @param request The legacy publish notification request * @param listener The listener for getting response @@ -211,11 +210,6 @@ object NotificationsPluginInterface { request: LegacyPublishNotificationRequest, listener: ActionListener ) { - if (request.feature != FEATURE_INDEX_MANAGEMENT) { - // Do not change this; do not pass in FEATURE_INDEX_MANAGEMENT if you are not the Index Management plugin. - throw IllegalArgumentException("The publish notification method only supports the Index Management feature.") - } - client.execute( LEGACY_PUBLISH_NOTIFICATION_ACTION_TYPE, request, diff --git a/src/main/kotlin/org/opensearch/commons/notifications/action/GetFeatureChannelListRequest.kt b/src/main/kotlin/org/opensearch/commons/notifications/action/GetFeatureChannelListRequest.kt index 901b4040..56a0b0fa 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/action/GetFeatureChannelListRequest.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/action/GetFeatureChannelListRequest.kt @@ -14,7 +14,7 @@ import org.opensearch.common.xcontent.ToXContentObject import org.opensearch.common.xcontent.XContentBuilder import org.opensearch.common.xcontent.XContentParser import org.opensearch.common.xcontent.XContentParserUtils -import org.opensearch.commons.notifications.NotificationConstants.FEATURE_TAG +import org.opensearch.commons.notifications.NotificationConstants.COMPACT_TAG import org.opensearch.commons.utils.logger import java.io.IOException @@ -22,7 +22,7 @@ import java.io.IOException * This request is plugin-only call. i.e. REST interface is not exposed. */ class GetFeatureChannelListRequest : ActionRequest, ToXContentObject { - val feature: String + val compact: Boolean // Dummy request parameter for transport request companion object { private val log by logger(GetFeatureChannelListRequest::class.java) @@ -39,7 +39,7 @@ class GetFeatureChannelListRequest : ActionRequest, ToXContentObject { @JvmStatic @Throws(IOException::class) fun parse(parser: XContentParser): GetFeatureChannelListRequest { - var feature: String? = null + var compact = false XContentParserUtils.ensureExpectedToken( XContentParser.Token.START_OBJECT, @@ -50,24 +50,32 @@ class GetFeatureChannelListRequest : ActionRequest, ToXContentObject { val fieldName = parser.currentName() parser.nextToken() when (fieldName) { - FEATURE_TAG -> feature = parser.text() + COMPACT_TAG -> compact = parser.booleanValue() else -> { parser.skipChildren() log.info("Unexpected field: $fieldName, while parsing GetFeatureChannelListRequest") } } } - feature ?: throw IllegalArgumentException("$FEATURE_TAG field absent") - return GetFeatureChannelListRequest(feature) + return GetFeatureChannelListRequest() } } + /** + * {@inheritDoc} + */ + override fun toXContent(builder: XContentBuilder?, params: ToXContent.Params?): XContentBuilder { + return builder!!.startObject() + .field(COMPACT_TAG, compact) + .endObject() + } + /** * constructor for creating the class - * @param feature the caller plugin feature + * @param compact Dummy request parameter for transport request */ - constructor(feature: String) { - this.feature = feature + constructor(compact: Boolean = false) { + this.compact = compact } /** @@ -75,7 +83,7 @@ class GetFeatureChannelListRequest : ActionRequest, ToXContentObject { */ @Throws(IOException::class) constructor(input: StreamInput) : super(input) { - feature = input.readString() + compact = input.readBoolean() } /** @@ -84,17 +92,7 @@ class GetFeatureChannelListRequest : ActionRequest, ToXContentObject { @Throws(IOException::class) override fun writeTo(output: StreamOutput) { super.writeTo(output) - output.writeString(feature) - } - - /** - * {@inheritDoc} - */ - override fun toXContent(builder: XContentBuilder?, params: ToXContent.Params?): XContentBuilder { - builder!! - return builder.startObject() - .field(FEATURE_TAG, feature) - .endObject() + output.writeBoolean(compact) } /** diff --git a/src/main/kotlin/org/opensearch/commons/notifications/action/LegacyPublishNotificationRequest.kt b/src/main/kotlin/org/opensearch/commons/notifications/action/LegacyPublishNotificationRequest.kt index eb5080cf..508815a8 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/action/LegacyPublishNotificationRequest.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/action/LegacyPublishNotificationRequest.kt @@ -23,7 +23,6 @@ import java.io.IOException */ class LegacyPublishNotificationRequest : ActionRequest { val baseMessage: LegacyBaseMessage - val feature: String companion object { /** @@ -35,14 +34,11 @@ class LegacyPublishNotificationRequest : ActionRequest { /** * constructor for creating the class * @param baseMessage the base message to send - * @param feature the feature that is trying to use this request */ constructor( - baseMessage: LegacyBaseMessage, - feature: String + baseMessage: LegacyBaseMessage ) { this.baseMessage = baseMessage - this.feature = feature } /** @@ -55,7 +51,6 @@ class LegacyPublishNotificationRequest : ActionRequest { LegacyDestinationType.LEGACY_CUSTOM_WEBHOOK -> LegacyCustomWebhookMessage(input) LegacyDestinationType.LEGACY_SLACK -> LegacySlackMessage(input) } - feature = input.readString() } /** @@ -66,7 +61,6 @@ class LegacyPublishNotificationRequest : ActionRequest { super.writeTo(output) output.writeEnum(baseMessage.channelType) baseMessage.writeTo(output) - output.writeString(feature) } /** diff --git a/src/main/kotlin/org/opensearch/commons/notifications/action/NotificationsActions.kt b/src/main/kotlin/org/opensearch/commons/notifications/action/NotificationsActions.kt index 10605cac..ca8dd2d7 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/action/NotificationsActions.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/action/NotificationsActions.kt @@ -52,7 +52,7 @@ object NotificationsActions { /** * Publish legacy notification message. Internal only - Inter plugin communication. - * Only for the Index Management plugin. + * Only for the Alerting and Index Management plugins. */ const val LEGACY_PUBLISH_NOTIFICATION_NAME = "cluster:admin/opensearch/notifications/feature/publish" @@ -106,7 +106,7 @@ object NotificationsActions { /** * Send legacy notification transport action type. Internal only - Inter plugin communication. - * Only for the Index Management plugin. + * Only for the Alerting and Index Management plugins. */ val LEGACY_PUBLISH_NOTIFICATION_ACTION_TYPE = ActionType(LEGACY_PUBLISH_NOTIFICATION_NAME, ::LegacyPublishNotificationResponse) diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/EventSource.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/EventSource.kt index 06b28bee..10bf04e3 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/EventSource.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/EventSource.kt @@ -12,7 +12,6 @@ import org.opensearch.common.xcontent.ToXContent import org.opensearch.common.xcontent.XContentBuilder import org.opensearch.common.xcontent.XContentParser import org.opensearch.common.xcontent.XContentParserUtils -import org.opensearch.commons.notifications.NotificationConstants.FEATURE_TAG import org.opensearch.commons.notifications.NotificationConstants.REFERENCE_ID_TAG import org.opensearch.commons.notifications.NotificationConstants.SEVERITY_TAG import org.opensearch.commons.notifications.NotificationConstants.TAGS_TAG @@ -27,7 +26,6 @@ import java.io.IOException data class EventSource( val title: String, val referenceId: String, - val feature: String, val severity: SeverityType = SeverityType.INFO, val tags: List = listOf() ) : BaseModel { @@ -53,7 +51,6 @@ data class EventSource( fun parse(parser: XContentParser): EventSource { var title: String? = null var referenceId: String? = null - var feature: String? = null var severity: SeverityType = SeverityType.INFO var tags: List = emptyList() @@ -68,7 +65,6 @@ data class EventSource( when (fieldName) { TITLE_TAG -> title = parser.text() REFERENCE_ID_TAG -> referenceId = parser.text() - FEATURE_TAG -> feature = parser.text() SEVERITY_TAG -> severity = SeverityType.fromTagOrDefault(parser.text()) TAGS_TAG -> tags = parser.stringList() else -> { @@ -79,12 +75,10 @@ data class EventSource( } title ?: throw IllegalArgumentException("$TITLE_TAG field absent") referenceId ?: throw IllegalArgumentException("$REFERENCE_ID_TAG field absent") - feature ?: throw IllegalArgumentException("$FEATURE_TAG field absent") return EventSource( title, referenceId, - feature, severity, tags ) @@ -99,7 +93,6 @@ data class EventSource( return builder.startObject() .field(TITLE_TAG, title) .field(REFERENCE_ID_TAG, referenceId) - .field(FEATURE_TAG, feature) .field(SEVERITY_TAG, severity.tag) .field(TAGS_TAG, tags) .endObject() @@ -112,7 +105,6 @@ data class EventSource( constructor(input: StreamInput) : this( title = input.readString(), referenceId = input.readString(), - feature = input.readString(), severity = input.readEnum(SeverityType::class.java), tags = input.readStringList() ) @@ -123,7 +115,6 @@ data class EventSource( override fun writeTo(output: StreamOutput) { output.writeString(title) output.writeString(referenceId) - output.writeString(feature) output.writeEnum(severity) output.writeStringCollection(tags) } diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationConfig.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationConfig.kt index e80a5497..f490e8b1 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationConfig.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationConfig.kt @@ -14,17 +14,13 @@ import org.opensearch.common.xcontent.XContentParser import org.opensearch.common.xcontent.XContentParserUtils import org.opensearch.commons.notifications.NotificationConstants.CONFIG_TYPE_TAG import org.opensearch.commons.notifications.NotificationConstants.DESCRIPTION_TAG -import org.opensearch.commons.notifications.NotificationConstants.FEATURE_LIST_TAG import org.opensearch.commons.notifications.NotificationConstants.IS_ENABLED_TAG import org.opensearch.commons.notifications.NotificationConstants.NAME_TAG import org.opensearch.commons.notifications.model.config.ConfigDataProperties.createConfigData import org.opensearch.commons.notifications.model.config.ConfigDataProperties.getReaderForConfigType import org.opensearch.commons.notifications.model.config.ConfigDataProperties.validateConfigData -import org.opensearch.commons.utils.STRING_READER -import org.opensearch.commons.utils.STRING_WRITER import org.opensearch.commons.utils.fieldIfNotNull import org.opensearch.commons.utils.logger -import org.opensearch.commons.utils.stringList import java.io.IOException /** @@ -34,7 +30,6 @@ data class NotificationConfig( val name: String, val description: String, val configType: ConfigType, - val features: Set, val configData: BaseConfigData?, val isEnabled: Boolean = true ) : BaseModel { @@ -68,7 +63,6 @@ data class NotificationConfig( var name: String? = null var description = "" var configType: ConfigType? = null - var features: Set? = null var isEnabled = true var configData: BaseConfigData? = null XContentParserUtils.ensureExpectedToken( @@ -83,7 +77,6 @@ data class NotificationConfig( NAME_TAG -> name = parser.text() DESCRIPTION_TAG -> description = parser.text() CONFIG_TYPE_TAG -> configType = ConfigType.fromTagOrDefault(parser.text()) - FEATURE_LIST_TAG -> features = parser.stringList().toSet() IS_ENABLED_TAG -> isEnabled = parser.booleanValue() else -> { val configTypeForTag = ConfigType.fromTagOrDefault(fieldName) @@ -98,12 +91,10 @@ data class NotificationConfig( } name ?: throw IllegalArgumentException("$NAME_TAG field absent") configType ?: throw IllegalArgumentException("$CONFIG_TYPE_TAG field absent") - features ?: throw IllegalArgumentException("$FEATURE_LIST_TAG field absent") return NotificationConfig( name, description, configType, - features, configData, isEnabled ) @@ -119,7 +110,6 @@ data class NotificationConfig( .field(NAME_TAG, name) .field(DESCRIPTION_TAG, description) .field(CONFIG_TYPE_TAG, configType.tag) - .field(FEATURE_LIST_TAG, features) .field(IS_ENABLED_TAG, isEnabled) .fieldIfNotNull(configType.tag, configData) .endObject() @@ -133,7 +123,6 @@ data class NotificationConfig( name = input.readString(), description = input.readString(), configType = input.readEnum(ConfigType::class.java), - features = input.readSet(STRING_READER), isEnabled = input.readBoolean(), configData = input.readOptionalWriteable(getReaderForConfigType(input.readEnum(ConfigType::class.java))) ) @@ -145,7 +134,6 @@ data class NotificationConfig( output.writeString(name) output.writeString(description) output.writeEnum(configType) - output.writeCollection(features, STRING_WRITER) output.writeBoolean(isEnabled) // Reading config types multiple times in constructor output.writeEnum(configType) diff --git a/src/test/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterfaceTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterfaceTests.kt index 8147650f..f6d3f9c1 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterfaceTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterfaceTests.kt @@ -21,9 +21,6 @@ import org.opensearch.action.ActionListener import org.opensearch.action.ActionType import org.opensearch.client.node.NodeClient import org.opensearch.commons.destination.response.LegacyDestinationResponse -import org.opensearch.commons.notifications.NotificationConstants.FEATURE_ALERTING -import org.opensearch.commons.notifications.NotificationConstants.FEATURE_INDEX_MANAGEMENT -import org.opensearch.commons.notifications.NotificationConstants.FEATURE_REPORTS import org.opensearch.commons.notifications.action.CreateNotificationConfigRequest import org.opensearch.commons.notifications.action.CreateNotificationConfigResponse import org.opensearch.commons.notifications.action.DeleteNotificationConfigRequest @@ -198,7 +195,6 @@ internal class NotificationsPluginInterfaceTests { val notificationInfo = EventSource( "title", "reference_id", - FEATURE_REPORTS, SeverityType.HIGH, listOf("tag1", "tag2") ) @@ -235,10 +231,6 @@ internal class NotificationsPluginInterfaceTests { .onResponse(res) }.whenever(client).execute(any(ActionType::class.java), any(), any()) - doAnswer { - FEATURE_INDEX_MANAGEMENT - }.whenever(request).feature - NotificationsPluginInterface.publishLegacyNotification(client, request, l) verify(l, times(1)).onResponse(eq(res)) } @@ -249,7 +241,6 @@ internal class NotificationsPluginInterfaceTests { "name", "description", ConfigType.SLACK, - setOf(FEATURE_REPORTS), configData = sampleSlack ) val configInfo = NotificationConfigInfo( @@ -265,7 +256,6 @@ internal class NotificationsPluginInterfaceTests { val sampleEventSource = EventSource( "title", "reference_id", - FEATURE_ALERTING, severity = SeverityType.INFO ) val sampleStatus = EventStatus( diff --git a/src/test/kotlin/org/opensearch/commons/notifications/action/CreateNotificationConfigRequestTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/action/CreateNotificationConfigRequestTests.kt index 9eb1de1f..24f389e2 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/action/CreateNotificationConfigRequestTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/action/CreateNotificationConfigRequestTests.kt @@ -9,7 +9,6 @@ import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Assertions.assertNull import org.junit.jupiter.api.Test import org.junit.jupiter.api.assertThrows -import org.opensearch.commons.notifications.NotificationConstants.FEATURE_INDEX_MANAGEMENT import org.opensearch.commons.notifications.model.Chime import org.opensearch.commons.notifications.model.ConfigType import org.opensearch.commons.notifications.model.Email @@ -32,9 +31,8 @@ internal class CreateNotificationConfigRequestTests { "name", "description", ConfigType.WEBHOOK, - setOf(FEATURE_INDEX_MANAGEMENT), - isEnabled = true, - configData = sampleWebhook + configData = sampleWebhook, + isEnabled = true ) } @@ -44,9 +42,8 @@ internal class CreateNotificationConfigRequestTests { "name", "description", ConfigType.SLACK, - setOf(FEATURE_INDEX_MANAGEMENT), - isEnabled = true, - configData = sampleSlack + configData = sampleSlack, + isEnabled = true ) } @@ -56,9 +53,8 @@ internal class CreateNotificationConfigRequestTests { "name", "description", ConfigType.CHIME, - setOf(FEATURE_INDEX_MANAGEMENT), - isEnabled = true, - configData = sampleChime + configData = sampleChime, + isEnabled = true ) } @@ -68,9 +64,8 @@ internal class CreateNotificationConfigRequestTests { "name", "description", ConfigType.EMAIL_GROUP, - setOf(FEATURE_INDEX_MANAGEMENT), - isEnabled = true, - configData = sampleEmailGroup + configData = sampleEmailGroup, + isEnabled = true ) } @@ -84,9 +79,8 @@ internal class CreateNotificationConfigRequestTests { "name", "description", ConfigType.EMAIL, - setOf(FEATURE_INDEX_MANAGEMENT), - isEnabled = true, - configData = sampleEmail + configData = sampleEmail, + isEnabled = true ) } @@ -101,9 +95,8 @@ internal class CreateNotificationConfigRequestTests { "name", "description", ConfigType.SMTP_ACCOUNT, - setOf(FEATURE_INDEX_MANAGEMENT), - isEnabled = true, - configData = sampleSmtpAccount + configData = sampleSmtpAccount, + isEnabled = true ) } @@ -264,9 +257,8 @@ internal class CreateNotificationConfigRequestTests { "name", "description", ConfigType.SLACK, - setOf(FEATURE_INDEX_MANAGEMENT), - isEnabled = true, - configData = sampleSlack + configData = sampleSlack, + isEnabled = true ) val jsonString = """ @@ -275,7 +267,6 @@ internal class CreateNotificationConfigRequestTests { "name":"name", "description":"description", "config_type":"slack", - "feature_list":["index_management"], "is_enabled":true, "slack":{"url":"https://domain.com/sample_slack_url#1234567890"} } @@ -292,9 +283,8 @@ internal class CreateNotificationConfigRequestTests { "name", "description", ConfigType.WEBHOOK, - setOf(FEATURE_INDEX_MANAGEMENT), - isEnabled = true, - configData = sampleWebhook + configData = sampleWebhook, + isEnabled = true ) val jsonString = """ @@ -303,7 +293,6 @@ internal class CreateNotificationConfigRequestTests { "name":"name", "description":"description", "config_type":"webhook", - "feature_list":["index_management"], "is_enabled":true, "webhook":{"url":"https://domain.com/sample_webhook_url#1234567890"} } @@ -320,9 +309,8 @@ internal class CreateNotificationConfigRequestTests { "name", "description", ConfigType.CHIME, - setOf(FEATURE_INDEX_MANAGEMENT), - isEnabled = true, - configData = sampleChime + configData = sampleChime, + isEnabled = true ) val jsonString = """ @@ -332,7 +320,6 @@ internal class CreateNotificationConfigRequestTests { "name":"name", "description":"description", "config_type":"chime", - "feature_list":["index_management"], "is_enabled":true, "chime":{"url":"https://domain.com/sample_chime_url#1234567890"} } @@ -349,9 +336,8 @@ internal class CreateNotificationConfigRequestTests { "name", "description", ConfigType.EMAIL_GROUP, - setOf(FEATURE_INDEX_MANAGEMENT), - isEnabled = true, - configData = sampleEmailGroup + configData = sampleEmailGroup, + isEnabled = true ) val jsonString = """ @@ -361,7 +347,6 @@ internal class CreateNotificationConfigRequestTests { "name":"name", "description":"description", "config_type":"email_group", - "feature_list":["index_management"], "is_enabled":true, "email_group":{"recipient_list":[{"recipient":"dummy@company.com"}]} } @@ -382,9 +367,8 @@ internal class CreateNotificationConfigRequestTests { "name", "description", ConfigType.EMAIL, - setOf(FEATURE_INDEX_MANAGEMENT), - isEnabled = true, - configData = sampleEmail + configData = sampleEmail, + isEnabled = true ) val jsonString = """ @@ -394,7 +378,6 @@ internal class CreateNotificationConfigRequestTests { "name":"name", "description":"description", "config_type":"email", - "feature_list":["index_management"], "is_enabled":true, "email":{ "email_account_id":"sample_1@dummy.com", @@ -420,9 +403,8 @@ internal class CreateNotificationConfigRequestTests { "name", "description", ConfigType.SMTP_ACCOUNT, - setOf(FEATURE_INDEX_MANAGEMENT), - isEnabled = true, - configData = sampleSmtpAccount + configData = sampleSmtpAccount, + isEnabled = true ) val jsonString = """ @@ -432,7 +414,6 @@ internal class CreateNotificationConfigRequestTests { "name":"name", "description":"description", "config_type":"smtp_account", - "feature_list":["index_management"], "is_enabled":true, "smtp_account":{"host":"http://dummy.com", "port":11,"method": "ssl", "from_address": "sample@dummy.com" } } @@ -463,7 +444,6 @@ internal class CreateNotificationConfigRequestTests { "name":"name", "description":"description", "config_type":"chime", - "feature_list":["index_management"], "is_enabled":true, "chime":{"url":"https://domain.com/sample_chime_url#1234567890"} } @@ -488,9 +468,8 @@ internal class CreateNotificationConfigRequestTests { "name", "description", ConfigType.SLACK, - setOf(FEATURE_INDEX_MANAGEMENT), - isEnabled = true, - configData = sampleSlack + configData = sampleSlack, + isEnabled = true ) val jsonString = """ @@ -499,7 +478,6 @@ internal class CreateNotificationConfigRequestTests { "name":"name", "description":"description", "config_type":"slack", - "feature_list":["index_management"], "is_enabled":true, "slack":{"url":"https://domain.com/sample_slack_url#1234567890"}, "extra_field_1":["extra", "value"], diff --git a/src/test/kotlin/org/opensearch/commons/notifications/action/GetFeatureChannelListRequestTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/action/GetFeatureChannelListRequestTests.kt index 98d577de..b9913ae2 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/action/GetFeatureChannelListRequestTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/action/GetFeatureChannelListRequestTests.kt @@ -8,9 +8,6 @@ import com.fasterxml.jackson.core.JsonParseException import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Test import org.junit.jupiter.api.assertThrows -import org.opensearch.commons.notifications.NotificationConstants.FEATURE_ALERTING -import org.opensearch.commons.notifications.NotificationConstants.FEATURE_INDEX_MANAGEMENT -import org.opensearch.commons.notifications.NotificationConstants.FEATURE_REPORTS import org.opensearch.commons.utils.createObjectFromJsonString import org.opensearch.commons.utils.getJsonString import org.opensearch.commons.utils.recreateObject @@ -21,19 +18,19 @@ internal class GetFeatureChannelListRequestTests { expected: GetFeatureChannelListRequest, actual: GetFeatureChannelListRequest ) { - assertEquals(expected.feature, actual.feature) + assertEquals(expected.compact, actual.compact) } @Test fun `Get request serialize and deserialize transport object should be equal`() { - val configRequest = GetFeatureChannelListRequest(FEATURE_REPORTS) + val configRequest = GetFeatureChannelListRequest() val recreatedObject = recreateObject(configRequest) { GetFeatureChannelListRequest(it) } assertGetRequestEquals(configRequest, recreatedObject) } @Test fun `Get request serialize and deserialize using json object should be equal`() { - val configRequest = GetFeatureChannelListRequest(FEATURE_INDEX_MANAGEMENT) + val configRequest = GetFeatureChannelListRequest() val jsonString = getJsonString(configRequest) val recreatedObject = createObjectFromJsonString(jsonString) { GetFeatureChannelListRequest.parse(it) } assertGetRequestEquals(configRequest, recreatedObject) @@ -49,10 +46,9 @@ internal class GetFeatureChannelListRequestTests { @Test fun `Get request should safely ignore extra field in json object`() { - val configRequest = GetFeatureChannelListRequest(FEATURE_ALERTING) + val configRequest = GetFeatureChannelListRequest() val jsonString = """ { - "feature":"${configRequest.feature}", "extra_field_1":["extra", "value"], "extra_field_2":{"extra":"value"}, "extra_field_3":"extra value 3" @@ -61,15 +57,4 @@ internal class GetFeatureChannelListRequestTests { val recreatedObject = createObjectFromJsonString(jsonString) { GetFeatureChannelListRequest.parse(it) } assertGetRequestEquals(configRequest, recreatedObject) } - - @Test - fun `Get request should throw exception if feature field is absent in json object`() { - val jsonString = """ - { - } - """.trimIndent() - assertThrows { - createObjectFromJsonString(jsonString) { GetFeatureChannelListRequest.parse(it) } - } - } } diff --git a/src/test/kotlin/org/opensearch/commons/notifications/action/GetNotificationConfigResponseTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/action/GetNotificationConfigResponseTests.kt index 7541acb2..3cfccfcb 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/action/GetNotificationConfigResponseTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/action/GetNotificationConfigResponseTests.kt @@ -8,8 +8,6 @@ import org.apache.lucene.search.TotalHits import org.junit.jupiter.api.Assertions import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Test -import org.opensearch.commons.notifications.NotificationConstants.FEATURE_INDEX_MANAGEMENT -import org.opensearch.commons.notifications.NotificationConstants.FEATURE_REPORTS import org.opensearch.commons.notifications.model.Chime import org.opensearch.commons.notifications.model.ConfigType import org.opensearch.commons.notifications.model.NotificationConfig @@ -41,7 +39,6 @@ internal class GetNotificationConfigResponseTests { "name", "description", ConfigType.SLACK, - setOf(FEATURE_REPORTS), configData = sampleSlack ) val configInfo = NotificationConfigInfo( @@ -62,7 +59,6 @@ internal class GetNotificationConfigResponseTests { "name", "description", ConfigType.SLACK, - setOf(FEATURE_REPORTS), configData = Slack("https://domain.com/sample_url#1234567890") ) val configInfo1 = NotificationConfigInfo( @@ -75,7 +71,6 @@ internal class GetNotificationConfigResponseTests { "name", "description", ConfigType.CHIME, - setOf(FEATURE_INDEX_MANAGEMENT), configData = Chime("https://domain.com/sample_url#1234567890") ) val configInfo2 = NotificationConfigInfo( @@ -104,7 +99,6 @@ internal class GetNotificationConfigResponseTests { "name", "description", ConfigType.SLACK, - setOf(FEATURE_REPORTS), configData = sampleSlack ) val configInfo = NotificationConfigInfo( @@ -128,7 +122,6 @@ internal class GetNotificationConfigResponseTests { "name", "description", ConfigType.SLACK, - setOf(FEATURE_REPORTS), configData = Slack("https://domain.com/sample_url#1234567890") ) val configInfo1 = NotificationConfigInfo( @@ -141,7 +134,6 @@ internal class GetNotificationConfigResponseTests { "name", "description", ConfigType.CHIME, - setOf(FEATURE_INDEX_MANAGEMENT), configData = Chime("https://domain.com/sample_url#1234567890") ) val configInfo2 = NotificationConfigInfo( @@ -171,9 +163,8 @@ internal class GetNotificationConfigResponseTests { "name", "description", ConfigType.SLACK, - setOf(FEATURE_INDEX_MANAGEMENT), - isEnabled = true, - configData = sampleSlack + configData = sampleSlack, + isEnabled = true ) val configInfo = NotificationConfigInfo( "config-Id", @@ -196,7 +187,6 @@ internal class GetNotificationConfigResponseTests { "name":"name", "description":"description", "config_type":"slack", - "feature_list":["index_management"], "is_enabled":true, "slack":{"url":"https://domain.com/sample_slack_url#1234567890"} } @@ -220,9 +210,8 @@ internal class GetNotificationConfigResponseTests { "name", "description", ConfigType.SLACK, - setOf(FEATURE_INDEX_MANAGEMENT), - isEnabled = true, - configData = sampleSlack + configData = sampleSlack, + isEnabled = true ) val configInfo = NotificationConfigInfo( "config-Id", @@ -242,7 +231,6 @@ internal class GetNotificationConfigResponseTests { "name":"name", "description":"description", "config_type":"slack", - "feature_list":["index_management"], "is_enabled":true, "slack":{"url":"https://domain.com/sample_slack_url#1234567890"} } diff --git a/src/test/kotlin/org/opensearch/commons/notifications/action/GetNotificationEventResponseTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/action/GetNotificationEventResponseTests.kt index 16139bb1..0de1c78b 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/action/GetNotificationEventResponseTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/action/GetNotificationEventResponseTests.kt @@ -8,8 +8,6 @@ import org.apache.lucene.search.TotalHits import org.junit.jupiter.api.Assertions import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Test -import org.opensearch.commons.notifications.NotificationConstants.FEATURE_ALERTING -import org.opensearch.commons.notifications.NotificationConstants.FEATURE_REPORTS import org.opensearch.commons.notifications.model.ConfigType import org.opensearch.commons.notifications.model.DeliveryStatus import org.opensearch.commons.notifications.model.EventSource @@ -41,7 +39,6 @@ internal class GetNotificationEventResponseTests { val sampleEventSource = EventSource( "title", "reference_id", - FEATURE_ALERTING, severity = SeverityType.INFO ) val sampleStatus = EventStatus( @@ -68,13 +65,11 @@ internal class GetNotificationEventResponseTests { val eventSource1 = EventSource( "title 1", "reference_id_1", - FEATURE_ALERTING, severity = SeverityType.INFO ) val eventSource2 = EventSource( "title 2", "reference_id_2", - FEATURE_REPORTS, severity = SeverityType.HIGH ) val status1 = EventStatus( @@ -131,7 +126,6 @@ internal class GetNotificationEventResponseTests { val sampleEventSource = EventSource( "title", "reference_id", - FEATURE_ALERTING, severity = SeverityType.INFO ) val sampleStatus = EventStatus( @@ -161,13 +155,11 @@ internal class GetNotificationEventResponseTests { val eventSource1 = EventSource( "title 1", "reference_id_1", - FEATURE_ALERTING, severity = SeverityType.INFO ) val eventSource2 = EventSource( "title 2", "reference_id_2", - FEATURE_REPORTS, severity = SeverityType.HIGH ) val status1 = EventStatus( @@ -213,7 +205,6 @@ internal class GetNotificationEventResponseTests { val sampleEventSource = EventSource( "title", "reference_id", - FEATURE_ALERTING, severity = SeverityType.INFO ) val sampleStatus = EventStatus( @@ -244,7 +235,6 @@ internal class GetNotificationEventResponseTests { "event_source":{ "title":"title", "reference_id":"reference_id", - "feature":"alerting", "severity":"info", "tags":[] }, @@ -279,7 +269,6 @@ internal class GetNotificationEventResponseTests { val sampleEventSource = EventSource( "title", "reference_id", - FEATURE_ALERTING, severity = SeverityType.INFO ) val sampleStatus = EventStatus( @@ -307,7 +296,6 @@ internal class GetNotificationEventResponseTests { "event_source":{ "title":"title", "reference_id":"reference_id", - "feature":"alerting", "severity":"info", "tags":[] }, diff --git a/src/test/kotlin/org/opensearch/commons/notifications/action/LegacyPublishNotificationRequestTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/action/LegacyPublishNotificationRequestTests.kt index c323ec85..e4b990a5 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/action/LegacyPublishNotificationRequestTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/action/LegacyPublishNotificationRequestTests.kt @@ -9,7 +9,6 @@ import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Assertions.assertNull import org.junit.jupiter.api.Test import org.opensearch.commons.destination.message.LegacyChimeMessage -import org.opensearch.commons.notifications.NotificationConstants.FEATURE_INDEX_MANAGEMENT import org.opensearch.commons.utils.recreateObject internal class LegacyPublishNotificationRequestTests { @@ -22,14 +21,13 @@ internal class LegacyPublishNotificationRequestTests { assertEquals(expected.baseMessage.channelType, actual.baseMessage.channelType) assertEquals(expected.baseMessage.messageContent, actual.baseMessage.messageContent) assertEquals(expected.baseMessage.url, actual.baseMessage.url) - assertEquals(expected.feature, actual.feature) assertNull(actual.validate()) } @Test fun `publish request serialize and deserialize transport object should be equal`() { val baseMessage = LegacyChimeMessage.Builder("chime_message").withMessage("Hello world").withUrl("https://amazon.com").build() - val request = LegacyPublishNotificationRequest(baseMessage, FEATURE_INDEX_MANAGEMENT) + val request = LegacyPublishNotificationRequest(baseMessage) val recreatedObject = recreateObject(request) { LegacyPublishNotificationRequest(it) } assertRequestEquals(request, recreatedObject) } diff --git a/src/test/kotlin/org/opensearch/commons/notifications/action/SendNotificationRequestTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/action/SendNotificationRequestTests.kt index 3874190c..70e0bd6c 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/action/SendNotificationRequestTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/action/SendNotificationRequestTests.kt @@ -10,9 +10,6 @@ import org.junit.jupiter.api.Assertions.assertNotNull import org.junit.jupiter.api.Assertions.assertNull import org.junit.jupiter.api.Test import org.junit.jupiter.api.assertThrows -import org.opensearch.commons.notifications.NotificationConstants.FEATURE_ALERTING -import org.opensearch.commons.notifications.NotificationConstants.FEATURE_INDEX_MANAGEMENT -import org.opensearch.commons.notifications.NotificationConstants.FEATURE_REPORTS import org.opensearch.commons.notifications.model.ChannelMessage import org.opensearch.commons.notifications.model.EventSource import org.opensearch.commons.notifications.model.SeverityType @@ -38,7 +35,6 @@ internal class SendNotificationRequestTests { val notificationInfo = EventSource( "title", "reference_id", - FEATURE_REPORTS, SeverityType.HIGH, listOf("tag1", "tag2") ) @@ -62,7 +58,6 @@ internal class SendNotificationRequestTests { val notificationInfo = EventSource( "title", "reference_id", - FEATURE_INDEX_MANAGEMENT, SeverityType.CRITICAL, listOf("tag1", "tag2") ) @@ -95,7 +90,6 @@ internal class SendNotificationRequestTests { val notificationInfo = EventSource( "title", "reference_id", - FEATURE_ALERTING, SeverityType.HIGH, listOf("tag1", "tag2") ) @@ -115,7 +109,6 @@ internal class SendNotificationRequestTests { "event_source":{ "title":"${notificationInfo.title}", "reference_id":"${notificationInfo.referenceId}", - "feature":"${notificationInfo.feature}", "severity":"${notificationInfo.severity}", "tags":["tag1", "tag2"] }, @@ -139,7 +132,6 @@ internal class SendNotificationRequestTests { val notificationInfo = EventSource( "title", "reference_id", - FEATURE_REPORTS, SeverityType.INFO, listOf("tag1", "tag2") ) @@ -159,7 +151,6 @@ internal class SendNotificationRequestTests { "event_source":{ "title":"${notificationInfo.title}", "reference_id":"${notificationInfo.referenceId}", - "feature":"${notificationInfo.feature}", "severity":"${notificationInfo.severity}", "tags":["tag1", "tag2"] }, @@ -196,7 +187,6 @@ internal class SendNotificationRequestTests { "event_source":{ "title":"title", "reference_id":"reference_id", - "feature":"feature", "severity":"High", "tags":["tag1", "tag2"] }, @@ -215,7 +205,6 @@ internal class SendNotificationRequestTests { "event_source":{ "title":"title", "reference_id":"reference_id", - "feature":"feature", "severity":"High", "tags":["tag1", "tag2"] }, @@ -236,7 +225,6 @@ internal class SendNotificationRequestTests { "event_source":{ "title":"title", "reference_id":"reference_id", - "feature":"feature", "severity":"High", "tags":["tag1", "tag2"] }, diff --git a/src/test/kotlin/org/opensearch/commons/notifications/action/UpdateNotificationConfigRequestTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/action/UpdateNotificationConfigRequestTests.kt index 725e3c59..a6e0077a 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/action/UpdateNotificationConfigRequestTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/action/UpdateNotificationConfigRequestTests.kt @@ -9,7 +9,6 @@ import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Assertions.assertNull import org.junit.jupiter.api.Test import org.junit.jupiter.api.assertThrows -import org.opensearch.commons.notifications.NotificationConstants.FEATURE_INDEX_MANAGEMENT import org.opensearch.commons.notifications.model.Chime import org.opensearch.commons.notifications.model.ConfigType import org.opensearch.commons.notifications.model.Email @@ -32,9 +31,8 @@ internal class UpdateNotificationConfigRequestTests { "name", "description", ConfigType.WEBHOOK, - setOf(FEATURE_INDEX_MANAGEMENT), - isEnabled = true, - configData = sampleWebhook + configData = sampleWebhook, + isEnabled = true ) } @@ -44,9 +42,8 @@ internal class UpdateNotificationConfigRequestTests { "name", "description", ConfigType.SLACK, - setOf(FEATURE_INDEX_MANAGEMENT), - isEnabled = true, - configData = sampleSlack + configData = sampleSlack, + isEnabled = true ) } @@ -56,9 +53,8 @@ internal class UpdateNotificationConfigRequestTests { "name", "description", ConfigType.CHIME, - setOf(FEATURE_INDEX_MANAGEMENT), - isEnabled = true, - configData = sampleChime + configData = sampleChime, + isEnabled = true ) } @@ -68,9 +64,8 @@ internal class UpdateNotificationConfigRequestTests { "name", "description", ConfigType.EMAIL_GROUP, - setOf(FEATURE_INDEX_MANAGEMENT), - isEnabled = true, - configData = sampleEmailGroup + configData = sampleEmailGroup, + isEnabled = true ) } @@ -84,9 +79,8 @@ internal class UpdateNotificationConfigRequestTests { "name", "description", ConfigType.EMAIL, - setOf(FEATURE_INDEX_MANAGEMENT), - isEnabled = true, - configData = sampleEmail + configData = sampleEmail, + isEnabled = true ) } @@ -101,9 +95,8 @@ internal class UpdateNotificationConfigRequestTests { "name", "description", ConfigType.SMTP_ACCOUNT, - setOf(FEATURE_INDEX_MANAGEMENT), - isEnabled = true, - configData = sampleSmtpAccount + configData = sampleSmtpAccount, + isEnabled = true ) } @@ -228,9 +221,8 @@ internal class UpdateNotificationConfigRequestTests { "name", "description", ConfigType.SLACK, - setOf(FEATURE_INDEX_MANAGEMENT), - isEnabled = true, - configData = sampleSlack + configData = sampleSlack, + isEnabled = true ) val jsonString = """ @@ -258,9 +250,8 @@ internal class UpdateNotificationConfigRequestTests { "name", "description", ConfigType.WEBHOOK, - setOf(FEATURE_INDEX_MANAGEMENT), - isEnabled = true, - configData = sampleWebhook + configData = sampleWebhook, + isEnabled = true ) val jsonString = """ @@ -288,9 +279,8 @@ internal class UpdateNotificationConfigRequestTests { "name", "description", ConfigType.CHIME, - setOf(FEATURE_INDEX_MANAGEMENT), - isEnabled = true, - configData = sampleChime + configData = sampleChime, + isEnabled = true ) val jsonString = """ @@ -318,9 +308,8 @@ internal class UpdateNotificationConfigRequestTests { "name", "description", ConfigType.EMAIL_GROUP, - setOf(FEATURE_INDEX_MANAGEMENT), - isEnabled = true, - configData = sampleEmailGroup + configData = sampleEmailGroup, + isEnabled = true ) val jsonString = """ @@ -352,9 +341,8 @@ internal class UpdateNotificationConfigRequestTests { "name", "description", ConfigType.EMAIL, - setOf(FEATURE_INDEX_MANAGEMENT), - isEnabled = true, - configData = sampleEmail + configData = sampleEmail, + isEnabled = true ) val jsonString = """ @@ -391,9 +379,8 @@ internal class UpdateNotificationConfigRequestTests { "name", "description", ConfigType.SMTP_ACCOUNT, - setOf(FEATURE_INDEX_MANAGEMENT), - isEnabled = true, - configData = sampleSmtpAccount + configData = sampleSmtpAccount, + isEnabled = true ) val jsonString = """ @@ -429,9 +416,8 @@ internal class UpdateNotificationConfigRequestTests { "name", "description", ConfigType.SLACK, - setOf(FEATURE_INDEX_MANAGEMENT), - isEnabled = true, - configData = sampleSlack + configData = sampleSlack, + isEnabled = true ) val jsonString = """ diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/EventSourceTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/EventSourceTests.kt index 2244d0c4..b36a2fc0 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/EventSourceTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/EventSourceTests.kt @@ -7,7 +7,6 @@ package org.opensearch.commons.notifications.model import org.junit.jupiter.api.Assertions import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Test -import org.opensearch.commons.notifications.NotificationConstants.FEATURE_ALERTING import org.opensearch.commons.utils.createObjectFromJsonString import org.opensearch.commons.utils.getJsonString import org.opensearch.commons.utils.recreateObject @@ -19,7 +18,6 @@ internal class EventSourceTests { val sampleEventSource = EventSource( "title", "reference_id", - FEATURE_ALERTING, severity = SeverityType.INFO ) val recreatedObject = recreateObject(sampleEventSource) { EventSource(it) } @@ -31,7 +29,6 @@ internal class EventSourceTests { val sampleEventSource = EventSource( "title", "reference_id", - FEATURE_ALERTING, severity = SeverityType.INFO ) @@ -45,9 +42,8 @@ internal class EventSourceTests { val sampleEventSource = EventSource( "title", "reference_id", - FEATURE_ALERTING, - tags = listOf("tag1", "tag2"), - severity = SeverityType.INFO + severity = SeverityType.INFO, + tags = listOf("tag1", "tag2") ) val jsonString = """ { @@ -70,9 +66,8 @@ internal class EventSourceTests { val sampleEventSource = EventSource( "title", "reference_id", - "NewFeature", - tags = listOf("tag1", "tag2"), - severity = SeverityType.INFO + severity = SeverityType.INFO, + tags = listOf("tag1", "tag2") ) val jsonString = """ { @@ -93,9 +88,8 @@ internal class EventSourceTests { EventSource( "", "reference_id", - FEATURE_ALERTING, - tags = listOf("tag1", "tag2"), - severity = SeverityType.INFO + severity = SeverityType.INFO, + tags = listOf("tag1", "tag2") ) } } diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationConfigInfoTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationConfigInfoTests.kt index d14b9f34..c4e28f33 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationConfigInfoTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationConfigInfoTests.kt @@ -7,8 +7,6 @@ package org.opensearch.commons.notifications.model import org.junit.jupiter.api.Assertions import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Test -import org.opensearch.commons.notifications.NotificationConstants.FEATURE_INDEX_MANAGEMENT -import org.opensearch.commons.notifications.NotificationConstants.FEATURE_REPORTS import org.opensearch.commons.utils.createObjectFromJsonString import org.opensearch.commons.utils.getJsonString import org.opensearch.commons.utils.recreateObject @@ -23,7 +21,6 @@ internal class NotificationConfigInfoTests { "name", "description", ConfigType.SLACK, - setOf(FEATURE_REPORTS), configData = sampleSlack ) val configInfo = NotificationConfigInfo( @@ -45,7 +42,6 @@ internal class NotificationConfigInfoTests { "name", "description", ConfigType.SLACK, - setOf(FEATURE_REPORTS), configData = sampleSlack ) val configInfo = NotificationConfigInfo( @@ -68,9 +64,8 @@ internal class NotificationConfigInfoTests { "name", "description", ConfigType.SLACK, - setOf(FEATURE_INDEX_MANAGEMENT), - isEnabled = true, - configData = sampleSlack + configData = sampleSlack, + isEnabled = true ) val configInfo = NotificationConfigInfo( "config-Id", @@ -107,7 +102,6 @@ internal class NotificationConfigInfoTests { "name", "description", ConfigType.SLACK, - setOf(FEATURE_REPORTS), configData = sampleSlack ) Assertions.assertThrows(IllegalArgumentException::class.java) { diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationConfigSearchResultsTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationConfigSearchResultsTests.kt index 835af358..06bb3557 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationConfigSearchResultsTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationConfigSearchResultsTests.kt @@ -8,8 +8,6 @@ import org.apache.lucene.search.TotalHits import org.junit.jupiter.api.Assertions import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Test -import org.opensearch.commons.notifications.NotificationConstants.FEATURE_INDEX_MANAGEMENT -import org.opensearch.commons.notifications.NotificationConstants.FEATURE_REPORTS import org.opensearch.commons.utils.createObjectFromJsonString import org.opensearch.commons.utils.getJsonString import org.opensearch.commons.utils.recreateObject @@ -35,7 +33,6 @@ internal class NotificationConfigSearchResultsTests { "name", "description", ConfigType.SLACK, - setOf(FEATURE_REPORTS), configData = sampleSlack ) val configInfo = NotificationConfigInfo( @@ -55,7 +52,6 @@ internal class NotificationConfigSearchResultsTests { "name", "description", ConfigType.SLACK, - setOf(FEATURE_REPORTS), configData = Slack("https://domain.com/sample_url#1234567890") ) val configInfo1 = NotificationConfigInfo( @@ -68,7 +64,6 @@ internal class NotificationConfigSearchResultsTests { "name", "description", ConfigType.CHIME, - setOf(FEATURE_INDEX_MANAGEMENT), configData = Chime("https://domain.com/sample_url#1234567890") ) val configInfo2 = NotificationConfigInfo( @@ -94,7 +89,6 @@ internal class NotificationConfigSearchResultsTests { "name", "description", ConfigType.SLACK, - setOf(FEATURE_REPORTS), configData = Slack("https://domain.com/sample_url#1234567890") ) val configInfo1 = NotificationConfigInfo( @@ -107,7 +101,6 @@ internal class NotificationConfigSearchResultsTests { "name", "description", ConfigType.CHIME, - setOf(FEATURE_INDEX_MANAGEMENT), configData = Chime("https://domain.com/sample_url#1234567890") ) val configInfo2 = NotificationConfigInfo( @@ -135,7 +128,6 @@ internal class NotificationConfigSearchResultsTests { "name", "description", ConfigType.SLACK, - setOf(FEATURE_REPORTS), configData = sampleSlack ) val configInfo = NotificationConfigInfo( @@ -158,7 +150,6 @@ internal class NotificationConfigSearchResultsTests { "name", "description", ConfigType.SLACK, - setOf(FEATURE_REPORTS), configData = Slack("https://domain.com/sample_url#1234567890") ) val configInfo1 = NotificationConfigInfo( @@ -171,7 +162,6 @@ internal class NotificationConfigSearchResultsTests { "name", "description", ConfigType.CHIME, - setOf(FEATURE_INDEX_MANAGEMENT), configData = Chime("https://domain.com/sample_url#1234567890") ) val configInfo2 = NotificationConfigInfo( @@ -200,9 +190,8 @@ internal class NotificationConfigSearchResultsTests { "name", "description", ConfigType.SLACK, - setOf(FEATURE_INDEX_MANAGEMENT), - isEnabled = true, - configData = sampleSlack + configData = sampleSlack, + isEnabled = true ) val configInfo = NotificationConfigInfo( "config-Id", @@ -249,9 +238,8 @@ internal class NotificationConfigSearchResultsTests { "name", "description", ConfigType.SLACK, - setOf(FEATURE_INDEX_MANAGEMENT), - isEnabled = true, - configData = sampleSlack + configData = sampleSlack, + isEnabled = true ) val configInfo = NotificationConfigInfo( "config-Id", diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationConfigTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationConfigTests.kt index 47614986..f8aa9e9d 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationConfigTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationConfigTests.kt @@ -6,9 +6,6 @@ package org.opensearch.commons.notifications.model import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Test -import org.opensearch.commons.notifications.NotificationConstants.FEATURE_ALERTING -import org.opensearch.commons.notifications.NotificationConstants.FEATURE_INDEX_MANAGEMENT -import org.opensearch.commons.notifications.NotificationConstants.FEATURE_REPORTS import org.opensearch.commons.utils.createObjectFromJsonString import org.opensearch.commons.utils.getJsonString import org.opensearch.commons.utils.recreateObject @@ -22,7 +19,6 @@ internal class NotificationConfigTests { "name", "description", ConfigType.SLACK, - setOf(FEATURE_REPORTS), configData = sampleSlack ) val recreatedObject = recreateObject(sampleConfig) { NotificationConfig(it) } @@ -36,7 +32,6 @@ internal class NotificationConfigTests { "name", "description", ConfigType.SLACK, - setOf(FEATURE_REPORTS), configData = sampleSlack ) val jsonString = getJsonString(sampleConfig) @@ -51,7 +46,6 @@ internal class NotificationConfigTests { "name", "description", ConfigType.CHIME, - setOf(FEATURE_ALERTING), configData = sampleChime ) val recreatedObject = recreateObject(sampleConfig) { NotificationConfig(it) } @@ -65,7 +59,6 @@ internal class NotificationConfigTests { "name", "description", ConfigType.CHIME, - setOf(FEATURE_ALERTING), configData = sampleChime ) val jsonString = getJsonString(sampleConfig) @@ -80,7 +73,6 @@ internal class NotificationConfigTests { "name", "description", ConfigType.WEBHOOK, - setOf(FEATURE_INDEX_MANAGEMENT), configData = sampleWebhook ) val recreatedObject = recreateObject(sampleConfig) { NotificationConfig(it) } @@ -94,7 +86,6 @@ internal class NotificationConfigTests { "name", "description", ConfigType.WEBHOOK, - setOf(FEATURE_INDEX_MANAGEMENT), configData = sampleWebhook ) val jsonString = getJsonString(sampleConfig) @@ -109,7 +100,6 @@ internal class NotificationConfigTests { "name", "description", ConfigType.EMAIL, - setOf(FEATURE_INDEX_MANAGEMENT), configData = sampleEmail ) val recreatedObject = recreateObject(sampleConfig) { NotificationConfig(it) } @@ -123,7 +113,6 @@ internal class NotificationConfigTests { "name", "description", ConfigType.EMAIL, - setOf(FEATURE_INDEX_MANAGEMENT), configData = sampleEmail ) val jsonString = getJsonString(sampleConfig) @@ -138,7 +127,6 @@ internal class NotificationConfigTests { "name", "description", ConfigType.SMTP_ACCOUNT, - setOf(FEATURE_INDEX_MANAGEMENT), configData = smtpAccount ) val jsonString = getJsonString(sampleConfig) @@ -153,7 +141,6 @@ internal class NotificationConfigTests { "name", "description", ConfigType.SMTP_ACCOUNT, - setOf(FEATURE_INDEX_MANAGEMENT), configData = sampleSmtpAccount ) val recreatedObject = recreateObject(sampleConfig) { NotificationConfig(it) } @@ -167,7 +154,6 @@ internal class NotificationConfigTests { "name", "description", ConfigType.EMAIL_GROUP, - setOf(FEATURE_INDEX_MANAGEMENT), configData = sampleEmailGroup ) val jsonString = getJsonString(sampleConfig) @@ -182,7 +168,6 @@ internal class NotificationConfigTests { "name", "description", ConfigType.EMAIL_GROUP, - setOf(FEATURE_INDEX_MANAGEMENT), configData = sampleEmailGroup ) val recreatedObject = recreateObject(sampleConfig) { NotificationConfig(it) } @@ -197,9 +182,8 @@ internal class NotificationConfigTests { "name", "description", ConfigType.NONE, - setOf(FEATURE_INDEX_MANAGEMENT), - isEnabled = true, - configData = sampleSlack + configData = sampleSlack, + isEnabled = true ) val jsonString = """ { @@ -226,9 +210,8 @@ internal class NotificationConfigTests { "name", "description", ConfigType.WEBHOOK, - setOf(FEATURE_INDEX_MANAGEMENT, "NewFeature1", "NewFeature2"), - isEnabled = true, - configData = sampleWebhook + configData = sampleWebhook, + isEnabled = true ) val jsonString = """ { diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationEventInfoTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationEventInfoTests.kt index a87e334a..85d2dee9 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationEventInfoTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationEventInfoTests.kt @@ -7,7 +7,6 @@ package org.opensearch.commons.notifications.model import org.junit.jupiter.api.Assertions import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Test -import org.opensearch.commons.notifications.NotificationConstants.FEATURE_ALERTING import org.opensearch.commons.utils.createObjectFromJsonString import org.opensearch.commons.utils.getJsonString import org.opensearch.commons.utils.recreateObject @@ -20,7 +19,6 @@ internal class NotificationEventInfoTests { val sampleEventSource = EventSource( "title", "reference_id", - FEATURE_ALERTING, severity = SeverityType.INFO ) val sampleStatus = EventStatus( @@ -47,7 +45,6 @@ internal class NotificationEventInfoTests { val sampleEventSource = EventSource( "title", "reference_id", - FEATURE_ALERTING, severity = SeverityType.INFO ) val sampleStatus = EventStatus( @@ -75,7 +72,6 @@ internal class NotificationEventInfoTests { val sampleEventSource = EventSource( "title", "reference_id", - FEATURE_ALERTING, severity = SeverityType.INFO ) val sampleStatus = EventStatus( @@ -133,7 +129,6 @@ internal class NotificationEventInfoTests { val sampleEventSource = EventSource( "title", "reference_id", - FEATURE_ALERTING, severity = SeverityType.INFO ) val sampleStatus = EventStatus( diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationEventSearchResultTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationEventSearchResultTests.kt index ae3f01a9..b65a0783 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationEventSearchResultTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationEventSearchResultTests.kt @@ -8,8 +8,6 @@ import org.apache.lucene.search.TotalHits import org.junit.jupiter.api.Assertions import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Test -import org.opensearch.commons.notifications.NotificationConstants.FEATURE_ALERTING -import org.opensearch.commons.notifications.NotificationConstants.FEATURE_REPORTS import org.opensearch.commons.utils.createObjectFromJsonString import org.opensearch.commons.utils.getJsonString import org.opensearch.commons.utils.recreateObject @@ -33,7 +31,6 @@ internal class NotificationEventSearchResultTests { val sampleEventSource = EventSource( "title", "reference_id", - FEATURE_ALERTING, severity = SeverityType.INFO ) val sampleStatus = EventStatus( @@ -59,13 +56,11 @@ internal class NotificationEventSearchResultTests { val eventSource1 = EventSource( "title 1", "reference_id_1", - FEATURE_ALERTING, severity = SeverityType.INFO ) val eventSource2 = EventSource( "title 2", "reference_id_2", - FEATURE_REPORTS, severity = SeverityType.HIGH ) val status1 = EventStatus( @@ -122,13 +117,11 @@ internal class NotificationEventSearchResultTests { val eventSource1 = EventSource( "title 1", "reference_id_1", - FEATURE_ALERTING, severity = SeverityType.INFO ) val eventSource2 = EventSource( "title 2", "reference_id_2", - FEATURE_REPORTS, severity = SeverityType.HIGH ) val status1 = EventStatus( @@ -184,7 +177,6 @@ internal class NotificationEventSearchResultTests { val sampleEventSource = EventSource( "title", "reference_id", - FEATURE_ALERTING, severity = SeverityType.INFO ) val sampleStatus = EventStatus( @@ -213,13 +205,11 @@ internal class NotificationEventSearchResultTests { val eventSource1 = EventSource( "title 1", "reference_id_1", - FEATURE_ALERTING, severity = SeverityType.INFO ) val eventSource2 = EventSource( "title 2", "reference_id_2", - FEATURE_REPORTS, severity = SeverityType.HIGH ) val status1 = EventStatus( @@ -264,7 +254,6 @@ internal class NotificationEventSearchResultTests { val sampleEventSource = EventSource( "title", "reference_id", - FEATURE_ALERTING, severity = SeverityType.INFO ) val sampleStatus = EventStatus( @@ -330,7 +319,6 @@ internal class NotificationEventSearchResultTests { val sampleEventSource = EventSource( "title", "reference_id", - FEATURE_ALERTING, severity = SeverityType.INFO ) val sampleStatus = EventStatus( diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationEventTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationEventTests.kt index 313ffca9..57df6066 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationEventTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationEventTests.kt @@ -7,8 +7,6 @@ package org.opensearch.commons.notifications.model import org.junit.jupiter.api.Assertions import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Test -import org.opensearch.commons.notifications.NotificationConstants.FEATURE_ALERTING -import org.opensearch.commons.notifications.NotificationConstants.FEATURE_REPORTS import org.opensearch.commons.utils.createObjectFromJsonString import org.opensearch.commons.utils.getJsonString import org.opensearch.commons.utils.recreateObject @@ -20,7 +18,6 @@ internal class NotificationEventTests { val sampleEventSource = EventSource( "title", "reference_id", - FEATURE_ALERTING, severity = SeverityType.INFO ) val sampleStatus = EventStatus( @@ -39,7 +36,6 @@ internal class NotificationEventTests { val sampleEventSource = EventSource( "title", "reference_id", - FEATURE_REPORTS, severity = SeverityType.INFO ) val sampleStatus = EventStatus( @@ -59,9 +55,8 @@ internal class NotificationEventTests { val sampleEventSource = EventSource( "title", "reference_id", - FEATURE_ALERTING, - tags = listOf("tag1", "tag2"), - severity = SeverityType.INFO + severity = SeverityType.INFO, + tags = listOf("tag1", "tag2") ) val status1 = EventStatus( "config_id1", From 3804e802857f0a1858bf720394d840f74c1f3b82 Mon Sep 17 00:00:00 2001 From: Marc Handalian Date: Fri, 18 Mar 2022 12:14:33 -0700 Subject: [PATCH 111/140] Add opensearch repositories plugin to resolve lucene snapshot dependencies. (#137) Signed-off-by: Marc Handalian Signed-off-by: Zelin Hao --- build.gradle | 1 + 1 file changed, 1 insertion(+) diff --git a/build.gradle b/build.gradle index 16c28922..bc142d75 100644 --- a/build.gradle +++ b/build.gradle @@ -65,6 +65,7 @@ apply plugin: 'com.github.johnrengelman.shadow' apply plugin: 'io.gitlab.arturbosch.detekt' apply plugin: 'org.jetbrains.kotlin.jvm' apply plugin: 'org.jetbrains.kotlin.plugin.allopen' +apply plugin: 'opensearch.repositories' configurations { ktlint From 616f423c5361647d05da11c40bfd51f85eeb2139 Mon Sep 17 00:00:00 2001 From: Saurabh Singh Date: Mon, 21 Mar 2022 15:22:54 -0700 Subject: [PATCH 112/140] Update MAINTAINERS.m to add new maintainer. (#127) Signed-off-by: Saurabh Singh Co-authored-by: Saurabh Singh Signed-off-by: Zelin Hao --- MAINTAINERS.md | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/MAINTAINERS.md b/MAINTAINERS.md index c50082af..3802e32b 100644 --- a/MAINTAINERS.md +++ b/MAINTAINERS.md @@ -1,13 +1,14 @@ ## Maintainers -| Maintainer | GitHub ID | Affiliation | -| --------------- | --------- | ----------- | -| Ashish Agrawal | [lezzago](https://github.com/lezzago) | Amazon | -| Mohammad Qureshi | [qreshi](https://github.com/qreshi) | Amazon | -| Sriram Kosuri | [skkosuri-amzn](https://github.com/skkosuri-amzn) | Amazon | -| Bowen Lan | [bowenlan-amzn](https://github.com/bowenlan-amzn) | Amazon | -| Rishabh Maurya | [rishabhmaurya](https://github.com/rishabhmaurya) | Amazon | -| Tianli Feng | [tlfeng](https://github.com/tlfeng) | Amazon | -| Annie Lee | [leeyun-amzn](https://github.com/leeyun-amzn) | Amazon | +| Maintainer | GitHub ID | Affiliation | +|------------------|---------------------------------------------------| ----------- | +| Ashish Agrawal | [lezzago](https://github.com/lezzago) | Amazon | +| Mohammad Qureshi | [qreshi](https://github.com/qreshi) | Amazon | +| Sriram Kosuri | [skkosuri-amzn](https://github.com/skkosuri-amzn) | Amazon | +| Bowen Lan | [bowenlan-amzn](https://github.com/bowenlan-amzn) | Amazon | +| Rishabh Maurya | [rishabhmaurya](https://github.com/rishabhmaurya) | Amazon | +| Tianli Feng | [tlfeng](https://github.com/tlfeng) | Amazon | +| Annie Lee | [leeyun-amzn](https://github.com/leeyun-amzn) | Amazon | +| Saurabh Singh | [getsaurabh02](https://github.com/getsaurabh02) | Amazon | [This document](https://github.com/opensearch-project/.github/blob/main/MAINTAINERS.md) explains what maintainers do in this repo, and how they should be doing it. If you're interested in contributing, see [CONTRIBUTING](CONTRIBUTING.md). From e624bbcca4fd9725619ea39f9e8494d24cb3fa70 Mon Sep 17 00:00:00 2001 From: Mohammad Qureshi <47198598+qreshi@users.noreply.github.com> Date: Tue, 22 Mar 2022 10:19:41 -0700 Subject: [PATCH 113/140] Rename references for Get Channels API (#140) Signed-off-by: Mohammad Qureshi <47198598+qreshi@users.noreply.github.com> Signed-off-by: Zelin Hao --- .../notifications/NotificationConstants.kt | 2 +- .../NotificationsPluginInterface.kt | 18 ++-- ...istRequest.kt => GetChannelListRequest.kt} | 12 +-- ...tResponse.kt => GetChannelListResponse.kt} | 16 ++-- .../action/NotificationsActions.kt | 8 +- .../model/{FeatureChannel.kt => Channel.kt} | 14 +-- .../{FeatureChannelList.kt => ChannelList.kt} | 26 +++--- .../NotificationsPluginInterfaceTests.kt | 24 +++--- ...Tests.kt => GetChannelListRequestTests.kt} | 20 ++--- ...ests.kt => GetChannelListResponseTests.kt} | 78 ++++++++--------- ...hannelListTests.kt => ChannelListTests.kt} | 86 +++++++++---------- ...FeatureChannelTests.kt => ChannelTests.kt} | 72 ++++++++-------- .../model/FilterConfigListTests.kt | 64 +++++++------- .../notifications/model/FilterConfigTests.kt | 28 +++--- 14 files changed, 234 insertions(+), 234 deletions(-) rename src/main/kotlin/org/opensearch/commons/notifications/action/{GetFeatureChannelListRequest.kt => GetChannelListRequest.kt} (88%) rename src/main/kotlin/org/opensearch/commons/notifications/action/{GetFeatureChannelListResponse.kt => GetChannelListResponse.kt} (75%) rename src/main/kotlin/org/opensearch/commons/notifications/model/{FeatureChannel.kt => Channel.kt} (92%) rename src/main/kotlin/org/opensearch/commons/notifications/model/{FeatureChannelList.kt => ChannelList.kt} (62%) rename src/test/kotlin/org/opensearch/commons/notifications/action/{GetFeatureChannelListRequestTests.kt => GetChannelListRequestTests.kt} (76%) rename src/test/kotlin/org/opensearch/commons/notifications/action/{GetFeatureChannelListResponseTests.kt => GetChannelListResponseTests.kt} (73%) rename src/test/kotlin/org/opensearch/commons/notifications/model/{FeatureChannelListTests.kt => ChannelListTests.kt} (66%) rename src/test/kotlin/org/opensearch/commons/notifications/model/{FeatureChannelTests.kt => ChannelTests.kt} (65%) diff --git a/src/main/kotlin/org/opensearch/commons/notifications/NotificationConstants.kt b/src/main/kotlin/org/opensearch/commons/notifications/NotificationConstants.kt index 6ebf7889..146c48de 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/NotificationConstants.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/NotificationConstants.kt @@ -52,7 +52,7 @@ object NotificationConstants { const val CREATED_TIME_TAG = "created_time_ms" const val CONFIG_LIST_TAG = "config_list" const val EVENT_LIST_TAG = "event_list" - const val FEATURE_CONFIG_LIST_TAG = "feature_channel_list" + const val CHANNEL_LIST_TAG = "channel_list" const val DELETE_RESPONSE_LIST_TAG = "delete_response_list" const val FROM_INDEX_TAG = "from_index" const val MAX_ITEMS_TAG = "max_items" diff --git a/src/main/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterface.kt b/src/main/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterface.kt index b67ec282..2da0562d 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterface.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterface.kt @@ -14,8 +14,8 @@ import org.opensearch.commons.notifications.action.CreateNotificationConfigReque import org.opensearch.commons.notifications.action.CreateNotificationConfigResponse import org.opensearch.commons.notifications.action.DeleteNotificationConfigRequest import org.opensearch.commons.notifications.action.DeleteNotificationConfigResponse -import org.opensearch.commons.notifications.action.GetFeatureChannelListRequest -import org.opensearch.commons.notifications.action.GetFeatureChannelListResponse +import org.opensearch.commons.notifications.action.GetChannelListRequest +import org.opensearch.commons.notifications.action.GetChannelListResponse import org.opensearch.commons.notifications.action.GetNotificationConfigRequest import org.opensearch.commons.notifications.action.GetNotificationConfigResponse import org.opensearch.commons.notifications.action.GetNotificationEventRequest @@ -26,7 +26,7 @@ import org.opensearch.commons.notifications.action.LegacyPublishNotificationRequ import org.opensearch.commons.notifications.action.LegacyPublishNotificationResponse import org.opensearch.commons.notifications.action.NotificationsActions.CREATE_NOTIFICATION_CONFIG_ACTION_TYPE import org.opensearch.commons.notifications.action.NotificationsActions.DELETE_NOTIFICATION_CONFIG_ACTION_TYPE -import org.opensearch.commons.notifications.action.NotificationsActions.GET_FEATURE_CHANNEL_LIST_ACTION_TYPE +import org.opensearch.commons.notifications.action.NotificationsActions.GET_CHANNEL_LIST_ACTION_TYPE import org.opensearch.commons.notifications.action.NotificationsActions.GET_NOTIFICATION_CONFIG_ACTION_TYPE import org.opensearch.commons.notifications.action.NotificationsActions.GET_NOTIFICATION_EVENT_ACTION_TYPE import org.opensearch.commons.notifications.action.NotificationsActions.GET_PLUGIN_FEATURES_ACTION_TYPE @@ -156,20 +156,20 @@ object NotificationsPluginInterface { } /** - * Get notification channel configuration enabled for a feature. + * Get notification channel configuration. * @param client Node client for making transport action * @param request The request object * @param listener The listener for getting response */ - fun getFeatureChannelList( + fun getChannelList( client: NodeClient, - request: GetFeatureChannelListRequest, - listener: ActionListener + request: GetChannelListRequest, + listener: ActionListener ) { client.execute( - GET_FEATURE_CHANNEL_LIST_ACTION_TYPE, + GET_CHANNEL_LIST_ACTION_TYPE, request, - wrapActionListener(listener) { response -> recreateObject(response) { GetFeatureChannelListResponse(it) } } + wrapActionListener(listener) { response -> recreateObject(response) { GetChannelListResponse(it) } } ) } diff --git a/src/main/kotlin/org/opensearch/commons/notifications/action/GetFeatureChannelListRequest.kt b/src/main/kotlin/org/opensearch/commons/notifications/action/GetChannelListRequest.kt similarity index 88% rename from src/main/kotlin/org/opensearch/commons/notifications/action/GetFeatureChannelListRequest.kt rename to src/main/kotlin/org/opensearch/commons/notifications/action/GetChannelListRequest.kt index 56a0b0fa..96a54eb2 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/action/GetFeatureChannelListRequest.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/action/GetChannelListRequest.kt @@ -21,16 +21,16 @@ import java.io.IOException /** * This request is plugin-only call. i.e. REST interface is not exposed. */ -class GetFeatureChannelListRequest : ActionRequest, ToXContentObject { +class GetChannelListRequest : ActionRequest, ToXContentObject { val compact: Boolean // Dummy request parameter for transport request companion object { - private val log by logger(GetFeatureChannelListRequest::class.java) + private val log by logger(GetChannelListRequest::class.java) /** * reader to create instance of class from writable. */ - val reader = Writeable.Reader { GetFeatureChannelListRequest(it) } + val reader = Writeable.Reader { GetChannelListRequest(it) } /** * Creator used in REST communication. @@ -38,7 +38,7 @@ class GetFeatureChannelListRequest : ActionRequest, ToXContentObject { */ @JvmStatic @Throws(IOException::class) - fun parse(parser: XContentParser): GetFeatureChannelListRequest { + fun parse(parser: XContentParser): GetChannelListRequest { var compact = false XContentParserUtils.ensureExpectedToken( @@ -53,11 +53,11 @@ class GetFeatureChannelListRequest : ActionRequest, ToXContentObject { COMPACT_TAG -> compact = parser.booleanValue() else -> { parser.skipChildren() - log.info("Unexpected field: $fieldName, while parsing GetFeatureChannelListRequest") + log.info("Unexpected field: $fieldName, while parsing GetChannelListRequest") } } } - return GetFeatureChannelListRequest() + return GetChannelListRequest() } } diff --git a/src/main/kotlin/org/opensearch/commons/notifications/action/GetFeatureChannelListResponse.kt b/src/main/kotlin/org/opensearch/commons/notifications/action/GetChannelListResponse.kt similarity index 75% rename from src/main/kotlin/org/opensearch/commons/notifications/action/GetFeatureChannelListResponse.kt rename to src/main/kotlin/org/opensearch/commons/notifications/action/GetChannelListResponse.kt index 79bf4435..89623ed0 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/action/GetFeatureChannelListResponse.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/action/GetChannelListResponse.kt @@ -10,21 +10,21 @@ import org.opensearch.common.io.stream.Writeable import org.opensearch.common.xcontent.ToXContent import org.opensearch.common.xcontent.XContentBuilder import org.opensearch.common.xcontent.XContentParser -import org.opensearch.commons.notifications.model.FeatureChannelList +import org.opensearch.commons.notifications.model.ChannelList import java.io.IOException /** * Action Response for creating new configuration. */ -class GetFeatureChannelListResponse : BaseResponse { - val searchResult: FeatureChannelList +class GetChannelListResponse : BaseResponse { + val searchResult: ChannelList companion object { /** * reader to create instance of class from writable. */ - val reader = Writeable.Reader { GetFeatureChannelListResponse(it) } + val reader = Writeable.Reader { GetChannelListResponse(it) } /** * Creator used in REST communication. @@ -32,8 +32,8 @@ class GetFeatureChannelListResponse : BaseResponse { */ @JvmStatic @Throws(IOException::class) - fun parse(parser: XContentParser): GetFeatureChannelListResponse { - return GetFeatureChannelListResponse(FeatureChannelList(parser)) + fun parse(parser: XContentParser): GetChannelListResponse { + return GetChannelListResponse(ChannelList(parser)) } } @@ -41,7 +41,7 @@ class GetFeatureChannelListResponse : BaseResponse { * constructor for creating the class * @param searchResult the notification configuration list */ - constructor(searchResult: FeatureChannelList) { + constructor(searchResult: ChannelList) { this.searchResult = searchResult } @@ -50,7 +50,7 @@ class GetFeatureChannelListResponse : BaseResponse { */ @Throws(IOException::class) constructor(input: StreamInput) : super(input) { - searchResult = FeatureChannelList(input) + searchResult = ChannelList(input) } /** diff --git a/src/main/kotlin/org/opensearch/commons/notifications/action/NotificationsActions.kt b/src/main/kotlin/org/opensearch/commons/notifications/action/NotificationsActions.kt index ca8dd2d7..204d9326 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/action/NotificationsActions.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/action/NotificationsActions.kt @@ -43,7 +43,7 @@ object NotificationsActions { /** * Get Config List for feature. Internal only - Inter plugin communication. */ - const val GET_FEATURE_CHANNEL_LIST_NAME = "cluster:admin/opensearch/notifications/feature/channels/get" + const val GET_CHANNEL_LIST_NAME = "cluster:admin/opensearch/notifications/channels/get" /** * Send notification message. Internal only - Inter plugin communication. @@ -93,10 +93,10 @@ object NotificationsActions { ActionType(GET_PLUGIN_FEATURES_NAME, ::GetPluginFeaturesResponse) /** - * Get Config List for feature transport action type. + * Get notification channel List transport action type. */ - val GET_FEATURE_CHANNEL_LIST_ACTION_TYPE = - ActionType(GET_FEATURE_CHANNEL_LIST_NAME, ::GetFeatureChannelListResponse) + val GET_CHANNEL_LIST_ACTION_TYPE = + ActionType(GET_CHANNEL_LIST_NAME, ::GetChannelListResponse) /** * Send notification transport action type. Internal only - Inter plugin communication. diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/FeatureChannel.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/Channel.kt similarity index 92% rename from src/main/kotlin/org/opensearch/commons/notifications/model/FeatureChannel.kt rename to src/main/kotlin/org/opensearch/commons/notifications/model/Channel.kt index c0e74c56..a235d974 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/FeatureChannel.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/Channel.kt @@ -21,9 +21,9 @@ import org.opensearch.commons.utils.logger import java.io.IOException /** - * Data class representing Notification config for exposed for other plugins. + * Data class representing Notification config exposed for other plugins. */ -data class FeatureChannel( +data class Channel( val configId: String, val name: String, val description: String, @@ -37,12 +37,12 @@ data class FeatureChannel( } companion object { - private val log by logger(FeatureChannel::class.java) + private val log by logger(Channel::class.java) /** * reader to create instance of class from writable. */ - val reader = Writeable.Reader { FeatureChannel(it) } + val reader = Writeable.Reader { Channel(it) } /** * Creator used in REST communication. @@ -51,7 +51,7 @@ data class FeatureChannel( @Suppress("ComplexMethod") @JvmStatic @Throws(IOException::class) - fun parse(parser: XContentParser): FeatureChannel { + fun parse(parser: XContentParser): Channel { var configId: String? = null var name: String? = null var description = "" @@ -74,14 +74,14 @@ data class FeatureChannel( IS_ENABLED_TAG -> isEnabled = parser.booleanValue() else -> { parser.skipChildren() - log.info("Unexpected field: $fieldName, while parsing FeatureChannel") + log.info("Unexpected field: $fieldName, while parsing Channel") } } } configId ?: throw IllegalArgumentException("$CONFIG_ID_TAG field absent") name ?: throw IllegalArgumentException("$NAME_TAG field absent") configType ?: throw IllegalArgumentException("$CONFIG_TYPE_TAG field absent") - return FeatureChannel( + return Channel( configId, name, description, diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/FeatureChannelList.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/ChannelList.kt similarity index 62% rename from src/main/kotlin/org/opensearch/commons/notifications/model/FeatureChannelList.kt rename to src/main/kotlin/org/opensearch/commons/notifications/model/ChannelList.kt index d5df20a1..7cb25c3a 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/FeatureChannelList.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/ChannelList.kt @@ -9,22 +9,22 @@ import org.apache.lucene.search.TotalHits import org.opensearch.action.search.SearchResponse import org.opensearch.common.io.stream.StreamInput import org.opensearch.common.xcontent.XContentParser -import org.opensearch.commons.notifications.NotificationConstants.FEATURE_CONFIG_LIST_TAG +import org.opensearch.commons.notifications.NotificationConstants.CHANNEL_LIST_TAG /** - * FeatureChannel search results + * Channel search results */ -class FeatureChannelList : SearchResults { +class ChannelList : SearchResults { /** * single item result constructor */ - constructor(objectItem: FeatureChannel) : super(FEATURE_CONFIG_LIST_TAG, objectItem) + constructor(objectItem: Channel) : super(CHANNEL_LIST_TAG, objectItem) /** * multiple items result constructor */ - constructor(objectList: List) : this( + constructor(objectList: List) : this( 0, objectList.size.toLong(), TotalHits.Relation.EQUAL_TO, @@ -38,34 +38,34 @@ class FeatureChannelList : SearchResults { startIndex: Long, totalHits: Long, totalHitRelation: TotalHits.Relation, - objectList: List - ) : super(startIndex, totalHits, totalHitRelation, FEATURE_CONFIG_LIST_TAG, objectList) + objectList: List + ) : super(startIndex, totalHits, totalHitRelation, CHANNEL_LIST_TAG, objectList) /** * Constructor used in transport action communication. * @param input StreamInput stream to deserialize data from. */ - constructor(input: StreamInput) : super(input, FeatureChannel.reader) + constructor(input: StreamInput) : super(input, Channel.reader) /** * Construct object from XContentParser */ - constructor(parser: XContentParser) : super(parser, FEATURE_CONFIG_LIST_TAG) + constructor(parser: XContentParser) : super(parser, CHANNEL_LIST_TAG) /** * Construct object from SearchResponse */ - constructor(from: Long, response: SearchResponse, searchHitParser: SearchHitParser) : super( + constructor(from: Long, response: SearchResponse, searchHitParser: SearchHitParser) : super( from, response, searchHitParser, - FEATURE_CONFIG_LIST_TAG + CHANNEL_LIST_TAG ) /** * {@inheritDoc} */ - override fun parseItem(parser: XContentParser): FeatureChannel { - return FeatureChannel.parse(parser) + override fun parseItem(parser: XContentParser): Channel { + return Channel.parse(parser) } } diff --git a/src/test/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterfaceTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterfaceTests.kt index f6d3f9c1..c71836eb 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterfaceTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterfaceTests.kt @@ -25,8 +25,8 @@ import org.opensearch.commons.notifications.action.CreateNotificationConfigReque import org.opensearch.commons.notifications.action.CreateNotificationConfigResponse import org.opensearch.commons.notifications.action.DeleteNotificationConfigRequest import org.opensearch.commons.notifications.action.DeleteNotificationConfigResponse -import org.opensearch.commons.notifications.action.GetFeatureChannelListRequest -import org.opensearch.commons.notifications.action.GetFeatureChannelListResponse +import org.opensearch.commons.notifications.action.GetChannelListRequest +import org.opensearch.commons.notifications.action.GetChannelListResponse import org.opensearch.commons.notifications.action.GetNotificationConfigRequest import org.opensearch.commons.notifications.action.GetNotificationConfigResponse import org.opensearch.commons.notifications.action.GetNotificationEventRequest @@ -38,13 +38,13 @@ import org.opensearch.commons.notifications.action.LegacyPublishNotificationResp import org.opensearch.commons.notifications.action.SendNotificationResponse import org.opensearch.commons.notifications.action.UpdateNotificationConfigRequest import org.opensearch.commons.notifications.action.UpdateNotificationConfigResponse +import org.opensearch.commons.notifications.model.Channel +import org.opensearch.commons.notifications.model.ChannelList import org.opensearch.commons.notifications.model.ChannelMessage import org.opensearch.commons.notifications.model.ConfigType import org.opensearch.commons.notifications.model.DeliveryStatus import org.opensearch.commons.notifications.model.EventSource import org.opensearch.commons.notifications.model.EventStatus -import org.opensearch.commons.notifications.model.FeatureChannel -import org.opensearch.commons.notifications.model.FeatureChannelList import org.opensearch.commons.notifications.model.NotificationConfig import org.opensearch.commons.notifications.model.NotificationConfigInfo import org.opensearch.commons.notifications.model.NotificationConfigSearchResult @@ -168,25 +168,25 @@ internal class NotificationsPluginInterfaceTests { } @Test - fun getFeatureChannelList() { - val sampleConfig = FeatureChannel( + fun getChannelList() { + val sampleConfig = Channel( "config_id", "name", "description", ConfigType.SLACK ) - val request = mock(GetFeatureChannelListRequest::class.java) - val response = GetFeatureChannelListResponse(FeatureChannelList(sampleConfig)) - val listener: ActionListener = - mock(ActionListener::class.java) as ActionListener + val request = mock(GetChannelListRequest::class.java) + val response = GetChannelListResponse(ChannelList(sampleConfig)) + val listener: ActionListener = + mock(ActionListener::class.java) as ActionListener doAnswer { - (it.getArgument(2) as ActionListener) + (it.getArgument(2) as ActionListener) .onResponse(response) }.whenever(client).execute(any(ActionType::class.java), any(), any()) - NotificationsPluginInterface.getFeatureChannelList(client, request, listener) + NotificationsPluginInterface.getChannelList(client, request, listener) verify(listener, times(1)).onResponse(eq(response)) } diff --git a/src/test/kotlin/org/opensearch/commons/notifications/action/GetFeatureChannelListRequestTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/action/GetChannelListRequestTests.kt similarity index 76% rename from src/test/kotlin/org/opensearch/commons/notifications/action/GetFeatureChannelListRequestTests.kt rename to src/test/kotlin/org/opensearch/commons/notifications/action/GetChannelListRequestTests.kt index b9913ae2..aaa29e21 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/action/GetFeatureChannelListRequestTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/action/GetChannelListRequestTests.kt @@ -12,27 +12,27 @@ import org.opensearch.commons.utils.createObjectFromJsonString import org.opensearch.commons.utils.getJsonString import org.opensearch.commons.utils.recreateObject -internal class GetFeatureChannelListRequestTests { +internal class GetChannelListRequestTests { private fun assertGetRequestEquals( - expected: GetFeatureChannelListRequest, - actual: GetFeatureChannelListRequest + expected: GetChannelListRequest, + actual: GetChannelListRequest ) { assertEquals(expected.compact, actual.compact) } @Test fun `Get request serialize and deserialize transport object should be equal`() { - val configRequest = GetFeatureChannelListRequest() - val recreatedObject = recreateObject(configRequest) { GetFeatureChannelListRequest(it) } + val configRequest = GetChannelListRequest() + val recreatedObject = recreateObject(configRequest) { GetChannelListRequest(it) } assertGetRequestEquals(configRequest, recreatedObject) } @Test fun `Get request serialize and deserialize using json object should be equal`() { - val configRequest = GetFeatureChannelListRequest() + val configRequest = GetChannelListRequest() val jsonString = getJsonString(configRequest) - val recreatedObject = createObjectFromJsonString(jsonString) { GetFeatureChannelListRequest.parse(it) } + val recreatedObject = createObjectFromJsonString(jsonString) { GetChannelListRequest.parse(it) } assertGetRequestEquals(configRequest, recreatedObject) } @@ -40,13 +40,13 @@ internal class GetFeatureChannelListRequestTests { fun `Get request should throw exception when invalid json object is passed`() { val jsonString = "sample message" assertThrows { - createObjectFromJsonString(jsonString) { GetFeatureChannelListRequest.parse(it) } + createObjectFromJsonString(jsonString) { GetChannelListRequest.parse(it) } } } @Test fun `Get request should safely ignore extra field in json object`() { - val configRequest = GetFeatureChannelListRequest() + val configRequest = GetChannelListRequest() val jsonString = """ { "extra_field_1":["extra", "value"], @@ -54,7 +54,7 @@ internal class GetFeatureChannelListRequestTests { "extra_field_3":"extra value 3" } """.trimIndent() - val recreatedObject = createObjectFromJsonString(jsonString) { GetFeatureChannelListRequest.parse(it) } + val recreatedObject = createObjectFromJsonString(jsonString) { GetChannelListRequest.parse(it) } assertGetRequestEquals(configRequest, recreatedObject) } } diff --git a/src/test/kotlin/org/opensearch/commons/notifications/action/GetFeatureChannelListResponseTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/action/GetChannelListResponseTests.kt similarity index 73% rename from src/test/kotlin/org/opensearch/commons/notifications/action/GetFeatureChannelListResponseTests.kt rename to src/test/kotlin/org/opensearch/commons/notifications/action/GetChannelListResponseTests.kt index 805f651e..eb4023dd 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/action/GetFeatureChannelListResponseTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/action/GetChannelListResponseTests.kt @@ -8,18 +8,18 @@ import org.apache.lucene.search.TotalHits import org.junit.jupiter.api.Assertions import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Test +import org.opensearch.commons.notifications.model.Channel +import org.opensearch.commons.notifications.model.ChannelList import org.opensearch.commons.notifications.model.ConfigType -import org.opensearch.commons.notifications.model.FeatureChannel -import org.opensearch.commons.notifications.model.FeatureChannelList import org.opensearch.commons.utils.createObjectFromJsonString import org.opensearch.commons.utils.getJsonString import org.opensearch.commons.utils.recreateObject -internal class GetFeatureChannelListResponseTests { +internal class GetChannelListResponseTests { private fun assertSearchResultEquals( - expected: FeatureChannelList, - actual: FeatureChannelList + expected: ChannelList, + actual: ChannelList ) { assertEquals(expected.startIndex, actual.startIndex) assertEquals(expected.totalHits, actual.totalHits) @@ -30,112 +30,112 @@ internal class GetFeatureChannelListResponseTests { @Test fun `Get Response serialize and deserialize with config object should be equal`() { - val sampleConfig = FeatureChannel( + val sampleConfig = Channel( "config_id", "name", "description", ConfigType.SLACK ) - val searchResult = FeatureChannelList(sampleConfig) - val getResponse = GetFeatureChannelListResponse(searchResult) - val recreatedObject = recreateObject(getResponse) { GetFeatureChannelListResponse(it) } + val searchResult = ChannelList(sampleConfig) + val getResponse = GetChannelListResponse(searchResult) + val recreatedObject = recreateObject(getResponse) { GetChannelListResponse(it) } assertSearchResultEquals(searchResult, recreatedObject.searchResult) } @Test fun `Get Response serialize and deserialize with multiple config object should be equal`() { - val sampleConfig1 = FeatureChannel( + val sampleConfig1 = Channel( "config_id1", "name1", "description1", ConfigType.SLACK ) - val sampleConfig2 = FeatureChannel( + val sampleConfig2 = Channel( "config_id2", "name2", "description2", ConfigType.CHIME ) - val sampleConfig3 = FeatureChannel( + val sampleConfig3 = Channel( "config_id3", "name3", "description3", ConfigType.WEBHOOK ) - val searchResult = FeatureChannelList( + val searchResult = ChannelList( 100, 1000, TotalHits.Relation.GREATER_THAN_OR_EQUAL_TO, listOf(sampleConfig1, sampleConfig2, sampleConfig3) ) - val getResponse = GetFeatureChannelListResponse(searchResult) - val recreatedObject = recreateObject(getResponse) { GetFeatureChannelListResponse(it) } + val getResponse = GetChannelListResponse(searchResult) + val recreatedObject = recreateObject(getResponse) { GetChannelListResponse(it) } assertSearchResultEquals(searchResult, recreatedObject.searchResult) } @Test fun `Get Response serialize and deserialize using json config object should be equal`() { - val sampleConfig = FeatureChannel( + val sampleConfig = Channel( "config_id", "name", "description", ConfigType.EMAIL_GROUP ) - val searchResult = FeatureChannelList(sampleConfig) - val getResponse = GetFeatureChannelListResponse(searchResult) + val searchResult = ChannelList(sampleConfig) + val getResponse = GetChannelListResponse(searchResult) val jsonString = getJsonString(getResponse) - val recreatedObject = createObjectFromJsonString(jsonString) { GetFeatureChannelListResponse.parse(it) } + val recreatedObject = createObjectFromJsonString(jsonString) { GetChannelListResponse.parse(it) } assertSearchResultEquals(searchResult, recreatedObject.searchResult) } @Test fun `Get Response serialize and deserialize using json with multiple config object should be equal`() { - val sampleConfig1 = FeatureChannel( + val sampleConfig1 = Channel( "config_id1", "name1", "description1", ConfigType.SLACK ) - val sampleConfig2 = FeatureChannel( + val sampleConfig2 = Channel( "config_id2", "name2", "description2", ConfigType.CHIME ) - val sampleConfig3 = FeatureChannel( + val sampleConfig3 = Channel( "config_id3", "name3", "description3", ConfigType.WEBHOOK ) - val searchResult = FeatureChannelList( + val searchResult = ChannelList( 100, 1000, TotalHits.Relation.GREATER_THAN_OR_EQUAL_TO, listOf(sampleConfig1, sampleConfig2, sampleConfig3) ) - val getResponse = GetFeatureChannelListResponse(searchResult) + val getResponse = GetChannelListResponse(searchResult) val jsonString = getJsonString(getResponse) - val recreatedObject = createObjectFromJsonString(jsonString) { GetFeatureChannelListResponse.parse(it) } + val recreatedObject = createObjectFromJsonString(jsonString) { GetChannelListResponse.parse(it) } assertSearchResultEquals(searchResult, recreatedObject.searchResult) } @Test fun `Get Response should use isEnabled=true if absent in json object`() { - val sampleConfig = FeatureChannel( + val sampleConfig = Channel( "config_id", "name", "description", ConfigType.EMAIL, true ) - val searchResult = FeatureChannelList(sampleConfig) + val searchResult = ChannelList(sampleConfig) val jsonString = """ { "start_index":"0", "total_hits":"1", "total_hit_relation":"eq", - "feature_channel_list":[ + "channel_list":[ { "config_id":"config_id", "name":"name", @@ -145,25 +145,25 @@ internal class GetFeatureChannelListResponseTests { ] } """.trimIndent() - val recreatedObject = createObjectFromJsonString(jsonString) { GetFeatureChannelListResponse.parse(it) } + val recreatedObject = createObjectFromJsonString(jsonString) { GetChannelListResponse.parse(it) } assertSearchResultEquals(searchResult, recreatedObject.searchResult) } @Test fun `Get Response should safely ignore extra field in json object`() { - val sampleConfig = FeatureChannel( + val sampleConfig = Channel( "config_id", "name", "description", ConfigType.EMAIL ) - val searchResult = FeatureChannelList(sampleConfig) + val searchResult = ChannelList(sampleConfig) val jsonString = """ { "start_index":"0", "total_hits":"1", "total_hit_relation":"eq", - "feature_channel_list":[ + "channel_list":[ { "config_id":"config_id", "name":"name", @@ -177,22 +177,22 @@ internal class GetFeatureChannelListResponseTests { "extra_field_3":"extra value 3" } """.trimIndent() - val recreatedObject = createObjectFromJsonString(jsonString) { GetFeatureChannelListResponse.parse(it) } + val recreatedObject = createObjectFromJsonString(jsonString) { GetChannelListResponse.parse(it) } assertSearchResultEquals(searchResult, recreatedObject.searchResult) } @Test fun `Get Response should safely fallback to default if startIndex, totalHits or totalHitRelation field absent in json object`() { - val sampleConfig = FeatureChannel( + val sampleConfig = Channel( "config_id", "name", "description", ConfigType.EMAIL ) - val searchResult = FeatureChannelList(sampleConfig) + val searchResult = ChannelList(sampleConfig) val jsonString = """ { - "feature_channel_list":[ + "channel_list":[ { "config_id":"config_id", "name":"name", @@ -203,12 +203,12 @@ internal class GetFeatureChannelListResponseTests { ] } """.trimIndent() - val recreatedObject = createObjectFromJsonString(jsonString) { GetFeatureChannelListResponse.parse(it) } + val recreatedObject = createObjectFromJsonString(jsonString) { GetChannelListResponse.parse(it) } assertSearchResultEquals(searchResult, recreatedObject.searchResult) } @Test - fun `Get Response should throw exception if featureChannelList is absent in json`() { + fun `Get Response should throw exception if channelList is absent in json`() { val jsonString = """ { "start_index":"0", @@ -217,7 +217,7 @@ internal class GetFeatureChannelListResponseTests { } """.trimIndent() Assertions.assertThrows(IllegalArgumentException::class.java) { - createObjectFromJsonString(jsonString) { GetFeatureChannelListResponse.parse(it) } + createObjectFromJsonString(jsonString) { GetChannelListResponse.parse(it) } } } } diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/FeatureChannelListTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/ChannelListTests.kt similarity index 66% rename from src/test/kotlin/org/opensearch/commons/notifications/model/FeatureChannelListTests.kt rename to src/test/kotlin/org/opensearch/commons/notifications/model/ChannelListTests.kt index 8a40aadd..06387d37 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/FeatureChannelListTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/ChannelListTests.kt @@ -12,11 +12,11 @@ import org.opensearch.commons.utils.createObjectFromJsonString import org.opensearch.commons.utils.getJsonString import org.opensearch.commons.utils.recreateObject -internal class FeatureChannelListTests { +internal class ChannelListTests { private fun assertSearchResultEquals( - expected: FeatureChannelList, - actual: FeatureChannelList + expected: ChannelList, + actual: ChannelList ) { assertEquals(expected.startIndex, actual.startIndex) assertEquals(expected.totalHits, actual.totalHits) @@ -27,129 +27,129 @@ internal class FeatureChannelListTests { @Test fun `Feature Channel List serialize and deserialize using transport should be equal`() { - val featureChannel = FeatureChannel( + val channel = Channel( "configId", "name", "description", ConfigType.SLACK, true ) - val featureChannelList = FeatureChannelList(featureChannel) - val recreatedObject = recreateObject(featureChannelList) { FeatureChannelList(it) } - assertSearchResultEquals(featureChannelList, recreatedObject) + val channelList = ChannelList(channel) + val recreatedObject = recreateObject(channelList) { ChannelList(it) } + assertSearchResultEquals(channelList, recreatedObject) } @Test fun `Feature Channel List serialize and deserialize multiple object with default values should be equal`() { - val featureChannel1 = FeatureChannel( + val channel1 = Channel( "configId1", "name1", "description1", ConfigType.SLACK, true ) - val featureChannel2 = FeatureChannel( + val channel2 = Channel( "configId2", "name2", "description2", ConfigType.CHIME, true ) - val featureChannelList = FeatureChannelList(listOf(featureChannel1, featureChannel2)) - val expectedResult = FeatureChannelList( + val channelList = ChannelList(listOf(channel1, channel2)) + val expectedResult = ChannelList( 0, 2, TotalHits.Relation.EQUAL_TO, - listOf(featureChannel1, featureChannel2) + listOf(channel1, channel2) ) - val recreatedObject = recreateObject(featureChannelList) { FeatureChannelList(it) } + val recreatedObject = recreateObject(channelList) { ChannelList(it) } assertSearchResultEquals(expectedResult, recreatedObject) } @Test fun `Feature Channel List serialize and deserialize with multiple object should be equal`() { - val featureChannel1 = FeatureChannel( + val channel1 = Channel( "configId1", "name1", "description1", ConfigType.SLACK, true ) - val featureChannel2 = FeatureChannel( + val channel2 = Channel( "configId2", "name2", "description2", ConfigType.CHIME, true ) - val featureChannelList = FeatureChannelList( + val channelList = ChannelList( 100, 1000, TotalHits.Relation.GREATER_THAN_OR_EQUAL_TO, - listOf(featureChannel1, featureChannel2) + listOf(channel1, channel2) ) - val recreatedObject = recreateObject(featureChannelList) { FeatureChannelList(it) } - assertSearchResultEquals(featureChannelList, recreatedObject) + val recreatedObject = recreateObject(channelList) { ChannelList(it) } + assertSearchResultEquals(channelList, recreatedObject) } @Test fun `Feature Channel List serialize and deserialize using json should be equal`() { - val featureChannel = FeatureChannel( + val channel = Channel( "configId", "name", "description", ConfigType.SLACK, true ) - val featureChannelList = FeatureChannelList(featureChannel) - val jsonString = getJsonString(featureChannelList) - val recreatedObject = createObjectFromJsonString(jsonString) { FeatureChannelList(it) } - assertSearchResultEquals(featureChannelList, recreatedObject) + val channelList = ChannelList(channel) + val jsonString = getJsonString(channelList) + val recreatedObject = createObjectFromJsonString(jsonString) { ChannelList(it) } + assertSearchResultEquals(channelList, recreatedObject) } @Test fun `Feature Channel List serialize and deserialize using json with multiple object should be equal`() { - val featureChannel1 = FeatureChannel( + val channel1 = Channel( "configId1", "name1", "description1", ConfigType.SLACK, true ) - val featureChannel2 = FeatureChannel( + val channel2 = Channel( "configId2", "name2", "description2", ConfigType.CHIME, true ) - val featureChannelList = FeatureChannelList( + val channelList = ChannelList( 100, 1000, TotalHits.Relation.GREATER_THAN_OR_EQUAL_TO, - listOf(featureChannel1, featureChannel2) + listOf(channel1, channel2) ) - val jsonString = getJsonString(featureChannelList) - val recreatedObject = createObjectFromJsonString(jsonString) { FeatureChannelList(it) } - assertSearchResultEquals(featureChannelList, recreatedObject) + val jsonString = getJsonString(channelList) + val recreatedObject = createObjectFromJsonString(jsonString) { ChannelList(it) } + assertSearchResultEquals(channelList, recreatedObject) } @Test fun `Feature Channel List should safely ignore extra field in json object`() { - val featureChannel = FeatureChannel( + val channel = Channel( "configId", "name", "description", ConfigType.SLACK, true ) - val featureChannelList = FeatureChannelList(featureChannel) + val channelList = ChannelList(channel) val jsonString = """ { "start_index":"0", "total_hits":"1", "total_hit_relation":"eq", - "feature_channel_list":[ + "channel_list":[ { "config_id":"configId", "name":"name", @@ -163,23 +163,23 @@ internal class FeatureChannelListTests { "extra_field_3":"extra value 3" } """.trimIndent() - val recreatedObject = createObjectFromJsonString(jsonString) { FeatureChannelList(it) } - assertSearchResultEquals(featureChannelList, recreatedObject) + val recreatedObject = createObjectFromJsonString(jsonString) { ChannelList(it) } + assertSearchResultEquals(channelList, recreatedObject) } @Test fun `Feature Channel List should safely fallback to default if startIndex, totalHits or totalHitRelation field absent in json object`() { - val featureChannel = FeatureChannel( + val channel = Channel( "configId", "name", "description", ConfigType.SLACK, true ) - val featureChannelList = FeatureChannelList(featureChannel) + val channelList = ChannelList(channel) val jsonString = """ { - "feature_channel_list":[ + "channel_list":[ { "config_id":"configId", "name":"name", @@ -190,12 +190,12 @@ internal class FeatureChannelListTests { ] } """.trimIndent() - val recreatedObject = createObjectFromJsonString(jsonString) { FeatureChannelList(it) } - assertSearchResultEquals(featureChannelList, recreatedObject) + val recreatedObject = createObjectFromJsonString(jsonString) { ChannelList(it) } + assertSearchResultEquals(channelList, recreatedObject) } @Test - fun `Feature Channel List should throw exception if feature_channel_list is absent in json`() { + fun `Channel List should throw exception if channel_list is absent in json`() { val jsonString = """ { "start_index":"0", @@ -204,7 +204,7 @@ internal class FeatureChannelListTests { } """.trimIndent() Assertions.assertThrows(IllegalArgumentException::class.java) { - createObjectFromJsonString(jsonString) { FeatureChannelList(it) } + createObjectFromJsonString(jsonString) { ChannelList(it) } } } } diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/FeatureChannelTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/ChannelTests.kt similarity index 65% rename from src/test/kotlin/org/opensearch/commons/notifications/model/FeatureChannelTests.kt rename to src/test/kotlin/org/opensearch/commons/notifications/model/ChannelTests.kt index 3fa2e4ab..3f64cc5a 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/FeatureChannelTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/ChannelTests.kt @@ -11,38 +11,38 @@ import org.opensearch.commons.utils.createObjectFromJsonString import org.opensearch.commons.utils.getJsonString import org.opensearch.commons.utils.recreateObject -internal class FeatureChannelTests { +internal class ChannelTests { @Test - fun `FeatureChannel Object serialize and deserialize using transport should be equal`() { - val featureChannel = FeatureChannel( + fun `Channel Object serialize and deserialize using transport should be equal`() { + val channel = Channel( "configId", "name", "description", ConfigType.SLACK, true ) - val recreatedObject = recreateObject(featureChannel) { FeatureChannel(it) } - assertEquals(featureChannel, recreatedObject) + val recreatedObject = recreateObject(channel) { Channel(it) } + assertEquals(channel, recreatedObject) } @Test - fun `FeatureChannel Object serialize and deserialize using json should be equal`() { - val featureChannel = FeatureChannel( + fun `Channel Object serialize and deserialize using json should be equal`() { + val channel = Channel( "configId", "name", "description", ConfigType.CHIME, false ) - val jsonString = getJsonString(featureChannel) - val recreatedObject = createObjectFromJsonString(jsonString) { FeatureChannel.parse(it) } - assertEquals(featureChannel, recreatedObject) + val jsonString = getJsonString(channel) + val recreatedObject = createObjectFromJsonString(jsonString) { Channel.parse(it) } + assertEquals(channel, recreatedObject) } @Test - fun `FeatureChannel Json parsing should safely ignore extra fields`() { - val featureChannel = FeatureChannel( + fun `Channel Json parsing should safely ignore extra fields`() { + val channel = Channel( "configId", "name", "description", @@ -61,13 +61,13 @@ internal class FeatureChannelTests { "extra_field_3":"extra value 3" } """.trimIndent() - val recreatedObject = createObjectFromJsonString(jsonString) { FeatureChannel.parse(it) } - assertEquals(featureChannel, recreatedObject) + val recreatedObject = createObjectFromJsonString(jsonString) { Channel.parse(it) } + assertEquals(channel, recreatedObject) } @Test - fun `FeatureChannel Json parsing should safely ignore unknown config type`() { - val featureChannel = FeatureChannel( + fun `Channel Json parsing should safely ignore unknown config type`() { + val channel = Channel( "configId", "name", "description", @@ -83,13 +83,13 @@ internal class FeatureChannelTests { "is_enabled":true } """.trimIndent() - val recreatedObject = createObjectFromJsonString(jsonString) { FeatureChannel.parse(it) } - assertEquals(featureChannel, recreatedObject) + val recreatedObject = createObjectFromJsonString(jsonString) { Channel.parse(it) } + assertEquals(channel, recreatedObject) } @Test - fun `FeatureChannel Json parsing should safely parse if description is absent`() { - val featureChannel = FeatureChannel( + fun `Channel Json parsing should safely parse if description is absent`() { + val channel = Channel( "configId", "name", "", @@ -104,13 +104,13 @@ internal class FeatureChannelTests { "is_enabled":true } """.trimIndent() - val recreatedObject = createObjectFromJsonString(jsonString) { FeatureChannel.parse(it) } - assertEquals(featureChannel, recreatedObject) + val recreatedObject = createObjectFromJsonString(jsonString) { Channel.parse(it) } + assertEquals(channel, recreatedObject) } @Test - fun `FeatureChannel Json parsing should safely parse if is_enabled is absent`() { - val featureChannel = FeatureChannel( + fun `Channel Json parsing should safely parse if is_enabled is absent`() { + val channel = Channel( "configId", "name", "description", @@ -125,12 +125,12 @@ internal class FeatureChannelTests { "config_type":"slack" } """.trimIndent() - val recreatedObject = createObjectFromJsonString(jsonString) { FeatureChannel.parse(it) } - assertEquals(featureChannel, recreatedObject) + val recreatedObject = createObjectFromJsonString(jsonString) { Channel.parse(it) } + assertEquals(channel, recreatedObject) } @Test - fun `FeatureChannel Json parsing should throw exception if config_id is absent`() { + fun `Channel Json parsing should throw exception if config_id is absent`() { val jsonString = """ { "name":"name", @@ -140,12 +140,12 @@ internal class FeatureChannelTests { } """.trimIndent() Assertions.assertThrows(IllegalArgumentException::class.java) { - createObjectFromJsonString(jsonString) { FeatureChannel.parse(it) } + createObjectFromJsonString(jsonString) { Channel.parse(it) } } } @Test - fun `FeatureChannel Json parsing should throw exception if config_id is empty`() { + fun `Channel Json parsing should throw exception if config_id is empty`() { val jsonString = """ { "config_id":"", @@ -156,12 +156,12 @@ internal class FeatureChannelTests { } """.trimIndent() Assertions.assertThrows(IllegalArgumentException::class.java) { - createObjectFromJsonString(jsonString) { FeatureChannel.parse(it) } + createObjectFromJsonString(jsonString) { Channel.parse(it) } } } @Test - fun `FeatureChannel Json parsing should throw exception if name is absent`() { + fun `Channel Json parsing should throw exception if name is absent`() { val jsonString = """ { "config_id":"configId", @@ -171,12 +171,12 @@ internal class FeatureChannelTests { } """.trimIndent() Assertions.assertThrows(IllegalArgumentException::class.java) { - createObjectFromJsonString(jsonString) { FeatureChannel.parse(it) } + createObjectFromJsonString(jsonString) { Channel.parse(it) } } } @Test - fun `FeatureChannel Json parsing should throw exception if name is empty`() { + fun `Channel Json parsing should throw exception if name is empty`() { val jsonString = """ { "config_id":"configId", @@ -187,12 +187,12 @@ internal class FeatureChannelTests { } """.trimIndent() Assertions.assertThrows(IllegalArgumentException::class.java) { - createObjectFromJsonString(jsonString) { FeatureChannel.parse(it) } + createObjectFromJsonString(jsonString) { Channel.parse(it) } } } @Test - fun `FeatureChannel Json parsing should throw exception if config_type is absent`() { + fun `Channel Json parsing should throw exception if config_type is absent`() { val jsonString = """ { "config_id":"configId", @@ -202,7 +202,7 @@ internal class FeatureChannelTests { } """.trimIndent() Assertions.assertThrows(IllegalArgumentException::class.java) { - createObjectFromJsonString(jsonString) { FeatureChannel.parse(it) } + createObjectFromJsonString(jsonString) { Channel.parse(it) } } } } diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/FilterConfigListTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/FilterConfigListTests.kt index 9ac569f6..de648bcd 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/FilterConfigListTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/FilterConfigListTests.kt @@ -15,8 +15,8 @@ import org.opensearch.commons.utils.recreateObject internal class FilterConfigListTests { private fun assertSearchResultEquals( - expected: FeatureChannelList, - actual: FeatureChannelList + expected: ChannelList, + actual: ChannelList ) { assertEquals(expected.startIndex, actual.startIndex) assertEquals(expected.totalHits, actual.totalHits) @@ -27,108 +27,108 @@ internal class FilterConfigListTests { @Test fun `Search result serialize and deserialize with config object should be equal`() { - val sampleConfig = FeatureChannel( + val sampleConfig = Channel( "config_id", "name", "description", ConfigType.SLACK ) - val searchResult = FeatureChannelList(sampleConfig) - val recreatedObject = recreateObject(searchResult) { FeatureChannelList(it) } + val searchResult = ChannelList(sampleConfig) + val recreatedObject = recreateObject(searchResult) { ChannelList(it) } assertSearchResultEquals(searchResult, recreatedObject) } @Test fun `Search result serialize and deserialize with multiple config object should be equal`() { - val sampleConfig1 = FeatureChannel( + val sampleConfig1 = Channel( "config_id1", "name1", "description1", ConfigType.SLACK ) - val sampleConfig2 = FeatureChannel( + val sampleConfig2 = Channel( "config_id2", "name2", "description2", ConfigType.CHIME ) - val sampleConfig3 = FeatureChannel( + val sampleConfig3 = Channel( "config_id3", "name3", "description3", ConfigType.WEBHOOK ) - val searchResult = FeatureChannelList( + val searchResult = ChannelList( 100, 1000, TotalHits.Relation.GREATER_THAN_OR_EQUAL_TO, listOf(sampleConfig1, sampleConfig2, sampleConfig3) ) - val recreatedObject = recreateObject(searchResult) { FeatureChannelList(it) } + val recreatedObject = recreateObject(searchResult) { ChannelList(it) } assertSearchResultEquals(searchResult, recreatedObject) } @Test fun `Search result serialize and deserialize using json config object should be equal`() { - val sampleConfig = FeatureChannel( + val sampleConfig = Channel( "config_id", "name", "description", ConfigType.EMAIL_GROUP ) - val searchResult = FeatureChannelList(sampleConfig) + val searchResult = ChannelList(sampleConfig) val jsonString = getJsonString(searchResult) - val recreatedObject = createObjectFromJsonString(jsonString) { FeatureChannelList(it) } + val recreatedObject = createObjectFromJsonString(jsonString) { ChannelList(it) } assertSearchResultEquals(searchResult, recreatedObject) } @Test fun `Search result serialize and deserialize using json with multiple config object should be equal`() { - val sampleConfig1 = FeatureChannel( + val sampleConfig1 = Channel( "config_id1", "name1", "description1", ConfigType.SLACK ) - val sampleConfig2 = FeatureChannel( + val sampleConfig2 = Channel( "config_id2", "name2", "description2", ConfigType.CHIME ) - val sampleConfig3 = FeatureChannel( + val sampleConfig3 = Channel( "config_id3", "name3", "description3", ConfigType.WEBHOOK ) - val searchResult = FeatureChannelList( + val searchResult = ChannelList( 100, 1000, TotalHits.Relation.GREATER_THAN_OR_EQUAL_TO, listOf(sampleConfig1, sampleConfig2, sampleConfig3) ) val jsonString = getJsonString(searchResult) - val recreatedObject = createObjectFromJsonString(jsonString) { FeatureChannelList(it) } + val recreatedObject = createObjectFromJsonString(jsonString) { ChannelList(it) } assertSearchResultEquals(searchResult, recreatedObject) } @Test fun `Search result should use isEnabled=true if absent in json object`() { - val sampleConfig = FeatureChannel( + val sampleConfig = Channel( "config_id", "name", "description", ConfigType.EMAIL, true ) - val searchResult = FeatureChannelList(sampleConfig) + val searchResult = ChannelList(sampleConfig) val jsonString = """ { "start_index":"0", "total_hits":"1", "total_hit_relation":"eq", - "feature_channel_list":[ + "channel_list":[ { "config_id":"config_id", "name":"name", @@ -138,25 +138,25 @@ internal class FilterConfigListTests { ] } """.trimIndent() - val recreatedObject = createObjectFromJsonString(jsonString) { FeatureChannelList(it) } + val recreatedObject = createObjectFromJsonString(jsonString) { ChannelList(it) } assertSearchResultEquals(searchResult, recreatedObject) } @Test fun `Search result should safely ignore extra field in json object`() { - val sampleConfig = FeatureChannel( + val sampleConfig = Channel( "config_id", "name", "description", ConfigType.EMAIL ) - val searchResult = FeatureChannelList(sampleConfig) + val searchResult = ChannelList(sampleConfig) val jsonString = """ { "start_index":"0", "total_hits":"1", "total_hit_relation":"eq", - "feature_channel_list":[ + "channel_list":[ { "config_id":"config_id", "name":"name", @@ -170,22 +170,22 @@ internal class FilterConfigListTests { "extra_field_3":"extra value 3" } """.trimIndent() - val recreatedObject = createObjectFromJsonString(jsonString) { FeatureChannelList(it) } + val recreatedObject = createObjectFromJsonString(jsonString) { ChannelList(it) } assertSearchResultEquals(searchResult, recreatedObject) } @Test fun `Search result should safely fallback to default if startIndex, totalHits or totalHitRelation field absent in json object`() { - val sampleConfig = FeatureChannel( + val sampleConfig = Channel( "config_id", "name", "description", ConfigType.EMAIL ) - val searchResult = FeatureChannelList(sampleConfig) + val searchResult = ChannelList(sampleConfig) val jsonString = """ { - "feature_channel_list":[ + "channel_list":[ { "config_id":"config_id", "name":"name", @@ -196,12 +196,12 @@ internal class FilterConfigListTests { ] } """.trimIndent() - val recreatedObject = createObjectFromJsonString(jsonString) { FeatureChannelList(it) } + val recreatedObject = createObjectFromJsonString(jsonString) { ChannelList(it) } assertSearchResultEquals(searchResult, recreatedObject) } @Test - fun `Search result should throw exception if featureChannelList is absent in json`() { + fun `Search result should throw exception if channelList is absent in json`() { val jsonString = """ { "start_index":"0", @@ -210,7 +210,7 @@ internal class FilterConfigListTests { } """.trimIndent() Assertions.assertThrows(IllegalArgumentException::class.java) { - createObjectFromJsonString(jsonString) { FeatureChannelList(it) } + createObjectFromJsonString(jsonString) { ChannelList(it) } } } } diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/FilterConfigTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/FilterConfigTests.kt index 234548a8..c3557e89 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/FilterConfigTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/FilterConfigTests.kt @@ -15,45 +15,45 @@ internal class FilterConfigTests { @Test fun `Config serialize and deserialize with default isEnabled flag should be equal`() { - val sampleConfig = FeatureChannel( + val sampleConfig = Channel( "config_id", "name", "description", ConfigType.SLACK ) - val recreatedObject = recreateObject(sampleConfig) { FeatureChannel(it) } + val recreatedObject = recreateObject(sampleConfig) { Channel(it) } assertEquals(sampleConfig, recreatedObject) } @Test fun `Config serialize and deserialize with isEnabled=false should be equal`() { - val sampleConfig = FeatureChannel( + val sampleConfig = Channel( "config_id", "name", "description", ConfigType.CHIME, false ) - val recreatedObject = recreateObject(sampleConfig) { FeatureChannel(it) } + val recreatedObject = recreateObject(sampleConfig) { Channel(it) } assertEquals(sampleConfig, recreatedObject) } @Test fun `Config serialize and deserialize using json object with default isEnabled flag should be equal`() { - val sampleConfig = FeatureChannel( + val sampleConfig = Channel( "config_id", "name", "description", ConfigType.WEBHOOK ) val jsonString = getJsonString(sampleConfig) - val recreatedObject = createObjectFromJsonString(jsonString) { FeatureChannel.parse(it) } + val recreatedObject = createObjectFromJsonString(jsonString) { Channel.parse(it) } assertEquals(sampleConfig, recreatedObject) } @Test fun `Config serialize and deserialize using json object with isEnabled=false should be equal`() { - val sampleConfig = FeatureChannel( + val sampleConfig = Channel( "config_id", "name", "description", @@ -61,13 +61,13 @@ internal class FilterConfigTests { false ) val jsonString = getJsonString(sampleConfig) - val recreatedObject = createObjectFromJsonString(jsonString) { FeatureChannel.parse(it) } + val recreatedObject = createObjectFromJsonString(jsonString) { Channel.parse(it) } assertEquals(sampleConfig, recreatedObject) } @Test fun `Config should safely ignore extra field in json object`() { - val sampleConfig = FeatureChannel( + val sampleConfig = Channel( "config_id", "name", "description", @@ -85,13 +85,13 @@ internal class FilterConfigTests { "extra_field_3":"extra value 3" } """.trimIndent() - val recreatedObject = createObjectFromJsonString(jsonString) { FeatureChannel.parse(it) } + val recreatedObject = createObjectFromJsonString(jsonString) { Channel.parse(it) } assertEquals(sampleConfig, recreatedObject) } @Test fun `Config should safely ignore unknown config type in json object`() { - val sampleConfig = FeatureChannel( + val sampleConfig = Channel( "config_id", "name", "description", @@ -105,14 +105,14 @@ internal class FilterConfigTests { "config_type":"NewConfig" } """.trimIndent() - val recreatedObject = createObjectFromJsonString(jsonString) { FeatureChannel.parse(it) } + val recreatedObject = createObjectFromJsonString(jsonString) { Channel.parse(it) } assertEquals(sampleConfig, recreatedObject) } @Test fun `Config throw exception if configId is empty`() { Assertions.assertThrows(IllegalArgumentException::class.java) { - FeatureChannel( + Channel( "", "name", "description", @@ -124,7 +124,7 @@ internal class FilterConfigTests { @Test fun `Config throw exception if name is empty`() { Assertions.assertThrows(IllegalArgumentException::class.java) { - FeatureChannel( + Channel( "config_id", "", "description", From 7cb2a9bce41801edeca4460c5dcadc8a68756e5f Mon Sep 17 00:00:00 2001 From: Vacha Shah Date: Wed, 23 Mar 2022 12:54:51 -0700 Subject: [PATCH 114/140] Adding signoff option for version workflow PR (#143) Signed-off-by: Vacha Shah Signed-off-by: Zelin Hao --- .github/workflows/version.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/version.yml b/.github/workflows/version.yml index 8ca31d8e..6c96199a 100644 --- a/.github/workflows/version.yml +++ b/.github/workflows/version.yml @@ -46,6 +46,7 @@ jobs: token: ${{ steps.github_app_token.outputs.token }} base: ${{ env.BASE }} commit-message: Incremented version to ${{ env.NEXT_VERSION }} + signoff: true delete-branch: true title: '[AUTO] Incremented version to ${{ env.NEXT_VERSION }}.' body: | From 928fcc5c0e4740e5fbd685dd1bd4c5e572712725 Mon Sep 17 00:00:00 2001 From: Mohammad Qureshi <47198598+qreshi@users.noreply.github.com> Date: Mon, 28 Mar 2022 10:28:01 -0700 Subject: [PATCH 115/140] Remove allowedConfigFeatureList from GetPluginFeaturesResponse (#144) Signed-off-by: Mohammad Qureshi <47198598+qreshi@users.noreply.github.com> Signed-off-by: Zelin Hao --- .../notifications/NotificationConstants.kt | 1 - .../action/GetPluginFeaturesResponse.kt | 13 +--------- .../NotificationsPluginInterfaceTests.kt | 1 - .../action/GetPluginFeaturesResponseTests.kt | 26 +------------------ 4 files changed, 2 insertions(+), 39 deletions(-) diff --git a/src/main/kotlin/org/opensearch/commons/notifications/NotificationConstants.kt b/src/main/kotlin/org/opensearch/commons/notifications/NotificationConstants.kt index 146c48de..74fcc600 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/NotificationConstants.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/NotificationConstants.kt @@ -66,7 +66,6 @@ object NotificationConstants { const val QUERY_TAG = "query" const val COMPACT_TAG = "compact" const val ALLOWED_CONFIG_TYPE_LIST_TAG = "allowed_config_type_list" - const val ALLOWED_CONFIG_FEATURE_LIST_TAG = "allowed_config_feature_list" const val PLUGIN_FEATURES_TAG = "plugin_features" const val DEFAULT_MAX_ITEMS = 1000 diff --git a/src/main/kotlin/org/opensearch/commons/notifications/action/GetPluginFeaturesResponse.kt b/src/main/kotlin/org/opensearch/commons/notifications/action/GetPluginFeaturesResponse.kt index 1e6fa2b9..73db57a0 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/action/GetPluginFeaturesResponse.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/action/GetPluginFeaturesResponse.kt @@ -11,7 +11,6 @@ import org.opensearch.common.xcontent.ToXContent import org.opensearch.common.xcontent.XContentBuilder import org.opensearch.common.xcontent.XContentParser import org.opensearch.common.xcontent.XContentParserUtils -import org.opensearch.commons.notifications.NotificationConstants.ALLOWED_CONFIG_FEATURE_LIST_TAG import org.opensearch.commons.notifications.NotificationConstants.ALLOWED_CONFIG_TYPE_LIST_TAG import org.opensearch.commons.notifications.NotificationConstants.PLUGIN_FEATURES_TAG import org.opensearch.commons.utils.STRING_READER @@ -25,7 +24,6 @@ import java.io.IOException */ class GetPluginFeaturesResponse : BaseResponse { val allowedConfigTypeList: List - val allowedConfigFeatureList: List val pluginFeatures: Map companion object { @@ -44,7 +42,6 @@ class GetPluginFeaturesResponse : BaseResponse { @Throws(IOException::class) fun parse(parser: XContentParser): GetPluginFeaturesResponse { var allowedConfigTypeList: List? = null - var allowedConfigFeatureList: List? = null var pluginFeatures: Map? = null XContentParserUtils.ensureExpectedToken( @@ -57,7 +54,6 @@ class GetPluginFeaturesResponse : BaseResponse { parser.nextToken() when (fieldName) { ALLOWED_CONFIG_TYPE_LIST_TAG -> allowedConfigTypeList = parser.stringList() - ALLOWED_CONFIG_FEATURE_LIST_TAG -> allowedConfigFeatureList = parser.stringList() PLUGIN_FEATURES_TAG -> pluginFeatures = parser.mapStrings() else -> { parser.skipChildren() @@ -66,9 +62,8 @@ class GetPluginFeaturesResponse : BaseResponse { } } allowedConfigTypeList ?: throw IllegalArgumentException("$ALLOWED_CONFIG_TYPE_LIST_TAG field absent") - allowedConfigFeatureList ?: throw IllegalArgumentException("$ALLOWED_CONFIG_TYPE_LIST_TAG field absent") pluginFeatures ?: throw IllegalArgumentException("$PLUGIN_FEATURES_TAG field absent") - return GetPluginFeaturesResponse(allowedConfigTypeList, allowedConfigFeatureList, pluginFeatures) + return GetPluginFeaturesResponse(allowedConfigTypeList, pluginFeatures) } } @@ -78,7 +73,6 @@ class GetPluginFeaturesResponse : BaseResponse { override fun toXContent(builder: XContentBuilder?, params: ToXContent.Params?): XContentBuilder { return builder!!.startObject() .field(ALLOWED_CONFIG_TYPE_LIST_TAG, allowedConfigTypeList) - .field(ALLOWED_CONFIG_FEATURE_LIST_TAG, allowedConfigFeatureList) .field(PLUGIN_FEATURES_TAG, pluginFeatures) .endObject() } @@ -86,16 +80,13 @@ class GetPluginFeaturesResponse : BaseResponse { /** * constructor for creating the class * @param allowedConfigTypeList the list of config types supported by plugin - * @param allowedConfigFeatureList the list of config features supported by plugin * @param pluginFeatures the map of plugin features supported to its value */ constructor( allowedConfigTypeList: List, - allowedConfigFeatureList: List, pluginFeatures: Map ) { this.allowedConfigTypeList = allowedConfigTypeList - this.allowedConfigFeatureList = allowedConfigFeatureList this.pluginFeatures = pluginFeatures } @@ -105,7 +96,6 @@ class GetPluginFeaturesResponse : BaseResponse { @Throws(IOException::class) constructor(input: StreamInput) : super(input) { allowedConfigTypeList = input.readStringList() - allowedConfigFeatureList = input.readStringList() pluginFeatures = input.readMap(STRING_READER, STRING_READER) } @@ -115,7 +105,6 @@ class GetPluginFeaturesResponse : BaseResponse { @Throws(IOException::class) override fun writeTo(output: StreamOutput) { output.writeStringCollection(allowedConfigTypeList) - output.writeStringCollection(allowedConfigFeatureList) output.writeMap(pluginFeatures, STRING_WRITER, STRING_WRITER) } } diff --git a/src/test/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterfaceTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterfaceTests.kt index c71836eb..aaa831d1 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterfaceTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterfaceTests.kt @@ -148,7 +148,6 @@ internal class NotificationsPluginInterfaceTests { val request = mock(GetPluginFeaturesRequest::class.java) val response = GetPluginFeaturesResponse( listOf("config_type_1", "config_type_2", "config_type_3"), - listOf("config_feature_1", "config_feature_2", "config_feature_3"), mapOf( Pair("FeatureKey1", "FeatureValue1"), Pair("FeatureKey2", "FeatureValue2"), diff --git a/src/test/kotlin/org/opensearch/commons/notifications/action/GetPluginFeaturesResponseTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/action/GetPluginFeaturesResponseTests.kt index 72b9a49f..1aa065a2 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/action/GetPluginFeaturesResponseTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/action/GetPluginFeaturesResponseTests.kt @@ -18,7 +18,6 @@ internal class GetPluginFeaturesResponseTests { actual: GetPluginFeaturesResponse ) { assertEquals(expected.allowedConfigTypeList, actual.allowedConfigTypeList) - assertEquals(expected.allowedConfigFeatureList, actual.allowedConfigFeatureList) assertEquals(expected.pluginFeatures, actual.pluginFeatures) } @@ -26,7 +25,6 @@ internal class GetPluginFeaturesResponseTests { fun `Get Response serialize and deserialize transport object should be equal`() { val response = GetPluginFeaturesResponse( listOf("config_type_1", "config_type_2", "config_type_3"), - listOf("config_feature_1", "config_feature_2", "config_feature_3"), mapOf( Pair("FeatureKey1", "FeatureValue1"), Pair("FeatureKey2", "FeatureValue2"), @@ -41,7 +39,6 @@ internal class GetPluginFeaturesResponseTests { fun `Get Response serialize and deserialize using json config object should be equal`() { val response = GetPluginFeaturesResponse( listOf("config_type_1", "config_type_2", "config_type_3"), - listOf("config_feature_1", "config_feature_2", "config_feature_3"), mapOf( Pair("FeatureKey1", "FeatureValue1"), Pair("FeatureKey2", "FeatureValue2"), @@ -57,7 +54,6 @@ internal class GetPluginFeaturesResponseTests { fun `Get Response should safely ignore extra field in json object`() { val response = GetPluginFeaturesResponse( listOf("config_type_1", "config_type_2", "config_type_3"), - listOf("config_feature_1", "config_feature_2", "config_feature_3"), mapOf( Pair("FeatureKey1", "FeatureValue1"), Pair("FeatureKey2", "FeatureValue2"), @@ -67,7 +63,6 @@ internal class GetPluginFeaturesResponseTests { val jsonString = """ { "allowed_config_type_list":["config_type_1", "config_type_2", "config_type_3"], - "allowed_config_feature_list":["config_feature_1", "config_feature_2", "config_feature_3"], "plugin_features":{ "FeatureKey1":"FeatureValue1", "FeatureKey2":"FeatureValue2", @@ -86,24 +81,6 @@ internal class GetPluginFeaturesResponseTests { fun `Get Response should throw exception if allowed_config_type_list is absent in json`() { val jsonString = """ { - "allowed_config_feature_list":["config_feature_1", "config_feature_2", "config_feature_3"], - "plugin_features":{ - "FeatureKey1":"FeatureValue1", - "FeatureKey2":"FeatureValue2", - "FeatureKey3":"FeatureValue3" - } - } - """.trimIndent() - Assertions.assertThrows(IllegalArgumentException::class.java) { - createObjectFromJsonString(jsonString) { GetPluginFeaturesResponse.parse(it) } - } - } - - @Test - fun `Get Response should throw exception if allowed_config_feature_list is absent in json`() { - val jsonString = """ - { - "allowed_config_type_list":["config_type_1", "config_type_2", "config_type_3"], "plugin_features":{ "FeatureKey1":"FeatureValue1", "FeatureKey2":"FeatureValue2", @@ -120,8 +97,7 @@ internal class GetPluginFeaturesResponseTests { fun `Get Response should throw exception if plugin_features is absent in json`() { val jsonString = """ { - "config_type_list":["config_type_1", "config_type_2", "config_type_3"], - "allowed_config_feature_list":["config_feature_1", "config_feature_2", "config_feature_3"] + "config_type_list":["config_type_1", "config_type_2", "config_type_3"] } """.trimIndent() Assertions.assertThrows(IllegalArgumentException::class.java) { From ede70140091b88df3b58e12852c0a47ac3e83cf9 Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Mon, 28 Mar 2022 16:56:39 -0400 Subject: [PATCH 116/140] change default opensearch version to 2.0.0-alpha1-SNAPSHOT (#146) Signed-off-by: Peter Zhu Signed-off-by: Zelin Hao --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index bc142d75..f11f252e 100644 --- a/build.gradle +++ b/build.gradle @@ -6,7 +6,7 @@ buildscript { ext { opensearch_group = "org.opensearch" - opensearch_version = System.getProperty("opensearch.version", "2.0.0-SNAPSHOT") + opensearch_version = System.getProperty("opensearch.version", "2.0.0-alpha1-SNAPSHOT") kotlin_version = System.getProperty("kotlin.version", "1.6.10") } From ab44c140d73aa8da2fc9213ee464f48db48d64dd Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Thu, 31 Mar 2022 16:44:08 -0400 Subject: [PATCH 117/140] Add qualifier default to alpha1 in build.gradle (#151) Signed-off-by: Peter Zhu Signed-off-by: Zelin Hao --- build.gradle | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/build.gradle b/build.gradle index f11f252e..cf3ca5b9 100644 --- a/build.gradle +++ b/build.gradle @@ -7,6 +7,8 @@ buildscript { ext { opensearch_group = "org.opensearch" opensearch_version = System.getProperty("opensearch.version", "2.0.0-alpha1-SNAPSHOT") + isSnapshot = "true" == System.getProperty("build.snapshot", "true") + buildVersionQualifier = System.getProperty("build.version_qualifier", "alpha1") kotlin_version = System.getProperty("kotlin.version", "1.6.10") } @@ -38,11 +40,6 @@ repositories { maven { url "https://aws.oss.sonatype.org/content/repositories/snapshots" } } -ext { - isSnapshot = "true" == System.getProperty("build.snapshot", "true") - buildVersionQualifier = System.getProperty("build.version_qualifier") -} - allprojects { group 'org.opensearch.commons' version = opensearch_version.tokenize('-')[0] + '.0' From ac8040adbe4630badcaca42975203386cfc0ca7f Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Thu, 31 Mar 2022 22:18:55 -0400 Subject: [PATCH 118/140] Make CU hosts its own script before delete the one on build repo (#152) Signed-off-by: Peter Zhu Signed-off-by: Zelin Hao --- scripts/build.sh | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/scripts/build.sh b/scripts/build.sh index 1f8b6d4d..e0495d4a 100755 --- a/scripts/build.sh +++ b/scripts/build.sh @@ -10,7 +10,7 @@ function usage() { echo "" echo "Arguments:" echo -e "-v VERSION\t[Required] OpenSearch version." - echo -e "-q QUALIFIER\t[Optional] Build qualifier." + echo -e "-q QUALIFIER\t[Optional] Version qualifier." echo -e "-s SNAPSHOT\t[Optional] Build a snapshot, default is 'false'." echo -e "-p PLATFORM\t[Optional] Platform, ignored." echo -e "-a ARCHITECTURE\t[Optional] Build architecture, ignored." @@ -60,11 +60,12 @@ if [ -z "$VERSION" ]; then exit 1 fi +[[ ! -z "$QUALIFIER" ]] && VERSION=$VERSION-$QUALIFIER [[ "$SNAPSHOT" == "true" ]] && VERSION=$VERSION-SNAPSHOT [ -z "$OUTPUT" ] && OUTPUT=artifacts -./gradlew build -Dopensearch.version=$VERSION -Dbuild.snapshot=$SNAPSHOT -Dbuild.version_qualifier=$QUALIFIER +./gradlew build -x test -Dopensearch.version=$VERSION -Dbuild.snapshot=$SNAPSHOT -Dbuild.version_qualifier=$QUALIFIER ./gradlew publishShadowPublicationToMavenLocal -Dopensearch.version=$VERSION -Dbuild.snapshot=$SNAPSHOT -Dbuild.version_qualifier=$QUALIFIER ./gradlew publishShadowPublicationToStagingRepository -Dopensearch.version=$VERSION -Dbuild.snapshot=$SNAPSHOT -Dbuild.version_qualifier=$QUALIFIER mkdir -p $OUTPUT/maven/org/opensearch -cp -r ./build/local-staging-repo/org/opensearch/common-utils $OUTPUT/maven/org/opensearch/common-utils +cp -r ./build/local-staging-repo/org/opensearch/. $OUTPUT/maven/org/opensearch From 96d5c1d4e2e33ff61782445e1b28e6007a9780ab Mon Sep 17 00:00:00 2001 From: Aditya Jindal <13850971+aditjind@users.noreply.github.com> Date: Tue, 5 Apr 2022 13:43:56 -0700 Subject: [PATCH 119/140] Removal of NotificationEvent Request, Response and SearchResults (#153) * Removal of NotificationEvent Request, Response , Search Results Addition of NotificationEventDoc and Removal of NotificationEventInfo Addition of NotificationEventDocTests Signed-off-by: Jindal * Removing NotificationEventDoc and NotificationEventDocTests Signed-off-by: Jindal Co-authored-by: Jindal Signed-off-by: Zelin Hao --- .../NotificationsPluginInterface.kt | 21 - .../action/GetNotificationEventRequest.kt | 171 -------- .../action/GetNotificationEventResponse.kt | 70 ---- .../action/NotificationsActions.kt | 11 - .../model/NotificationEventInfo.kt | 122 ------ .../model/NotificationEventSearchResult.kt | 71 ---- .../NotificationsPluginInterfaceTests.kt | 45 -- .../GetNotificationEventRequestTests.kt | 258 ------------ .../GetNotificationEventResponseTests.kt | 345 --------------- .../model/NotificationEventInfoTests.kt | 273 ------------ .../NotificationEventSearchResultTests.kt | 396 ------------------ 11 files changed, 1783 deletions(-) delete mode 100644 src/main/kotlin/org/opensearch/commons/notifications/action/GetNotificationEventRequest.kt delete mode 100644 src/main/kotlin/org/opensearch/commons/notifications/action/GetNotificationEventResponse.kt delete mode 100644 src/main/kotlin/org/opensearch/commons/notifications/model/NotificationEventInfo.kt delete mode 100644 src/main/kotlin/org/opensearch/commons/notifications/model/NotificationEventSearchResult.kt delete mode 100644 src/test/kotlin/org/opensearch/commons/notifications/action/GetNotificationEventRequestTests.kt delete mode 100644 src/test/kotlin/org/opensearch/commons/notifications/action/GetNotificationEventResponseTests.kt delete mode 100644 src/test/kotlin/org/opensearch/commons/notifications/model/NotificationEventInfoTests.kt delete mode 100644 src/test/kotlin/org/opensearch/commons/notifications/model/NotificationEventSearchResultTests.kt diff --git a/src/main/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterface.kt b/src/main/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterface.kt index 2da0562d..c3baa938 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterface.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterface.kt @@ -18,8 +18,6 @@ import org.opensearch.commons.notifications.action.GetChannelListRequest import org.opensearch.commons.notifications.action.GetChannelListResponse import org.opensearch.commons.notifications.action.GetNotificationConfigRequest import org.opensearch.commons.notifications.action.GetNotificationConfigResponse -import org.opensearch.commons.notifications.action.GetNotificationEventRequest -import org.opensearch.commons.notifications.action.GetNotificationEventResponse import org.opensearch.commons.notifications.action.GetPluginFeaturesRequest import org.opensearch.commons.notifications.action.GetPluginFeaturesResponse import org.opensearch.commons.notifications.action.LegacyPublishNotificationRequest @@ -28,7 +26,6 @@ import org.opensearch.commons.notifications.action.NotificationsActions.CREATE_N import org.opensearch.commons.notifications.action.NotificationsActions.DELETE_NOTIFICATION_CONFIG_ACTION_TYPE import org.opensearch.commons.notifications.action.NotificationsActions.GET_CHANNEL_LIST_ACTION_TYPE import org.opensearch.commons.notifications.action.NotificationsActions.GET_NOTIFICATION_CONFIG_ACTION_TYPE -import org.opensearch.commons.notifications.action.NotificationsActions.GET_NOTIFICATION_EVENT_ACTION_TYPE import org.opensearch.commons.notifications.action.NotificationsActions.GET_PLUGIN_FEATURES_ACTION_TYPE import org.opensearch.commons.notifications.action.NotificationsActions.LEGACY_PUBLISH_NOTIFICATION_ACTION_TYPE import org.opensearch.commons.notifications.action.NotificationsActions.SEND_NOTIFICATION_ACTION_TYPE @@ -119,24 +116,6 @@ object NotificationsPluginInterface { ) } - /** - * Get notification events. - * @param client Node client for making transport action - * @param request The request object - * @param listener The listener for getting response - */ - fun getNotificationEvent( - client: NodeClient, - request: GetNotificationEventRequest, - listener: ActionListener - ) { - client.execute( - GET_NOTIFICATION_EVENT_ACTION_TYPE, - request, - wrapActionListener(listener) { response -> recreateObject(response) { GetNotificationEventResponse(it) } } - ) - } - /** * Get notification plugin features. * @param client Node client for making transport action diff --git a/src/main/kotlin/org/opensearch/commons/notifications/action/GetNotificationEventRequest.kt b/src/main/kotlin/org/opensearch/commons/notifications/action/GetNotificationEventRequest.kt deleted file mode 100644 index 66bfba6a..00000000 --- a/src/main/kotlin/org/opensearch/commons/notifications/action/GetNotificationEventRequest.kt +++ /dev/null @@ -1,171 +0,0 @@ -/* - * Copyright OpenSearch Contributors - * SPDX-License-Identifier: Apache-2.0 - */ -package org.opensearch.commons.notifications.action - -import org.opensearch.action.ActionRequest -import org.opensearch.action.ActionRequestValidationException -import org.opensearch.action.ValidateActions -import org.opensearch.common.io.stream.StreamInput -import org.opensearch.common.io.stream.StreamOutput -import org.opensearch.common.io.stream.Writeable -import org.opensearch.common.xcontent.ToXContent -import org.opensearch.common.xcontent.ToXContentObject -import org.opensearch.common.xcontent.XContentBuilder -import org.opensearch.common.xcontent.XContentParser -import org.opensearch.common.xcontent.XContentParserUtils -import org.opensearch.commons.notifications.NotificationConstants.DEFAULT_MAX_ITEMS -import org.opensearch.commons.notifications.NotificationConstants.EVENT_ID_LIST_TAG -import org.opensearch.commons.notifications.NotificationConstants.FILTER_PARAM_LIST_TAG -import org.opensearch.commons.notifications.NotificationConstants.FROM_INDEX_TAG -import org.opensearch.commons.notifications.NotificationConstants.MAX_ITEMS_TAG -import org.opensearch.commons.notifications.NotificationConstants.SORT_FIELD_TAG -import org.opensearch.commons.notifications.NotificationConstants.SORT_ORDER_TAG -import org.opensearch.commons.utils.STRING_READER -import org.opensearch.commons.utils.STRING_WRITER -import org.opensearch.commons.utils.enumReader -import org.opensearch.commons.utils.fieldIfNotNull -import org.opensearch.commons.utils.logger -import org.opensearch.commons.utils.stringList -import org.opensearch.search.sort.SortOrder -import java.io.IOException - -/** - * Action Request for getting notification event. - */ -class GetNotificationEventRequest : ActionRequest, ToXContentObject { - val eventIds: Set - val fromIndex: Int - val maxItems: Int - val sortField: String? - val sortOrder: SortOrder? - val filterParams: Map - - companion object { - private val log by logger(GetNotificationEventRequest::class.java) - - /** - * reader to create instance of class from writable. - */ - val reader = Writeable.Reader { GetNotificationEventRequest(it) } - - /** - * Creator used in REST communication. - * @param parser XContentParser to deserialize data from. - */ - @JvmStatic - @Throws(IOException::class) - fun parse(parser: XContentParser): GetNotificationEventRequest { - var eventIds: Set = setOf() - var fromIndex = 0 - var maxItems = DEFAULT_MAX_ITEMS - var sortField: String? = null - var sortOrder: SortOrder? = null - var filterParams: Map = mapOf() - - XContentParserUtils.ensureExpectedToken( - XContentParser.Token.START_OBJECT, - parser.currentToken(), - parser - ) - while (parser.nextToken() != XContentParser.Token.END_OBJECT) { - val fieldName = parser.currentName() - parser.nextToken() - when (fieldName) { - EVENT_ID_LIST_TAG -> eventIds = parser.stringList().toSet() - FROM_INDEX_TAG -> fromIndex = parser.intValue() - MAX_ITEMS_TAG -> maxItems = parser.intValue() - SORT_FIELD_TAG -> sortField = parser.textOrNull() - SORT_ORDER_TAG -> sortOrder = SortOrder.fromString(parser.text()) - FILTER_PARAM_LIST_TAG -> filterParams = parser.mapStrings() - else -> { - parser.skipChildren() - log.info("Unexpected field: $fieldName, while parsing GetNotificationEventRequest") - } - } - } - return GetNotificationEventRequest(eventIds, fromIndex, maxItems, sortField, sortOrder, filterParams) - } - } - - /** - * {@inheritDoc} - */ - override fun toXContent(builder: XContentBuilder?, params: ToXContent.Params?): XContentBuilder { - return builder!!.startObject() - .field(EVENT_ID_LIST_TAG, eventIds) - .field(FROM_INDEX_TAG, fromIndex) - .field(MAX_ITEMS_TAG, maxItems) - .fieldIfNotNull(SORT_FIELD_TAG, sortField) - .fieldIfNotNull(SORT_ORDER_TAG, sortOrder) - .field(FILTER_PARAM_LIST_TAG, filterParams) - .endObject() - } - - /** - * constructor for creating the class - * @param eventIds the ids of the notification events (other parameters are not relevant if ids are present) - * @param fromIndex the starting index for paginated response - * @param maxItems the maximum number of items to return for paginated response - * @param sortField the sort field if response has many items - * @param sortOrder the sort order if response has many items - * @param filterParams the filter parameters - */ - constructor( - eventIds: Set = setOf(), - fromIndex: Int = 0, - maxItems: Int = DEFAULT_MAX_ITEMS, - sortField: String? = null, - sortOrder: SortOrder? = null, - filterParams: Map = mapOf() - ) { - this.eventIds = eventIds - this.fromIndex = fromIndex - this.maxItems = maxItems - this.sortField = sortField - this.sortOrder = sortOrder - this.filterParams = filterParams - } - - /** - * {@inheritDoc} - */ - @Throws(IOException::class) - constructor(input: StreamInput) : super(input) { - eventIds = input.readStringList().toSet() - fromIndex = input.readInt() - maxItems = input.readInt() - sortField = input.readOptionalString() - sortOrder = input.readOptionalWriteable(enumReader(SortOrder::class.java)) - filterParams = input.readMap(STRING_READER, STRING_READER) - } - - /** - * {@inheritDoc} - */ - @Throws(IOException::class) - override fun writeTo(output: StreamOutput) { - super.writeTo(output) - output.writeStringCollection(eventIds) - output.writeInt(fromIndex) - output.writeInt(maxItems) - output.writeOptionalString(sortField) - output.writeOptionalWriteable(sortOrder) - output.writeMap(filterParams, STRING_WRITER, STRING_WRITER) - } - - /** - * {@inheritDoc} - */ - override fun validate(): ActionRequestValidationException? { - var validationException: ActionRequestValidationException? = null - if (fromIndex < 0) { - validationException = ValidateActions.addValidationError("fromIndex is -ve", validationException) - } - if (maxItems <= 0) { - validationException = ValidateActions.addValidationError("maxItems is not +ve", validationException) - } - return validationException - } -} diff --git a/src/main/kotlin/org/opensearch/commons/notifications/action/GetNotificationEventResponse.kt b/src/main/kotlin/org/opensearch/commons/notifications/action/GetNotificationEventResponse.kt deleted file mode 100644 index c512aa48..00000000 --- a/src/main/kotlin/org/opensearch/commons/notifications/action/GetNotificationEventResponse.kt +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright OpenSearch Contributors - * SPDX-License-Identifier: Apache-2.0 - */ -package org.opensearch.commons.notifications.action - -import org.opensearch.common.io.stream.StreamInput -import org.opensearch.common.io.stream.StreamOutput -import org.opensearch.common.io.stream.Writeable -import org.opensearch.common.xcontent.ToXContent -import org.opensearch.common.xcontent.XContentBuilder -import org.opensearch.common.xcontent.XContentParser -import org.opensearch.commons.notifications.model.NotificationEventSearchResult -import java.io.IOException - -/** - * Action Response for getting notification event. - */ -class GetNotificationEventResponse : BaseResponse { - val searchResult: NotificationEventSearchResult - - companion object { - - /** - * reader to create instance of class from writable. - */ - val reader = Writeable.Reader { GetNotificationEventResponse(it) } - - /** - * Creator used in REST communication. - * @param parser XContentParser to deserialize data from. - */ - @JvmStatic - @Throws(IOException::class) - fun parse(parser: XContentParser): GetNotificationEventResponse { - return GetNotificationEventResponse(NotificationEventSearchResult(parser)) - } - } - - /** - * constructor for creating the class - * @param searchResult the notification event list - */ - constructor(searchResult: NotificationEventSearchResult) { - this.searchResult = searchResult - } - - /** - * {@inheritDoc} - */ - @Throws(IOException::class) - constructor(input: StreamInput) : super(input) { - searchResult = NotificationEventSearchResult(input) - } - - /** - * {@inheritDoc} - */ - @Throws(IOException::class) - override fun writeTo(output: StreamOutput) { - searchResult.writeTo(output) - } - - /** - * {@inheritDoc} - */ - override fun toXContent(builder: XContentBuilder?, params: ToXContent.Params?): XContentBuilder { - return searchResult.toXContent(builder, params) - } -} diff --git a/src/main/kotlin/org/opensearch/commons/notifications/action/NotificationsActions.kt b/src/main/kotlin/org/opensearch/commons/notifications/action/NotificationsActions.kt index 204d9326..e4a8cfe5 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/action/NotificationsActions.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/action/NotificationsActions.kt @@ -30,11 +30,6 @@ object NotificationsActions { */ const val GET_NOTIFICATION_CONFIG_NAME = "cluster:admin/opensearch/notifications/configs/get" - /** - * Get notification events transport action name. - */ - const val GET_NOTIFICATION_EVENT_NAME = "cluster:admin/opensearch/notifications/events/get" - /** * Get notification plugin features transport action name. */ @@ -80,12 +75,6 @@ object NotificationsActions { val GET_NOTIFICATION_CONFIG_ACTION_TYPE = ActionType(GET_NOTIFICATION_CONFIG_NAME, ::GetNotificationConfigResponse) - /** - * Get notification events transport action type. - */ - val GET_NOTIFICATION_EVENT_ACTION_TYPE = - ActionType(GET_NOTIFICATION_EVENT_NAME, ::GetNotificationEventResponse) - /** * Get notification plugin features transport action type. */ diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationEventInfo.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationEventInfo.kt deleted file mode 100644 index 51921fc8..00000000 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationEventInfo.kt +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright OpenSearch Contributors - * SPDX-License-Identifier: Apache-2.0 - */ -package org.opensearch.commons.notifications.model - -import org.opensearch.common.Strings -import org.opensearch.common.io.stream.StreamInput -import org.opensearch.common.io.stream.StreamOutput -import org.opensearch.common.io.stream.Writeable -import org.opensearch.common.xcontent.ToXContent -import org.opensearch.common.xcontent.XContentBuilder -import org.opensearch.common.xcontent.XContentParser -import org.opensearch.common.xcontent.XContentParserUtils -import org.opensearch.commons.notifications.NotificationConstants.CREATED_TIME_TAG -import org.opensearch.commons.notifications.NotificationConstants.EVENT_ID_TAG -import org.opensearch.commons.notifications.NotificationConstants.EVENT_TAG -import org.opensearch.commons.notifications.NotificationConstants.UPDATED_TIME_TAG -import org.opensearch.commons.utils.logger -import java.io.IOException -import java.time.Instant - -/** - * Data class representing Notification event with information. - */ -data class NotificationEventInfo( - val eventId: String, - val lastUpdatedTime: Instant, - val createdTime: Instant, - val notificationEvent: NotificationEvent -) : BaseModel { - - init { - require(!Strings.isNullOrEmpty(eventId)) { "event id is null or empty" } - } - - companion object { - private val log by logger(NotificationEventInfo::class.java) - - /** - * reader to create instance of class from writable. - */ - val reader = Writeable.Reader { NotificationEventInfo(it) } - - /** - * Creator used in REST communication. - * @param parser XContentParser to deserialize data from. - */ - @JvmStatic - @Throws(IOException::class) - fun parse(parser: XContentParser): NotificationEventInfo { - var eventId: String? = null - var lastUpdatedTime: Instant? = null - var createdTime: Instant? = null - var notificationEvent: NotificationEvent? = null - - XContentParserUtils.ensureExpectedToken( - XContentParser.Token.START_OBJECT, - parser.currentToken(), - parser - ) - while (parser.nextToken() != XContentParser.Token.END_OBJECT) { - val fieldName = parser.currentName() - parser.nextToken() - when (fieldName) { - EVENT_ID_TAG -> eventId = parser.text() - UPDATED_TIME_TAG -> lastUpdatedTime = Instant.ofEpochMilli(parser.longValue()) - CREATED_TIME_TAG -> createdTime = Instant.ofEpochMilli(parser.longValue()) - EVENT_TAG -> notificationEvent = NotificationEvent.parse(parser) - else -> { - parser.skipChildren() - log.info("Unexpected field: $fieldName, while parsing event info") - } - } - } - eventId ?: throw IllegalArgumentException("$EVENT_ID_TAG field absent") - lastUpdatedTime ?: throw IllegalArgumentException("$UPDATED_TIME_TAG field absent") - createdTime ?: throw IllegalArgumentException("$CREATED_TIME_TAG field absent") - notificationEvent ?: throw IllegalArgumentException("$EVENT_TAG field absent") - return NotificationEventInfo( - eventId, - lastUpdatedTime, - createdTime, - notificationEvent - ) - } - } - - /** - * {@inheritDoc} - */ - override fun toXContent(builder: XContentBuilder?, params: ToXContent.Params?): XContentBuilder { - builder!! - return builder.startObject() - .field(EVENT_ID_TAG, eventId) - .field(UPDATED_TIME_TAG, lastUpdatedTime.toEpochMilli()) - .field(CREATED_TIME_TAG, createdTime.toEpochMilli()) - .field(EVENT_TAG, notificationEvent) - .endObject() - } - - /** - * Constructor used in transport action communication. - * @param input StreamInput stream to deserialize data from. - */ - constructor(input: StreamInput) : this( - eventId = input.readString(), - lastUpdatedTime = input.readInstant(), - createdTime = input.readInstant(), - notificationEvent = NotificationEvent.reader.read(input) - ) - - /** - * {@inheritDoc} - */ - override fun writeTo(output: StreamOutput) { - output.writeString(eventId) - output.writeInstant(lastUpdatedTime) - output.writeInstant(createdTime) - notificationEvent.writeTo(output) - } -} diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationEventSearchResult.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationEventSearchResult.kt deleted file mode 100644 index e9b68406..00000000 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationEventSearchResult.kt +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright OpenSearch Contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -package org.opensearch.commons.notifications.model - -import org.apache.lucene.search.TotalHits -import org.opensearch.action.search.SearchResponse -import org.opensearch.common.io.stream.StreamInput -import org.opensearch.common.xcontent.XContentParser -import org.opensearch.commons.notifications.NotificationConstants.EVENT_LIST_TAG - -/** - * Notification Event search results - */ -class NotificationEventSearchResult : SearchResults { - - /** - * single item result constructor - */ - constructor(objectItem: NotificationEventInfo) : super(EVENT_LIST_TAG, objectItem) - - /** - * multiple items result constructor - */ - constructor(objectList: List) : this( - 0, - objectList.size.toLong(), - TotalHits.Relation.EQUAL_TO, - objectList - ) - - /** - * all param constructor - */ - constructor( - startIndex: Long, - totalHits: Long, - totalHitRelation: TotalHits.Relation, - objectList: List - ) : super(startIndex, totalHits, totalHitRelation, EVENT_LIST_TAG, objectList) - - /** - * Constructor used in transport action communication. - * @param input StreamInput stream to deserialize data from. - */ - constructor(input: StreamInput) : super(input, NotificationEventInfo.reader) - - /** - * Construct object from XContentParser - */ - constructor(parser: XContentParser) : super(parser, EVENT_LIST_TAG) - - /** - * Construct object from SearchResponse - */ - constructor(from: Long, response: SearchResponse, searchHitParser: SearchHitParser) : super( - from, - response, - searchHitParser, - EVENT_LIST_TAG - ) - - /** - * {@inheritDoc} - */ - override fun parseItem(parser: XContentParser): NotificationEventInfo { - return NotificationEventInfo.parse(parser) - } -} diff --git a/src/test/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterfaceTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterfaceTests.kt index aaa831d1..556c35b6 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterfaceTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterfaceTests.kt @@ -29,8 +29,6 @@ import org.opensearch.commons.notifications.action.GetChannelListRequest import org.opensearch.commons.notifications.action.GetChannelListResponse import org.opensearch.commons.notifications.action.GetNotificationConfigRequest import org.opensearch.commons.notifications.action.GetNotificationConfigResponse -import org.opensearch.commons.notifications.action.GetNotificationEventRequest -import org.opensearch.commons.notifications.action.GetNotificationEventResponse import org.opensearch.commons.notifications.action.GetPluginFeaturesRequest import org.opensearch.commons.notifications.action.GetPluginFeaturesResponse import org.opensearch.commons.notifications.action.LegacyPublishNotificationRequest @@ -42,15 +40,10 @@ import org.opensearch.commons.notifications.model.Channel import org.opensearch.commons.notifications.model.ChannelList import org.opensearch.commons.notifications.model.ChannelMessage import org.opensearch.commons.notifications.model.ConfigType -import org.opensearch.commons.notifications.model.DeliveryStatus import org.opensearch.commons.notifications.model.EventSource -import org.opensearch.commons.notifications.model.EventStatus import org.opensearch.commons.notifications.model.NotificationConfig import org.opensearch.commons.notifications.model.NotificationConfigInfo import org.opensearch.commons.notifications.model.NotificationConfigSearchResult -import org.opensearch.commons.notifications.model.NotificationEvent -import org.opensearch.commons.notifications.model.NotificationEventInfo -import org.opensearch.commons.notifications.model.NotificationEventSearchResult import org.opensearch.commons.notifications.model.SeverityType import org.opensearch.commons.notifications.model.Slack import org.opensearch.rest.RestStatus @@ -127,22 +120,6 @@ internal class NotificationsPluginInterfaceTests { verify(listener, times(1)).onResponse(eq(response)) } - @Test - fun getNotificationEvent() { - val request = mock(GetNotificationEventRequest::class.java) - val response = mockGetNotificationEventResponse() - val listener: ActionListener = - mock(ActionListener::class.java) as ActionListener - - doAnswer { - (it.getArgument(2) as ActionListener) - .onResponse(response) - }.whenever(client).execute(any(ActionType::class.java), any(), any()) - - NotificationsPluginInterface.getNotificationEvent(client, request, listener) - verify(listener, times(1)).onResponse(eq(response)) - } - @Test fun getPluginFeatures() { val request = mock(GetPluginFeaturesRequest::class.java) @@ -250,26 +227,4 @@ internal class NotificationsPluginInterfaceTests { ) return GetNotificationConfigResponse(NotificationConfigSearchResult(configInfo)) } - - private fun mockGetNotificationEventResponse(): GetNotificationEventResponse { - val sampleEventSource = EventSource( - "title", - "reference_id", - severity = SeverityType.INFO - ) - val sampleStatus = EventStatus( - "config_id", - "name", - ConfigType.SLACK, - deliveryStatus = DeliveryStatus("404", "invalid recipient") - ) - val sampleEvent = NotificationEvent(sampleEventSource, listOf(sampleStatus)) - val eventInfo = NotificationEventInfo( - "event_id", - Instant.now(), - Instant.now(), - sampleEvent - ) - return GetNotificationEventResponse(NotificationEventSearchResult(eventInfo)) - } } diff --git a/src/test/kotlin/org/opensearch/commons/notifications/action/GetNotificationEventRequestTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/action/GetNotificationEventRequestTests.kt deleted file mode 100644 index 53bb825a..00000000 --- a/src/test/kotlin/org/opensearch/commons/notifications/action/GetNotificationEventRequestTests.kt +++ /dev/null @@ -1,258 +0,0 @@ -/* - * Copyright OpenSearch Contributors - * SPDX-License-Identifier: Apache-2.0 - */ -package org.opensearch.commons.notifications.action - -import com.fasterxml.jackson.core.JsonParseException -import org.junit.jupiter.api.Assertions.assertEquals -import org.junit.jupiter.api.Test -import org.junit.jupiter.api.assertThrows -import org.opensearch.commons.utils.createObjectFromJsonString -import org.opensearch.commons.utils.getJsonString -import org.opensearch.commons.utils.recreateObject -import org.opensearch.search.sort.SortOrder - -internal class GetNotificationEventRequestTests { - - private fun assertGetRequestEquals( - expected: GetNotificationEventRequest, - actual: GetNotificationEventRequest - ) { - assertEquals(expected.eventIds, actual.eventIds) - assertEquals(expected.fromIndex, actual.fromIndex) - assertEquals(expected.maxItems, actual.maxItems) - assertEquals(expected.sortField, actual.sortField) - assertEquals(expected.sortOrder, actual.sortOrder) - assertEquals(expected.filterParams, actual.filterParams) - } - - @Test - fun `Get request serialize and deserialize transport object should be equal`() { - val configRequest = GetNotificationEventRequest( - setOf("sample_event_id"), - 0, - 10, - "sortField", - SortOrder.DESC, - mapOf(Pair("filterKey", "filterValue")) - ) - val recreatedObject = recreateObject(configRequest) { GetNotificationEventRequest(it) } - assertGetRequestEquals(configRequest, recreatedObject) - } - - @Test - fun `Get request serialize and deserialize using json object should be equal`() { - val configRequest = GetNotificationEventRequest( - setOf("sample_event_id"), - 0, - 10, - "sortField", - SortOrder.ASC, - mapOf(Pair("filterKey", "filterValue")) - ) - val jsonString = getJsonString(configRequest) - val recreatedObject = createObjectFromJsonString(jsonString) { GetNotificationEventRequest.parse(it) } - assertGetRequestEquals(configRequest, recreatedObject) - } - - @Test - fun `Get request with all field should deserialize json object using parser`() { - val configRequest = GetNotificationEventRequest( - setOf("sample_event_id"), - 10, - 100, - "sortField", - SortOrder.DESC, - mapOf( - Pair("filterKey1", "filterValue1"), - Pair("filterKey2", "true"), - Pair("filterKey3", "filter,Value,3"), - Pair("filterKey4", "4") - ) - ) - val jsonString = """ - { - "event_id_list":["${configRequest.eventIds.first()}"], - "from_index":"10", - "max_items":"100", - "sort_field":"sortField", - "sort_order":"desc", - "filter_param_list": { - "filterKey1":"filterValue1", - "filterKey2":"true", - "filterKey3":"filter,Value,3", - "filterKey4":"4" - } - } - """.trimIndent() - val recreatedObject = createObjectFromJsonString(jsonString) { GetNotificationEventRequest.parse(it) } - assertGetRequestEquals(configRequest, recreatedObject) - } - - @Test - fun `Get request with only event_id field should deserialize json object using parser`() { - val configRequest = GetNotificationEventRequest(eventIds = setOf("sample_event_id")) - val jsonString = """ - { - "event_id_list":["${configRequest.eventIds.first()}"] - } - """.trimIndent() - val recreatedObject = createObjectFromJsonString(jsonString) { GetNotificationEventRequest.parse(it) } - assertGetRequestEquals(configRequest, recreatedObject) - } - - @Test - fun `Get request with only from_index field should deserialize json object using parser`() { - val configRequest = GetNotificationEventRequest(fromIndex = 20) - val jsonString = """ - { - "from_index":"20" - } - """.trimIndent() - val recreatedObject = createObjectFromJsonString(jsonString) { GetNotificationEventRequest.parse(it) } - assertGetRequestEquals(configRequest, recreatedObject) - } - - @Test - fun `Get request with only max_items field should deserialize json object using parser`() { - val configRequest = GetNotificationEventRequest(maxItems = 100) - val jsonString = """ - { - "max_items":"100" - } - """.trimIndent() - val recreatedObject = createObjectFromJsonString(jsonString) { GetNotificationEventRequest.parse(it) } - assertGetRequestEquals(configRequest, recreatedObject) - } - - @Test - fun `Get request with only sort_field field should deserialize json object using parser`() { - val configRequest = GetNotificationEventRequest(sortField = "sample_sort_field") - val jsonString = """ - { - "sort_field":"sample_sort_field" - } - """.trimIndent() - val recreatedObject = createObjectFromJsonString(jsonString) { GetNotificationEventRequest.parse(it) } - assertGetRequestEquals(configRequest, recreatedObject) - } - - @Test - fun `Get request with only sort_order=asc field should deserialize json object using parser`() { - val configRequest = GetNotificationEventRequest(sortOrder = SortOrder.ASC) - val jsonString = """ - { - "sort_order":"asc" - } - """.trimIndent() - val recreatedObject = createObjectFromJsonString(jsonString) { GetNotificationEventRequest.parse(it) } - assertGetRequestEquals(configRequest, recreatedObject) - } - - @Test - fun `Get request with only sort_order=ASC field should deserialize json object using parser`() { - val configRequest = GetNotificationEventRequest(sortOrder = SortOrder.ASC) - val jsonString = """ - { - "sort_order":"ASC" - } - """.trimIndent() - val recreatedObject = createObjectFromJsonString(jsonString) { GetNotificationEventRequest.parse(it) } - assertGetRequestEquals(configRequest, recreatedObject) - } - - @Test - fun `Get request with only sort_order=desc field should deserialize json object using parser`() { - val configRequest = GetNotificationEventRequest(sortOrder = SortOrder.DESC) - val jsonString = """ - { - "sort_order":"desc" - } - """.trimIndent() - val recreatedObject = createObjectFromJsonString(jsonString) { GetNotificationEventRequest.parse(it) } - assertGetRequestEquals(configRequest, recreatedObject) - } - - @Test - fun `Get request with only sort_order=DESC field should deserialize json object using parser`() { - val configRequest = GetNotificationEventRequest(sortOrder = SortOrder.DESC) - val jsonString = """ - { - "sort_order":"DESC" - } - """.trimIndent() - val recreatedObject = createObjectFromJsonString(jsonString) { GetNotificationEventRequest.parse(it) } - assertGetRequestEquals(configRequest, recreatedObject) - } - - @Test - fun `Get request with invalid sort_order should throw exception`() { - val jsonString = """ - { - "sort_order":"descending" - } - """.trimIndent() - assertThrows { - createObjectFromJsonString(jsonString) { GetNotificationEventRequest.parse(it) } - } - } - - @Test - fun `Get request with only filter_param_list field should deserialize json object using parser`() { - val configRequest = GetNotificationEventRequest( - filterParams = mapOf( - Pair("filterKey1", "filterValue1"), - Pair("filterKey2", "true"), - Pair("filterKey3", "filter,Value,3"), - Pair("filterKey4", "4") - ) - ) - val jsonString = """ - { - "filter_param_list": { - "filterKey1":"filterValue1", - "filterKey2":"true", - "filterKey3":"filter,Value,3", - "filterKey4":"4" - } - } - """.trimIndent() - val recreatedObject = createObjectFromJsonString(jsonString) { GetNotificationEventRequest.parse(it) } - assertGetRequestEquals(configRequest, recreatedObject) - } - - @Test - fun `Get request no field should deserialize json object using parser`() { - val configRequest = GetNotificationEventRequest() - val jsonString = """ - { - } - """.trimIndent() - val recreatedObject = createObjectFromJsonString(jsonString) { GetNotificationEventRequest.parse(it) } - assertGetRequestEquals(configRequest, recreatedObject) - } - - @Test - fun `Get request should throw exception when invalid json object is passed`() { - val jsonString = "sample message" - assertThrows { - createObjectFromJsonString(jsonString) { GetNotificationEventRequest.parse(it) } - } - } - - @Test - fun `Get request should safely ignore extra field in json object`() { - val configRequest = GetNotificationEventRequest(eventIds = setOf("sample_event_id")) - val jsonString = """ - { - "event_id_list":["${configRequest.eventIds.first()}"], - "extra_field_1":["extra", "value"], - "extra_field_2":{"extra":"value"}, - "extra_field_3":"extra value 3" - } - """.trimIndent() - val recreatedObject = createObjectFromJsonString(jsonString) { GetNotificationEventRequest.parse(it) } - assertGetRequestEquals(configRequest, recreatedObject) - } -} diff --git a/src/test/kotlin/org/opensearch/commons/notifications/action/GetNotificationEventResponseTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/action/GetNotificationEventResponseTests.kt deleted file mode 100644 index 0de1c78b..00000000 --- a/src/test/kotlin/org/opensearch/commons/notifications/action/GetNotificationEventResponseTests.kt +++ /dev/null @@ -1,345 +0,0 @@ -/* - * Copyright OpenSearch Contributors - * SPDX-License-Identifier: Apache-2.0 - */ -package org.opensearch.commons.notifications.action - -import org.apache.lucene.search.TotalHits -import org.junit.jupiter.api.Assertions -import org.junit.jupiter.api.Assertions.assertEquals -import org.junit.jupiter.api.Test -import org.opensearch.commons.notifications.model.ConfigType -import org.opensearch.commons.notifications.model.DeliveryStatus -import org.opensearch.commons.notifications.model.EventSource -import org.opensearch.commons.notifications.model.EventStatus -import org.opensearch.commons.notifications.model.NotificationEvent -import org.opensearch.commons.notifications.model.NotificationEventInfo -import org.opensearch.commons.notifications.model.NotificationEventSearchResult -import org.opensearch.commons.notifications.model.SeverityType -import org.opensearch.commons.utils.createObjectFromJsonString -import org.opensearch.commons.utils.getJsonString -import org.opensearch.commons.utils.recreateObject -import java.time.Instant - -internal class GetNotificationEventResponseTests { - - private fun assertSearchResultEquals( - expected: NotificationEventSearchResult, - actual: NotificationEventSearchResult - ) { - assertEquals(expected.startIndex, actual.startIndex) - assertEquals(expected.totalHits, actual.totalHits) - assertEquals(expected.totalHitRelation, actual.totalHitRelation) - assertEquals(expected.objectListFieldName, actual.objectListFieldName) - assertEquals(expected.objectList, actual.objectList) - } - - @Test - fun `Search result serialize and deserialize with event object should be equal`() { - val sampleEventSource = EventSource( - "title", - "reference_id", - severity = SeverityType.INFO - ) - val sampleStatus = EventStatus( - "config_id", - "name", - ConfigType.SLACK, - deliveryStatus = DeliveryStatus("404", "invalid recipient") - ) - val sampleEvent = NotificationEvent(sampleEventSource, listOf(sampleStatus)) - val eventInfo = NotificationEventInfo( - "event_id", - Instant.now(), - Instant.now(), - sampleEvent - ) - val searchResult = NotificationEventSearchResult(eventInfo) - val searchResponse = GetNotificationEventResponse(searchResult) - val recreatedObject = recreateObject(searchResponse) { GetNotificationEventResponse(it) } - assertSearchResultEquals(searchResult, recreatedObject.searchResult) - } - - @Test - fun `Search result serialize and deserialize with multiple event status object should be equal`() { - val eventSource1 = EventSource( - "title 1", - "reference_id_1", - severity = SeverityType.INFO - ) - val eventSource2 = EventSource( - "title 2", - "reference_id_2", - severity = SeverityType.HIGH - ) - val status1 = EventStatus( - "config_id1", - "name", - ConfigType.SLACK, - deliveryStatus = DeliveryStatus("200", "success") - ) - val status2 = EventStatus( - "config_id2", - "name", - ConfigType.CHIME, - deliveryStatus = DeliveryStatus("404", "invalid recipient") - ) - val eventInfo1 = NotificationEventInfo( - "event_id1", - Instant.now(), - Instant.now(), - NotificationEvent(eventSource1, listOf(status1)) - ) - val eventInfo2 = NotificationEventInfo( - "event_id2", - Instant.now(), - Instant.now(), - NotificationEvent(eventSource2, listOf(status2)) - ) - val eventInfo3 = NotificationEventInfo( - "event_id3", - Instant.now(), - Instant.now(), - NotificationEvent(eventSource1, listOf(status1, status2)) - ) - val eventInfo4 = NotificationEventInfo( - "event_id4", - Instant.now(), - Instant.now(), - NotificationEvent(eventSource2, listOf(status1, status2)) - ) - val searchResult = NotificationEventSearchResult( - 100, - 1000, - TotalHits.Relation.GREATER_THAN_OR_EQUAL_TO, - listOf(eventInfo1, eventInfo2, eventInfo3, eventInfo4) - ) - val searchResponse = GetNotificationEventResponse(searchResult) - val recreatedObject = recreateObject(searchResponse) { GetNotificationEventResponse(it) } - assertSearchResultEquals(searchResult, recreatedObject.searchResult) - } - - @Test - fun `Search result serialize and deserialize using json event object should be equal`() { - val lastUpdatedTimeMs = Instant.ofEpochMilli(Instant.now().toEpochMilli()) - val createdTimeMs = lastUpdatedTimeMs.minusSeconds(1000) - val sampleEventSource = EventSource( - "title", - "reference_id", - severity = SeverityType.INFO - ) - val sampleStatus = EventStatus( - "config_id", - "name", - ConfigType.SLACK, - deliveryStatus = DeliveryStatus("404", "invalid recipient") - ) - val sampleEvent = NotificationEvent(sampleEventSource, listOf(sampleStatus)) - val eventInfo = NotificationEventInfo( - "event_id", - lastUpdatedTimeMs, - createdTimeMs, - sampleEvent - ) - val searchResult = NotificationEventSearchResult(eventInfo) - val searchResponse = GetNotificationEventResponse(searchResult) - val jsonString = getJsonString(searchResponse) - val recreatedObject = createObjectFromJsonString(jsonString) { GetNotificationEventResponse.parse(it) } - assertSearchResultEquals(searchResult, recreatedObject.searchResult) - } - - @Test - fun `Search result serialize and deserialize using json with multiple event object should be equal`() { - val lastUpdatedTimeMs = Instant.ofEpochMilli(Instant.now().toEpochMilli()) - val createdTimeMs = lastUpdatedTimeMs.minusSeconds(1000) - val eventSource1 = EventSource( - "title 1", - "reference_id_1", - severity = SeverityType.INFO - ) - val eventSource2 = EventSource( - "title 2", - "reference_id_2", - severity = SeverityType.HIGH - ) - val status1 = EventStatus( - "config_id1", - "name", - ConfigType.SLACK, - deliveryStatus = DeliveryStatus("200", "success") - ) - val status2 = EventStatus( - "config_id2", - "name", - ConfigType.CHIME, - deliveryStatus = DeliveryStatus("404", "invalid recipient") - ) - val eventInfo1 = NotificationEventInfo( - "event_id1", - lastUpdatedTimeMs, - createdTimeMs, - NotificationEvent(eventSource1, listOf(status1)) - ) - val eventInfo2 = NotificationEventInfo( - "event_id2", - lastUpdatedTimeMs, - createdTimeMs, - NotificationEvent(eventSource2, listOf(status2)) - ) - val searchResult = NotificationEventSearchResult( - 100, - 1000, - TotalHits.Relation.GREATER_THAN_OR_EQUAL_TO, - listOf(eventInfo1, eventInfo2) - ) - val searchResponse = GetNotificationEventResponse(searchResult) - val jsonString = getJsonString(searchResponse) - val recreatedObject = createObjectFromJsonString(jsonString) { GetNotificationEventResponse.parse(it) } - assertSearchResultEquals(searchResult, recreatedObject.searchResult) - } - - @Test - fun `Search result should safely ignore extra field in json object`() { - val lastUpdatedTimeMs = Instant.ofEpochMilli(Instant.now().toEpochMilli()) - val createdTimeMs = lastUpdatedTimeMs.minusSeconds(1000) - val sampleEventSource = EventSource( - "title", - "reference_id", - severity = SeverityType.INFO - ) - val sampleStatus = EventStatus( - "config_id", - "name", - ConfigType.SLACK, - deliveryStatus = DeliveryStatus("200", "success") - ) - val sampleEvent = NotificationEvent(sampleEventSource, listOf(sampleStatus)) - val eventInfo = NotificationEventInfo( - "event_id", - lastUpdatedTimeMs, - createdTimeMs, - sampleEvent - ) - val searchResult = NotificationEventSearchResult(eventInfo) - val jsonString = """ - { - "start_index":"0", - "total_hits":"1", - "total_hit_relation":"eq", - "event_list":[ - { - "event_id":"event_id", - "last_updated_time_ms":"${lastUpdatedTimeMs.toEpochMilli()}", - "created_time_ms":"${createdTimeMs.toEpochMilli()}", - "event":{ - "event_source":{ - "title":"title", - "reference_id":"reference_id", - "severity":"info", - "tags":[] - }, - "status_list":[ - { - "config_id":"config_id", - "config_type":"slack", - "config_name":"name", - "delivery_status": - { - "status_code":"200", - "status_text":"success" - } - } - ] - } - } - ], - "extra_field_1":["extra", "value"], - "extra_field_2":{"extra":"value"}, - "extra_field_3":"extra value 3" - } - """.trimIndent() - val recreatedObject = createObjectFromJsonString(jsonString) { GetNotificationEventResponse.parse(it) } - assertSearchResultEquals(searchResult, recreatedObject.searchResult) - } - - @Test - fun `Search result should safely fallback to default if startIndex, totalHits or totalHitRelation field absent in json object`() { - val lastUpdatedTimeMs = Instant.ofEpochMilli(Instant.now().toEpochMilli()) - val createdTimeMs = lastUpdatedTimeMs.minusSeconds(1000) - val sampleEventSource = EventSource( - "title", - "reference_id", - severity = SeverityType.INFO - ) - val sampleStatus = EventStatus( - "config_id", - "name", - ConfigType.SLACK, - deliveryStatus = DeliveryStatus("200", "success") - ) - val sampleEvent = NotificationEvent(sampleEventSource, listOf(sampleStatus)) - val eventInfo = NotificationEventInfo( - "event_id", - lastUpdatedTimeMs, - createdTimeMs, - sampleEvent - ) - val searchResult = NotificationEventSearchResult(eventInfo) - val jsonString = """ - { - "event_list":[ - { - "event_id":"event_id", - "last_updated_time_ms":"${lastUpdatedTimeMs.toEpochMilli()}", - "created_time_ms":"${createdTimeMs.toEpochMilli()}", - "event":{ - "event_source":{ - "title":"title", - "reference_id":"reference_id", - "severity":"info", - "tags":[] - }, - "status_list":[ - { - "config_id":"config_id", - "config_type":"slack", - "config_name":"name", - "delivery_status": - { - "status_code":"200", - "status_text":"success" - } - } - ] - } - } - ] - } - """.trimIndent() - val recreatedObject = createObjectFromJsonString(jsonString) { GetNotificationEventResponse.parse(it) } - assertSearchResultEquals(searchResult, recreatedObject.searchResult) - } - - @Test - fun `Search result should throw exception if event is absent in json`() { - val lastUpdatedTimeMs = Instant.ofEpochMilli(Instant.now().toEpochMilli()) - val createdTimeMs = lastUpdatedTimeMs.minusSeconds(1000) - val jsonString = """ - { - "start_index":"0", - "total_hits":"1", - "total_hit_relation":"eq", - "event_list":[ - { - "event_id":"event_id", - "last_updated_time_ms":"${lastUpdatedTimeMs.toEpochMilli()}", - "created_time_ms":"${createdTimeMs.toEpochMilli()}" - } - ] - } - """.trimIndent() - Assertions.assertThrows(IllegalArgumentException::class.java) { - createObjectFromJsonString(jsonString) { GetNotificationEventResponse.parse(it) } - } - } -} diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationEventInfoTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationEventInfoTests.kt deleted file mode 100644 index 85d2dee9..00000000 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationEventInfoTests.kt +++ /dev/null @@ -1,273 +0,0 @@ -/* - * Copyright OpenSearch Contributors - * SPDX-License-Identifier: Apache-2.0 - */ -package org.opensearch.commons.notifications.model - -import org.junit.jupiter.api.Assertions -import org.junit.jupiter.api.Assertions.assertEquals -import org.junit.jupiter.api.Test -import org.opensearch.commons.utils.createObjectFromJsonString -import org.opensearch.commons.utils.getJsonString -import org.opensearch.commons.utils.recreateObject -import java.time.Instant - -internal class NotificationEventInfoTests { - - @Test - fun `Event info serialize and deserialize with event object should be equal`() { - val sampleEventSource = EventSource( - "title", - "reference_id", - severity = SeverityType.INFO - ) - val sampleStatus = EventStatus( - "config_id", - "name", - ConfigType.SLACK, - deliveryStatus = DeliveryStatus("404", "invalid recipient") - ) - val sampleEvent = NotificationEvent(sampleEventSource, listOf(sampleStatus)) - val eventInfo = NotificationEventInfo( - "event_id", - Instant.now(), - Instant.now(), - sampleEvent - ) - val recreatedObject = recreateObject(eventInfo) { NotificationEventInfo(it) } - assertEquals(eventInfo, recreatedObject) - } - - @Test - fun `Event info serialize and deserialize using json event object should be equal`() { - val lastUpdatedTimeMs = Instant.ofEpochMilli(Instant.now().toEpochMilli()) - val createdTimeMs = lastUpdatedTimeMs.minusSeconds(1000) - val sampleEventSource = EventSource( - "title", - "reference_id", - severity = SeverityType.INFO - ) - val sampleStatus = EventStatus( - "config_id", - "name", - ConfigType.SLACK, - deliveryStatus = DeliveryStatus("200", "success") - ) - val sampleEvent = NotificationEvent(sampleEventSource, listOf(sampleStatus)) - val eventInfo = NotificationEventInfo( - "event_id", - lastUpdatedTimeMs, - createdTimeMs, - sampleEvent - ) - val jsonString = getJsonString(eventInfo) - val recreatedObject = createObjectFromJsonString(jsonString) { NotificationEventInfo.parse(it) } - assertEquals(eventInfo, recreatedObject) - } - - @Test - fun `Event info should safely ignore extra field in json object`() { - val lastUpdatedTimeMs = Instant.ofEpochMilli(Instant.now().toEpochMilli()) - val createdTimeMs = lastUpdatedTimeMs.minusSeconds(1000) - val sampleEventSource = EventSource( - "title", - "reference_id", - severity = SeverityType.INFO - ) - val sampleStatus = EventStatus( - "config_id", - "name", - ConfigType.SLACK, - deliveryStatus = DeliveryStatus("200", "success") - ) - val sampleEvent = NotificationEvent(sampleEventSource, listOf(sampleStatus)) - val eventInfo = NotificationEventInfo( - "event_id", - lastUpdatedTimeMs, - createdTimeMs, - sampleEvent - ) - val jsonString = """ - { - "event_id":"event_id", - "last_updated_time_ms":"${lastUpdatedTimeMs.toEpochMilli()}", - "created_time_ms":"${createdTimeMs.toEpochMilli()}", - "event":{ - "event_source":{ - "title":"title", - "reference_id":"reference_id", - "feature":"alerting", - "severity":"info", - "tags":[] - }, - "status_list":[ - { - "config_id":"config_id", - "config_type":"slack", - "config_name":"name", - "delivery_status": - { - "status_code":"200", - "status_text":"success" - } - } - ] - }, - "extra_field_1":["extra", "value"], - "extra_field_2":{"extra":"value"}, - "extra_field_3":"extra value 3" - } - """.trimIndent() - val recreatedObject = createObjectFromJsonString(jsonString) { NotificationEventInfo.parse(it) } - assertEquals(eventInfo, recreatedObject) - } - - @Test - fun `Event info should throw exception if event_id is empty`() { - val lastUpdatedTimeMs = Instant.ofEpochMilli(Instant.now().toEpochMilli()) - val createdTimeMs = lastUpdatedTimeMs.minusSeconds(1000) - val sampleEventSource = EventSource( - "title", - "reference_id", - severity = SeverityType.INFO - ) - val sampleStatus = EventStatus( - "event_id", - "name", - ConfigType.SLACK, - deliveryStatus = DeliveryStatus("200", "success") - ) - val sampleEvent = NotificationEvent(sampleEventSource, listOf(sampleStatus)) - Assertions.assertThrows(IllegalArgumentException::class.java) { - NotificationEventInfo( - "", - lastUpdatedTimeMs, - createdTimeMs, - sampleEvent - ) - } - } - - @Test - fun `Event info should throw exception if event_id is absent in json`() { - val lastUpdatedTimeMs = Instant.ofEpochMilli(Instant.now().toEpochMilli()) - val createdTimeMs = lastUpdatedTimeMs.minusSeconds(1000) - val jsonString = """ - { - "last_updated_time_ms":"${lastUpdatedTimeMs.toEpochMilli()}", - "created_time_ms":"${createdTimeMs.toEpochMilli()}", - "event":{ - "event_source":{ - "title":"title", - "reference_id":"reference_id", - "feature":"alerting", - "severity":"info", - "tags":["tag1", "tag2"] - }, - "status_list":[ - { - "event_id":"event_id", - "config_type":"slack", - "config_name":"name", - "delivery_status": - { - "status_code":"200", - "status_text":"success" - } - } - ] - } - } - """.trimIndent() - Assertions.assertThrows(IllegalArgumentException::class.java) { - createObjectFromJsonString(jsonString) { NotificationEventInfo.parse(it) } - } - } - - @Test - fun `Event info should throw exception if lastUpdatedTimeMs is absent in json`() { - val lastUpdatedTimeMs = Instant.ofEpochMilli(Instant.now().toEpochMilli()) - val createdTimeMs = lastUpdatedTimeMs.minusSeconds(1000) - val jsonString = """ - { - "event_id":"event_id", - "created_time_ms":"${createdTimeMs.toEpochMilli()}", - "event":{ - "event_source":{ - "title":"title", - "reference_id":"reference_id", - "feature":"alerting", - "severity":"info", - "tags":["tag1", "tag2"] - }, - "status_list":[ - { - "event_id":"event_id", - "config_type":"slack", - "config_name":"name", - "delivery_status": - { - "status_code":"200", - "status_text":"success" - } - } - ] - } - } - """.trimIndent() - Assertions.assertThrows(IllegalArgumentException::class.java) { - createObjectFromJsonString(jsonString) { NotificationEventInfo.parse(it) } - } - } - - @Test - fun `Event info should throw exception if createdTimeMs is absent in json`() { - val lastUpdatedTimeMs = Instant.ofEpochMilli(Instant.now().toEpochMilli()) - val jsonString = """ - { - "event_id":"event_id", - "last_updated_time_ms":"${lastUpdatedTimeMs.toEpochMilli()}", - "event":{ - "event_source":{ - "title":"title", - "reference_id":"reference_id", - "feature":"alerting", - "severity":"info", - "tags":["tag1", "tag2"] - }, - "status_list":[ - { - "event_id":"event_id", - "config_type":"slack", - "config_name":"name", - "delivery_status": - { - "status_code":"200", - "status_text":"success" - } - } - ] - } - } - """.trimIndent() - Assertions.assertThrows(IllegalArgumentException::class.java) { - createObjectFromJsonString(jsonString) { NotificationEventInfo.parse(it) } - } - } - - @Test - fun `Event info should throw exception if event is absent in json`() { - val lastUpdatedTimeMs = Instant.ofEpochMilli(Instant.now().toEpochMilli()) - val createdTimeMs = lastUpdatedTimeMs.minusSeconds(1000) - val jsonString = """ - { - "event_id":"event_id", - "last_updated_time_ms":"${lastUpdatedTimeMs.toEpochMilli()}", - "created_time_ms":"${createdTimeMs.toEpochMilli()}" - } - """.trimIndent() - Assertions.assertThrows(IllegalArgumentException::class.java) { - createObjectFromJsonString(jsonString) { NotificationEventInfo.parse(it) } - } - } -} diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationEventSearchResultTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationEventSearchResultTests.kt deleted file mode 100644 index b65a0783..00000000 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationEventSearchResultTests.kt +++ /dev/null @@ -1,396 +0,0 @@ -/* - * Copyright OpenSearch Contributors - * SPDX-License-Identifier: Apache-2.0 - */ -package org.opensearch.commons.notifications.model - -import org.apache.lucene.search.TotalHits -import org.junit.jupiter.api.Assertions -import org.junit.jupiter.api.Assertions.assertEquals -import org.junit.jupiter.api.Test -import org.opensearch.commons.utils.createObjectFromJsonString -import org.opensearch.commons.utils.getJsonString -import org.opensearch.commons.utils.recreateObject -import java.time.Instant - -internal class NotificationEventSearchResultTests { - - private fun assertSearchResultEquals( - expected: NotificationEventSearchResult, - actual: NotificationEventSearchResult - ) { - assertEquals(expected.startIndex, actual.startIndex) - assertEquals(expected.totalHits, actual.totalHits) - assertEquals(expected.totalHitRelation, actual.totalHitRelation) - assertEquals(expected.objectListFieldName, actual.objectListFieldName) - assertEquals(expected.objectList, actual.objectList) - } - - @Test - fun `Search result serialize and deserialize with event object should be equal`() { - val sampleEventSource = EventSource( - "title", - "reference_id", - severity = SeverityType.INFO - ) - val sampleStatus = EventStatus( - "config_id", - "name", - ConfigType.SLACK, - deliveryStatus = DeliveryStatus("404", "invalid recipient") - ) - val sampleEvent = NotificationEvent(sampleEventSource, listOf(sampleStatus)) - val eventInfo = NotificationEventInfo( - "event_id", - Instant.now(), - Instant.now(), - sampleEvent - ) - val searchResult = NotificationEventSearchResult(eventInfo) - val recreatedObject = recreateObject(searchResult) { NotificationEventSearchResult(it) } - assertSearchResultEquals(searchResult, recreatedObject) - } - - @Test - fun `Search result serialize and deserialize with multiple event default values should be equal`() { - val eventSource1 = EventSource( - "title 1", - "reference_id_1", - severity = SeverityType.INFO - ) - val eventSource2 = EventSource( - "title 2", - "reference_id_2", - severity = SeverityType.HIGH - ) - val status1 = EventStatus( - "config_id1", - "name", - ConfigType.SLACK, - deliveryStatus = DeliveryStatus("200", "success") - ) - val status2 = EventStatus( - "config_id2", - "name", - ConfigType.CHIME, - deliveryStatus = DeliveryStatus("404", "invalid recipient") - ) - val eventInfo1 = NotificationEventInfo( - "event_id1", - Instant.now(), - Instant.now(), - NotificationEvent(eventSource1, listOf(status1)) - ) - val eventInfo2 = NotificationEventInfo( - "event_id2", - Instant.now(), - Instant.now(), - NotificationEvent(eventSource2, listOf(status2)) - ) - val eventInfo3 = NotificationEventInfo( - "event_id3", - Instant.now(), - Instant.now(), - NotificationEvent(eventSource1, listOf(status1, status2)) - ) - val eventInfo4 = NotificationEventInfo( - "event_id4", - Instant.now(), - Instant.now(), - NotificationEvent(eventSource2, listOf(status1, status2)) - ) - val searchResult = NotificationEventSearchResult( - listOf(eventInfo1, eventInfo2, eventInfo3, eventInfo4) - ) - val expectedResult = NotificationEventSearchResult( - 0, - 4, - TotalHits.Relation.EQUAL_TO, - listOf(eventInfo1, eventInfo2, eventInfo3, eventInfo4) - ) - val recreatedObject = recreateObject(searchResult) { NotificationEventSearchResult(it) } - assertSearchResultEquals(expectedResult, recreatedObject) - } - - @Test - fun `Search result serialize and deserialize with multiple event status object should be equal`() { - val eventSource1 = EventSource( - "title 1", - "reference_id_1", - severity = SeverityType.INFO - ) - val eventSource2 = EventSource( - "title 2", - "reference_id_2", - severity = SeverityType.HIGH - ) - val status1 = EventStatus( - "config_id1", - "name", - ConfigType.SLACK, - deliveryStatus = DeliveryStatus("200", "success") - ) - val status2 = EventStatus( - "config_id2", - "name", - ConfigType.CHIME, - deliveryStatus = DeliveryStatus("404", "invalid recipient") - ) - val eventInfo1 = NotificationEventInfo( - "event_id1", - Instant.now(), - Instant.now(), - NotificationEvent(eventSource1, listOf(status1)) - ) - val eventInfo2 = NotificationEventInfo( - "event_id2", - Instant.now(), - Instant.now(), - NotificationEvent(eventSource2, listOf(status2)) - ) - val eventInfo3 = NotificationEventInfo( - "event_id3", - Instant.now(), - Instant.now(), - NotificationEvent(eventSource1, listOf(status1, status2)) - ) - val eventInfo4 = NotificationEventInfo( - "event_id4", - Instant.now(), - Instant.now(), - NotificationEvent(eventSource2, listOf(status1, status2)) - ) - val searchResult = NotificationEventSearchResult( - 100, - 1000, - TotalHits.Relation.GREATER_THAN_OR_EQUAL_TO, - listOf(eventInfo1, eventInfo2, eventInfo3, eventInfo4) - ) - val recreatedObject = recreateObject(searchResult) { NotificationEventSearchResult(it) } - assertSearchResultEquals(searchResult, recreatedObject) - } - - @Test - fun `Search result serialize and deserialize using json event object should be equal`() { - val lastUpdatedTimeMs = Instant.ofEpochMilli(Instant.now().toEpochMilli()) - val createdTimeMs = lastUpdatedTimeMs.minusSeconds(1000) - val sampleEventSource = EventSource( - "title", - "reference_id", - severity = SeverityType.INFO - ) - val sampleStatus = EventStatus( - "config_id", - "name", - ConfigType.SLACK, - deliveryStatus = DeliveryStatus("404", "invalid recipient") - ) - val sampleEvent = NotificationEvent(sampleEventSource, listOf(sampleStatus)) - val eventInfo = NotificationEventInfo( - "event_id", - lastUpdatedTimeMs, - createdTimeMs, - sampleEvent - ) - val searchResult = NotificationEventSearchResult(eventInfo) - val jsonString = getJsonString(searchResult) - val recreatedObject = createObjectFromJsonString(jsonString) { NotificationEventSearchResult(it) } - assertSearchResultEquals(searchResult, recreatedObject) - } - - @Test - fun `Search result serialize and deserialize using json with multiple event object should be equal`() { - val lastUpdatedTimeMs = Instant.ofEpochMilli(Instant.now().toEpochMilli()) - val createdTimeMs = lastUpdatedTimeMs.minusSeconds(1000) - val eventSource1 = EventSource( - "title 1", - "reference_id_1", - severity = SeverityType.INFO - ) - val eventSource2 = EventSource( - "title 2", - "reference_id_2", - severity = SeverityType.HIGH - ) - val status1 = EventStatus( - "config_id1", - "name", - ConfigType.SLACK, - deliveryStatus = DeliveryStatus("200", "success") - ) - val status2 = EventStatus( - "config_id2", - "name", - ConfigType.CHIME, - deliveryStatus = DeliveryStatus("404", "invalid recipient") - ) - val eventInfo1 = NotificationEventInfo( - "event_id1", - lastUpdatedTimeMs, - createdTimeMs, - NotificationEvent(eventSource1, listOf(status1)) - ) - val eventInfo2 = NotificationEventInfo( - "event_id2", - lastUpdatedTimeMs, - createdTimeMs, - NotificationEvent(eventSource2, listOf(status2)) - ) - val searchResult = NotificationEventSearchResult( - 100, - 1000, - TotalHits.Relation.GREATER_THAN_OR_EQUAL_TO, - listOf(eventInfo1, eventInfo2) - ) - val jsonString = getJsonString(searchResult) - val recreatedObject = createObjectFromJsonString(jsonString) { NotificationEventSearchResult(it) } - assertSearchResultEquals(searchResult, recreatedObject) - } - - @Test - fun `Search result should safely ignore extra field in json object`() { - val lastUpdatedTimeMs = Instant.ofEpochMilli(Instant.now().toEpochMilli()) - val createdTimeMs = lastUpdatedTimeMs.minusSeconds(1000) - val sampleEventSource = EventSource( - "title", - "reference_id", - severity = SeverityType.INFO - ) - val sampleStatus = EventStatus( - "config_id", - "name", - ConfigType.SLACK, - deliveryStatus = DeliveryStatus("200", "success") - ) - val sampleEvent = NotificationEvent(sampleEventSource, listOf(sampleStatus)) - val eventInfo = NotificationEventInfo( - "event_id", - lastUpdatedTimeMs, - createdTimeMs, - sampleEvent - ) - val searchResult = NotificationEventSearchResult(eventInfo) - val jsonString = """ - { - "start_index":"0", - "total_hits":"1", - "total_hit_relation":"eq", - "event_list":[ - { - "event_id":"event_id", - "last_updated_time_ms":"${lastUpdatedTimeMs.toEpochMilli()}", - "created_time_ms":"${createdTimeMs.toEpochMilli()}", - "event":{ - "event_source":{ - "title":"title", - "reference_id":"reference_id", - "feature":"alerting", - "severity":"info", - "tags":[] - }, - "status_list":[ - { - "config_id":"config_id", - "config_type":"slack", - "config_name":"name", - "delivery_status": - { - "status_code":"200", - "status_text":"success" - } - } - ] - } - } - ], - "extra_field_1":["extra", "value"], - "extra_field_2":{"extra":"value"}, - "extra_field_3":"extra value 3" - } - """.trimIndent() - val recreatedObject = createObjectFromJsonString(jsonString) { NotificationEventSearchResult(it) } - assertSearchResultEquals(searchResult, recreatedObject) - } - - @Test - fun `Search result should safely fallback to default if startIndex, totalHits or totalHitRelation field absent in json object`() { - val lastUpdatedTimeMs = Instant.ofEpochMilli(Instant.now().toEpochMilli()) - val createdTimeMs = lastUpdatedTimeMs.minusSeconds(1000) - val sampleEventSource = EventSource( - "title", - "reference_id", - severity = SeverityType.INFO - ) - val sampleStatus = EventStatus( - "config_id", - "name", - ConfigType.SLACK, - deliveryStatus = DeliveryStatus("200", "success") - ) - val sampleEvent = NotificationEvent(sampleEventSource, listOf(sampleStatus)) - val eventInfo = NotificationEventInfo( - "event_id", - lastUpdatedTimeMs, - createdTimeMs, - sampleEvent - ) - val searchResult = NotificationEventSearchResult(eventInfo) - val jsonString = """ - { - "event_list":[ - { - "event_id":"event_id", - "last_updated_time_ms":"${lastUpdatedTimeMs.toEpochMilli()}", - "created_time_ms":"${createdTimeMs.toEpochMilli()}", - "event":{ - "event_source":{ - "title":"title", - "reference_id":"reference_id", - "feature":"alerting", - "severity":"info", - "tags":[] - }, - "status_list":[ - { - "config_id":"config_id", - "config_type":"slack", - "config_name":"name", - "delivery_status": - { - "status_code":"200", - "status_text":"success" - } - } - ] - } - } - ] - } - """.trimIndent() - val recreatedObject = createObjectFromJsonString(jsonString) { NotificationEventSearchResult(it) } - assertSearchResultEquals(searchResult, recreatedObject) - } - - @Test - fun `Search result should throw exception if event is absent in json`() { - val lastUpdatedTimeMs = Instant.ofEpochMilli(Instant.now().toEpochMilli()) - val createdTimeMs = lastUpdatedTimeMs.minusSeconds(1000) - val jsonString = """ - { - "start_index":"0", - "total_hits":"1", - "total_hit_relation":"eq", - "event_list":[ - { - "event_id":"event_id", - "last_updated_time_ms":"${lastUpdatedTimeMs.toEpochMilli()}", - "created_time_ms":"${createdTimeMs.toEpochMilli()}" - } - ] - } - """.trimIndent() - Assertions.assertThrows(IllegalArgumentException::class.java) { - createObjectFromJsonString(jsonString) { NotificationEventSearchResult(it) } - } - } -} From bf1e3afb79f12d80a4f97212dc31f2be9b3d9d8a Mon Sep 17 00:00:00 2001 From: "Daniel Doubrovkine (dB.)" Date: Wed, 6 Apr 2022 16:41:59 -0400 Subject: [PATCH 120/140] Updated issue templates from .github. (#154) Signed-off-by: dblock Signed-off-by: Zelin Hao --- .github/ISSUE_TEMPLATE/bug_report.md | 28 +++++++++++------------ .github/ISSUE_TEMPLATE/config.yml | 7 ++++++ .github/ISSUE_TEMPLATE/feature_request.md | 17 +++++++------- 3 files changed, 28 insertions(+), 24 deletions(-) create mode 100644 .github/ISSUE_TEMPLATE/config.yml diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 8af6ebb5..29eddb95 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -1,33 +1,31 @@ --- name: 🐛 Bug report about: Create a report to help us improve -title: "[BUG]" -labels: 'bug, untriaged, Beta' +title: '[BUG]' +labels: 'bug, untriaged' assignees: '' --- -**Describe the bug** -A clear and concise description of what the bug is. +**What is the bug?** +A clear and concise description of the bug. -**To Reproduce** +**How can one reproduce the bug?** Steps to reproduce the behavior: 1. Go to '...' 2. Click on '....' 3. Scroll down to '....' 4. See error -**Expected behavior** +**What is the expected behavior?** A clear and concise description of what you expected to happen. -**Plugins** -Please list all plugins currently enabled. - -**Screenshots** -If applicable, add screenshots to help explain your problem. - -**Host/Environment (please complete the following information):** +**What is your host/environment?** - OS: [e.g. iOS] - Version [e.g. 22] + - Plugins + +**Do you have any screenshots?** +If applicable, add screenshots to help explain your problem. -**Additional context** -Add any other context about the problem here. \ No newline at end of file +**Do you have any additional context?** +Add any other context about the problem. diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 00000000..a8199a10 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,7 @@ +contact_links: + - name: OpenSearch Community Support + url: https://discuss.opendistrocommunity.dev/ + about: Please ask and answer questions here. + - name: AWS/Amazon Security + url: https://aws.amazon.com/security/vulnerability-reporting/ + about: Please report security vulnerabilities here. \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md index 2791b808..6198f338 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -1,19 +1,18 @@ --- name: 🎆 Feature request -about: Suggest an idea for this project -title: '' -labels: enhancement +about: Request a feature in this project +title: '[FEATURE]' +labels: 'enhancement, untriaged' assignees: '' --- +**Is your feature request related to a problem?** +A clear and concise description of what the problem is, e.g. _I'm always frustrated when [...]_ -**Is your feature request related to a problem? Please describe.** -A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] - -**Describe the solution you'd like** +**What solution would you like?** A clear and concise description of what you want to happen. -**Describe alternatives you've considered** +**What alternatives have you considered?** A clear and concise description of any alternative solutions or features you've considered. -**Additional context** +**Do you have any additional context?** Add any other context or screenshots about the feature request here. \ No newline at end of file From 860166569bf63104bd92a8339aa8db876c12ad6f Mon Sep 17 00:00:00 2001 From: Aditya Jindal <13850971+aditjind@users.noreply.github.com> Date: Thu, 7 Apr 2022 15:51:50 -0700 Subject: [PATCH 121/140] Addition of NotificationEvent to SendNotificationResponse and Removal of NotificationID (#156) * Removal of NotificationEvent Request, Response , Search Results Addition of NotificationEventDoc and Removal of NotificationEventInfo Addition of NotificationEventDocTests Signed-off-by: Jindal * Removing NotificationEventDoc and NotificationEventDocTests Signed-off-by: Jindal Co-authored-by: Jindal Signed-off-by: Zelin Hao --- .../action/SendNotificationResponse.kt | 43 ++++----------- .../NotificationsPluginInterfaceTests.kt | 14 ++++- .../action/SendNotificationResponseTests.kt | 52 ++++++++++++++----- 3 files changed, 61 insertions(+), 48 deletions(-) diff --git a/src/main/kotlin/org/opensearch/commons/notifications/action/SendNotificationResponse.kt b/src/main/kotlin/org/opensearch/commons/notifications/action/SendNotificationResponse.kt index 96599b3a..8967bdd9 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/action/SendNotificationResponse.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/action/SendNotificationResponse.kt @@ -10,19 +10,16 @@ import org.opensearch.common.io.stream.Writeable import org.opensearch.common.xcontent.ToXContent import org.opensearch.common.xcontent.XContentBuilder import org.opensearch.common.xcontent.XContentParser -import org.opensearch.common.xcontent.XContentParserUtils -import org.opensearch.commons.notifications.NotificationConstants.EVENT_ID_TAG -import org.opensearch.commons.utils.logger +import org.opensearch.commons.notifications.model.NotificationEvent import java.io.IOException /** * Action Response for send notification. */ class SendNotificationResponse : BaseResponse { - val notificationId: String + val notificationEvent: NotificationEvent companion object { - private val log by logger(SendNotificationResponse::class.java) /** * reader to create instance of class from writable. @@ -36,35 +33,16 @@ class SendNotificationResponse : BaseResponse { @JvmStatic @Throws(IOException::class) fun parse(parser: XContentParser): SendNotificationResponse { - var notificationId: String? = null - - XContentParserUtils.ensureExpectedToken( - XContentParser.Token.START_OBJECT, - parser.currentToken(), - parser - ) - while (parser.nextToken() != XContentParser.Token.END_OBJECT) { - val fieldName = parser.currentName() - parser.nextToken() - when (fieldName) { - EVENT_ID_TAG -> notificationId = parser.text() - else -> { - parser.skipChildren() - log.info("Unexpected field: $fieldName, while parsing SendNotificationResponse") - } - } - } - notificationId ?: throw IllegalArgumentException("$EVENT_ID_TAG field absent") - return SendNotificationResponse(notificationId) + return SendNotificationResponse(NotificationEvent.parse(parser)) } } /** * constructor for creating the class - * @param configId the id of the created notification configuration + * @param notificationEvent the id of the created notification configuration */ - constructor(configId: String) { - this.notificationId = configId + constructor(notificationEvent: NotificationEvent) { + this.notificationEvent = notificationEvent } /** @@ -72,7 +50,7 @@ class SendNotificationResponse : BaseResponse { */ @Throws(IOException::class) constructor(input: StreamInput) : super(input) { - notificationId = input.readString() + notificationEvent = NotificationEvent(input) } /** @@ -80,16 +58,13 @@ class SendNotificationResponse : BaseResponse { */ @Throws(IOException::class) override fun writeTo(output: StreamOutput) { - output.writeString(notificationId) + notificationEvent.writeTo(output) } /** * {@inheritDoc} */ override fun toXContent(builder: XContentBuilder?, params: ToXContent.Params?): XContentBuilder { - builder!! - return builder.startObject() - .field(EVENT_ID_TAG, notificationId) - .endObject() + return notificationEvent.toXContent(builder, params) } } diff --git a/src/test/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterfaceTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterfaceTests.kt index 556c35b6..61cbca7a 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterfaceTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterfaceTests.kt @@ -40,10 +40,13 @@ import org.opensearch.commons.notifications.model.Channel import org.opensearch.commons.notifications.model.ChannelList import org.opensearch.commons.notifications.model.ChannelMessage import org.opensearch.commons.notifications.model.ConfigType +import org.opensearch.commons.notifications.model.DeliveryStatus import org.opensearch.commons.notifications.model.EventSource +import org.opensearch.commons.notifications.model.EventStatus import org.opensearch.commons.notifications.model.NotificationConfig import org.opensearch.commons.notifications.model.NotificationConfigInfo import org.opensearch.commons.notifications.model.NotificationConfigSearchResult +import org.opensearch.commons.notifications.model.NotificationEvent import org.opensearch.commons.notifications.model.SeverityType import org.opensearch.commons.notifications.model.Slack import org.opensearch.rest.RestStatus @@ -180,7 +183,16 @@ internal class NotificationsPluginInterfaceTests { null ) - val response = SendNotificationResponse("configId") + val sampleStatus = EventStatus( + "config_id", + "name", + ConfigType.SLACK, + deliveryStatus = DeliveryStatus("404", "invalid recipient") + ) + + val sampleEvent = NotificationEvent(notificationInfo, listOf(sampleStatus)) + + val response = SendNotificationResponse(sampleEvent) val listener: ActionListener = mock(ActionListener::class.java) as ActionListener diff --git a/src/test/kotlin/org/opensearch/commons/notifications/action/SendNotificationResponseTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/action/SendNotificationResponseTests.kt index ca7f789c..4d828998 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/action/SendNotificationResponseTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/action/SendNotificationResponseTests.kt @@ -5,9 +5,15 @@ package org.opensearch.commons.notifications.action import com.fasterxml.jackson.core.JsonParseException +import org.junit.Test import org.junit.jupiter.api.Assertions.assertEquals -import org.junit.jupiter.api.Test import org.junit.jupiter.api.assertThrows +import org.opensearch.commons.notifications.model.ConfigType +import org.opensearch.commons.notifications.model.DeliveryStatus +import org.opensearch.commons.notifications.model.EventSource +import org.opensearch.commons.notifications.model.EventStatus +import org.opensearch.commons.notifications.model.NotificationEvent +import org.opensearch.commons.notifications.model.SeverityType import org.opensearch.commons.utils.createObjectFromJsonString import org.opensearch.commons.utils.getJsonString import org.opensearch.commons.utils.recreateObject @@ -16,25 +22,29 @@ internal class SendNotificationResponseTests { @Test fun `Create response serialize and deserialize transport object should be equal`() { - val configResponse = SendNotificationResponse("sample_notification_id") - val recreatedObject = recreateObject(configResponse) { SendNotificationResponse(it) } - assertEquals(configResponse.notificationId, recreatedObject.notificationId) + + val sampleEvent = getSampleEvent() + + val recreatedObject = recreateObject(sampleEvent) { SendNotificationResponse(it) } + assertEquals(sampleEvent, recreatedObject) } @Test fun `Create response serialize and deserialize using json object should be equal`() { - val configResponse = SendNotificationResponse("sample_notification_id") - val jsonString = getJsonString(configResponse) + + val sampleEvent = getSampleEvent() + + val jsonString = getJsonString(sampleEvent) val recreatedObject = createObjectFromJsonString(jsonString) { SendNotificationResponse.parse(it) } - assertEquals(configResponse.notificationId, recreatedObject.notificationId) + assertEquals(sampleEvent, recreatedObject) } @Test fun `Create response should deserialize json object using parser`() { - val notificationId = "sample_notification_id" - val jsonString = "{\"event_id\":\"$notificationId\"}" + val sampleEvent = getSampleEvent() + val jsonString = "{\"event_id\":\"$sampleEvent\"}" val recreatedObject = createObjectFromJsonString(jsonString) { SendNotificationResponse.parse(it) } - assertEquals(notificationId, recreatedObject.notificationId) + assertEquals(sampleEvent, recreatedObject) } @Test @@ -55,16 +65,32 @@ internal class SendNotificationResponseTests { @Test fun `Create response should safely ignore extra field in json object`() { - val notificationId = "sample_notification_id" + val sampleEvent = getSampleEvent() val jsonString = """ { - "event_id":"$notificationId", + "event_id":"$sampleEvent", "extra_field_1":["extra", "value"], "extra_field_2":{"extra":"value"}, "extra_field_3":"extra value 3" } """.trimIndent() val recreatedObject = createObjectFromJsonString(jsonString) { SendNotificationResponse.parse(it) } - assertEquals(notificationId, recreatedObject.notificationId) + assertEquals(sampleEvent, recreatedObject) + } + + private fun getSampleEvent(): NotificationEvent { + val sampleEventSource = EventSource( + "title", + "reference_id", + severity = SeverityType.INFO + ) + val sampleStatus = EventStatus( + "config_id", + "name", + ConfigType.SLACK, + deliveryStatus = DeliveryStatus("404", "invalid recipient") + ) + + return NotificationEvent(sampleEventSource, listOf(sampleStatus)) } } From 5f4e3c6c220409af24e5bb50fbcc1b14e29f1b49 Mon Sep 17 00:00:00 2001 From: Saurabh Singh Date: Wed, 13 Apr 2022 23:00:48 -0700 Subject: [PATCH 122/140] Remove JDK 14 (#159) Signed-off-by: Saurabh Singh Signed-off-by: Zelin Hao --- .github/workflows/ci.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 69e7573d..5e017740 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -13,7 +13,6 @@ jobs: matrix: java: - 11 - - 14 - 17 name: Build and Test From 385209edf48f951fbc241c16f08d53b82006ea9f Mon Sep 17 00:00:00 2001 From: "Daniel Doubrovkine (dB.)" Date: Fri, 15 Apr 2022 14:06:06 -0400 Subject: [PATCH 123/140] Incremented version to 2.0-rc1. (#160) Signed-off-by: dblock Signed-off-by: Zelin Hao --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index cf3ca5b9..b3680fcd 100644 --- a/build.gradle +++ b/build.gradle @@ -6,9 +6,9 @@ buildscript { ext { opensearch_group = "org.opensearch" - opensearch_version = System.getProperty("opensearch.version", "2.0.0-alpha1-SNAPSHOT") + opensearch_version = System.getProperty("opensearch.version", "2.0.0-rc1-SNAPSHOT") isSnapshot = "true" == System.getProperty("build.snapshot", "true") - buildVersionQualifier = System.getProperty("build.version_qualifier", "alpha1") + buildVersionQualifier = System.getProperty("build.version_qualifier", "rc1") kotlin_version = System.getProperty("kotlin.version", "1.6.10") } From 80d13c7e22364f136db7bcc4505b0a82b6593bf5 Mon Sep 17 00:00:00 2001 From: Mohammad Qureshi <47198598+qreshi@users.noreply.github.com> Date: Sat, 16 Apr 2022 14:24:12 -0700 Subject: [PATCH 124/140] Support sending email message via Notifications passthrough API (#158) * Add legacy email support as a legacy Destination type Signed-off-by: Mohammad Qureshi <47198598+qreshi@users.noreply.github.com> * Add accountName to LegacyEmailMessage Signed-off-by: Mohammad Qureshi <47198598+qreshi@users.noreply.github.com> Signed-off-by: Zelin Hao --- .../message/LegacyCustomWebhookMessage.java | 5 +- .../message/LegacyDestinationType.java | 3 +- .../message/LegacyEmailMessage.java | 234 ++++++++++++++ .../LegacyPublishNotificationRequest.kt | 2 + .../notifications/model/NotificationEvent.kt | 12 + .../message/LegacyEmailMessageTest.java | 295 ++++++++++++++++++ 6 files changed, 548 insertions(+), 3 deletions(-) create mode 100644 src/main/java/org/opensearch/commons/destination/message/LegacyEmailMessage.java create mode 100644 src/test/java/org/opensearch/commons/destination/message/LegacyEmailMessageTest.java diff --git a/src/main/java/org/opensearch/commons/destination/message/LegacyCustomWebhookMessage.java b/src/main/java/org/opensearch/commons/destination/message/LegacyCustomWebhookMessage.java index d0421ca9..dbc4b7df 100644 --- a/src/main/java/org/opensearch/commons/destination/message/LegacyCustomWebhookMessage.java +++ b/src/main/java/org/opensearch/commons/destination/message/LegacyCustomWebhookMessage.java @@ -236,8 +236,9 @@ public String getMessage() { @Override public void writeTo(StreamOutput streamOutput) throws IOException { super.writeTo(streamOutput); - // Making LegacyCustomWebhookMessage streamable is purely to support the new pass through API from ISM -> Notification plugin - // and it only supports LegacyCustomWebhookMessage when the url is already constructed by ISM. + // Making LegacyCustomWebhookMessage streamable is purely to support the new pass through API from Alerting/ISM -> Notification + // plugin + // and it only supports LegacyCustomWebhookMessage when the url is already constructed by Alerting/ISM. if (Strings.isNullOrEmpty(getUrl())) { throw new IllegalStateException("Cannot use LegacyCustomWebhookMessage across transport wire without defining full url."); } diff --git a/src/main/java/org/opensearch/commons/destination/message/LegacyDestinationType.java b/src/main/java/org/opensearch/commons/destination/message/LegacyDestinationType.java index 1bad1029..f5086c27 100644 --- a/src/main/java/org/opensearch/commons/destination/message/LegacyDestinationType.java +++ b/src/main/java/org/opensearch/commons/destination/message/LegacyDestinationType.java @@ -11,5 +11,6 @@ public enum LegacyDestinationType { LEGACY_CHIME, LEGACY_SLACK, - LEGACY_CUSTOM_WEBHOOK + LEGACY_CUSTOM_WEBHOOK, + LEGACY_EMAIL } diff --git a/src/main/java/org/opensearch/commons/destination/message/LegacyEmailMessage.java b/src/main/java/org/opensearch/commons/destination/message/LegacyEmailMessage.java new file mode 100644 index 00000000..01810868 --- /dev/null +++ b/src/main/java/org/opensearch/commons/destination/message/LegacyEmailMessage.java @@ -0,0 +1,234 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.opensearch.commons.destination.message; + +import java.io.IOException; +import java.net.URI; +import java.util.List; + +import org.opensearch.common.Strings; +import org.opensearch.common.io.stream.StreamInput; +import org.opensearch.common.io.stream.StreamOutput; +import org.opensearch.commons.notifications.model.MethodType; + +/** + * This class holds the content of an CustomWebhook message + */ +public class LegacyEmailMessage extends LegacyBaseMessage { + + private final String accountName; + private final String host; + private final int port; + private final String method; + private final String from; + private final List recipients; + private final String subject; + private final String message; + + private LegacyEmailMessage( + final String destinationName, + final String accountName, + final String host, + final Integer port, + final String method, + final String from, + final List recipients, + final String subject, + final String message + ) { + super(LegacyDestinationType.LEGACY_EMAIL, destinationName, message); + + if (Strings.isNullOrEmpty(message)) { + throw new IllegalArgumentException("Message content is missing"); + } + + if (Strings.isNullOrEmpty(accountName)) { + throw new IllegalArgumentException("Account name should be provided"); + } + + if (Strings.isNullOrEmpty(host)) { + throw new IllegalArgumentException("Host name should be provided"); + } + + if (Strings.isNullOrEmpty(from)) { + throw new IllegalArgumentException("From address should be provided"); + } + + if (recipients == null || recipients.isEmpty()) { + throw new IllegalArgumentException("List of recipients should be provided"); + } + + this.message = message; + this.accountName = accountName; + this.host = host; + this.port = port == null ? 25 : port; + + if (Strings.isNullOrEmpty(method)) { + // Default to "none" + this.method = "none"; + } else if (!MethodType.NONE.toString().equals(method) + && !MethodType.SSL.toString().equals(method) + && !MethodType.START_TLS.toString().equals(method)) { + throw new IllegalArgumentException("Invalid method supplied. Only none, ssl and start_tls are allowed"); + } else { + this.method = method; + } + + this.from = from; + this.recipients = recipients; + this.subject = Strings.isNullOrEmpty(subject) ? destinationName : subject; + } + + public LegacyEmailMessage(StreamInput streamInput) throws IOException { + super(streamInput); + this.message = super.getMessageContent(); + this.accountName = streamInput.readString(); + this.host = streamInput.readString(); + this.port = streamInput.readInt(); + this.method = streamInput.readString(); + this.from = streamInput.readString(); + this.recipients = streamInput.readStringList(); + this.subject = streamInput.readString(); + } + + @Override + public String toString() { + return "DestinationType: " + + getChannelType() + + ", DestinationName:" + + destinationName + + ", AccountName:" + + accountName + + ", From: " + + from + + ", Host: " + + host + + ", Port: " + + port + + ", Method: " + + method + + ", Subject: <...>" + + ", Message: <...>"; + } + + public static class Builder { + private final String destinationName; + private String accountName; + private String host; + private Integer port; + private String method; + private String from; + private List recipients; + private String subject; + private String message; + + public Builder(String destinationName) { + this.destinationName = destinationName; + } + + public LegacyEmailMessage.Builder withAccountName(String accountName) { + this.accountName = accountName; + return this; + } + + public LegacyEmailMessage.Builder withHost(String host) { + this.host = host; + return this; + } + + public LegacyEmailMessage.Builder withPort(Integer port) { + this.port = port; + return this; + } + + public LegacyEmailMessage.Builder withMethod(String method) { + this.method = method; + return this; + } + + public LegacyEmailMessage.Builder withFrom(String from) { + this.from = from; + return this; + } + + public LegacyEmailMessage.Builder withRecipients(List recipients) { + this.recipients = recipients; + return this; + } + + public LegacyEmailMessage.Builder withSubject(String subject) { + this.subject = subject; + return this; + } + + public LegacyEmailMessage.Builder withMessage(String message) { + this.message = message; + return this; + } + + public LegacyEmailMessage build() { + return new LegacyEmailMessage( + this.destinationName, + this.accountName, + this.host, + this.port, + this.method, + this.from, + this.recipients, + this.subject, + this.message + ); + } + } + + public String getAccountName() { + return accountName; + } + + public String getHost() { + return host; + } + + public int getPort() { + return port; + } + + public String getMethod() { + return method; + } + + public String getFrom() { + return from; + } + + public List getRecipients() { + return recipients; + } + + public String getSubject() { + return subject; + } + + public String getMessage() { + return message; + } + + public URI getUri() { + return buildUri(null, null, host, port, null, null); + } + + @Override + public void writeTo(StreamOutput streamOutput) throws IOException { + super.writeTo(streamOutput); + streamOutput.writeString(accountName); + streamOutput.writeString(host); + streamOutput.writeInt(port); + streamOutput.writeString(method); + streamOutput.writeString(from); + streamOutput.writeStringCollection(recipients); + streamOutput.writeString(subject); + } +} diff --git a/src/main/kotlin/org/opensearch/commons/notifications/action/LegacyPublishNotificationRequest.kt b/src/main/kotlin/org/opensearch/commons/notifications/action/LegacyPublishNotificationRequest.kt index 508815a8..211e2076 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/action/LegacyPublishNotificationRequest.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/action/LegacyPublishNotificationRequest.kt @@ -14,6 +14,7 @@ import org.opensearch.commons.destination.message.LegacyBaseMessage import org.opensearch.commons.destination.message.LegacyChimeMessage import org.opensearch.commons.destination.message.LegacyCustomWebhookMessage import org.opensearch.commons.destination.message.LegacyDestinationType +import org.opensearch.commons.destination.message.LegacyEmailMessage import org.opensearch.commons.destination.message.LegacySlackMessage import java.io.IOException @@ -50,6 +51,7 @@ class LegacyPublishNotificationRequest : ActionRequest { LegacyDestinationType.LEGACY_CHIME -> LegacyChimeMessage(input) LegacyDestinationType.LEGACY_CUSTOM_WEBHOOK -> LegacyCustomWebhookMessage(input) LegacyDestinationType.LEGACY_SLACK -> LegacySlackMessage(input) + LegacyDestinationType.LEGACY_EMAIL -> LegacyEmailMessage(input) } } diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationEvent.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationEvent.kt index a76f552d..6bc49d5f 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationEvent.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationEvent.kt @@ -8,9 +8,12 @@ import org.opensearch.common.io.stream.StreamInput import org.opensearch.common.io.stream.StreamOutput import org.opensearch.common.io.stream.Writeable import org.opensearch.common.xcontent.ToXContent +import org.opensearch.common.xcontent.ToXContent.EMPTY_PARAMS import org.opensearch.common.xcontent.XContentBuilder +import org.opensearch.common.xcontent.XContentHelper import org.opensearch.common.xcontent.XContentParser import org.opensearch.common.xcontent.XContentParserUtils +import org.opensearch.common.xcontent.XContentType import org.opensearch.commons.notifications.NotificationConstants.EVENT_SOURCE_TAG import org.opensearch.commons.notifications.NotificationConstants.STATUS_LIST_TAG import org.opensearch.commons.utils.logger @@ -102,4 +105,13 @@ data class NotificationEvent( .field(STATUS_LIST_TAG, statusList) .endObject() } + + // Overriding toString so consuming plugins can log/output this from the sendNotification response if needed + override fun toString(): String { + return try { + XContentHelper.toXContent(this, XContentType.JSON, EMPTY_PARAMS, true).utf8ToString() + } catch (e: IOException) { + super.toString() + " threw " + e.toString() + } + } } diff --git a/src/test/java/org/opensearch/commons/destination/message/LegacyEmailMessageTest.java b/src/test/java/org/opensearch/commons/destination/message/LegacyEmailMessageTest.java new file mode 100644 index 00000000..06625053 --- /dev/null +++ b/src/test/java/org/opensearch/commons/destination/message/LegacyEmailMessageTest.java @@ -0,0 +1,295 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.opensearch.commons.destination.message; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.fail; + +import java.io.IOException; +import java.util.Arrays; +import java.util.List; + +import org.junit.jupiter.api.Test; +import org.opensearch.common.io.stream.BytesStreamOutput; +import org.opensearch.common.io.stream.StreamInput; + +public class LegacyEmailMessageTest { + + @Test + public void testBuildingLegacyEmailMessage() { + LegacyEmailMessage message = new LegacyEmailMessage.Builder("email") + .withAccountName("test_email") + .withHost("smtp.test.com") + .withPort(123) + .withMethod("none") + .withFrom("test@email.com") + .withRecipients(Arrays.asList("test2@email.com", "test3@email.com")) + .withSubject("Test Subject") + .withMessage("Hello world") + .build(); + + assertEquals("email", message.destinationName); + assertEquals(LegacyDestinationType.LEGACY_EMAIL, message.getChannelType()); + assertEquals("test_email", message.getAccountName()); + assertEquals("smtp.test.com", message.getHost()); + assertEquals(123, message.getPort()); + assertEquals("none", message.getMethod()); + assertEquals("test@email.com", message.getFrom()); + assertEquals(Arrays.asList("test2@email.com", "test3@email.com"), message.getRecipients()); + assertEquals("Test Subject", message.getSubject()); + assertEquals("Hello world", message.getMessage()); + } + + @Test + public void testRoundTrippingLegacyEmailMessage() throws IOException { + LegacyEmailMessage message = new LegacyEmailMessage.Builder("email") + .withAccountName("test_email") + .withHost("smtp.test.com") + .withPort(123) + .withMethod("none") + .withFrom("test@email.com") + .withRecipients(Arrays.asList("test2@email.com", "test3@email.com")) + .withSubject("Test Subject") + .withMessage("Hello world") + .build(); + BytesStreamOutput out = new BytesStreamOutput(); + message.writeTo(out); + + StreamInput in = StreamInput.wrap(out.bytes().toBytesRef().bytes); + LegacyEmailMessage newMessage = new LegacyEmailMessage(in); + + assertEquals(newMessage.destinationName, message.destinationName); + assertEquals(newMessage.getChannelType(), message.getChannelType()); + assertEquals(newMessage.getAccountName(), message.getAccountName()); + assertEquals(newMessage.getHost(), message.getHost()); + assertEquals(newMessage.getPort(), message.getPort()); + assertEquals(newMessage.getMethod(), message.getMethod()); + assertEquals(newMessage.getFrom(), message.getFrom()); + assertEquals(newMessage.getRecipients(), message.getRecipients()); + assertEquals(newMessage.getSubject(), message.getSubject()); + assertEquals(newMessage.getMessage(), message.getMessage()); + } + + @Test + public void testContentMissingMessage() { + try { + new LegacyEmailMessage.Builder("email") + .withAccountName("test_email") + .withHost("smtp.test.com") + .withPort(123) + .withMethod("none") + .withFrom("test@email.com") + .withRecipients(Arrays.asList("test2@email.com", "test3@email.com")) + .withSubject("Test Subject") + .build(); + fail("Building legacy email message without message should fail"); + } catch (IllegalArgumentException e) { + assertEquals("Message content is missing", e.getMessage()); + } + } + + @Test + public void testMissingDestinationName() { + try { + new LegacyEmailMessage.Builder(null) + .withAccountName("test_email") + .withHost("smtp.test.com") + .withPort(123) + .withMethod("none") + .withFrom("test@email.com") + .withRecipients(Arrays.asList("test2@email.com", "test3@email.com")) + .withSubject("Test Subject") + .withMessage("Hello world") + .build(); + fail("Building legacy email message with null destination name should fail"); + } catch (IllegalArgumentException e) { + assertEquals("Channel name must be defined", e.getMessage()); + } + } + + @Test + public void testUnsupportedMethods() { + try { + new LegacyEmailMessage.Builder("email") + .withAccountName("test_email") + .withHost("smtp.test.com") + .withPort(123) + .withMethod("unsupported") + .withFrom("test@email.com") + .withRecipients(Arrays.asList("test2@email.com", "test3@email.com")) + .withSubject("Test Subject") + .withMessage("Hello world") + .build(); + fail("Building legacy email message with unsupported method should fail"); + } catch (IllegalArgumentException e) { + assertEquals("Invalid method supplied. Only none, ssl and start_tls are allowed", e.getMessage()); + } + } + + @Test + public void testAccountNameMissingOrEmpty() { + try { + new LegacyEmailMessage.Builder("email") + .withHost("smtp.test.com") + .withPort(123) + .withMethod("none") + .withFrom("test@email.com") + .withRecipients(Arrays.asList("test2@email.com", "test3@email.com")) + .withSubject("Test Subject") + .withMessage("Hello world") + .build(); + fail("Building legacy email message with missing account name should fail"); + } catch (IllegalArgumentException e) { + assertEquals("Account name should be provided", e.getMessage()); + } + + try { + new LegacyEmailMessage.Builder("email") + .withAccountName("") + .withHost("smtp.test.com") + .withPort(123) + .withMethod("none") + .withFrom("test@email.com") + .withRecipients(Arrays.asList("test2@email.com", "test3@email.com")) + .withSubject("Test Subject") + .withMessage("Hello world") + .build(); + fail("Building legacy email message with empty account name should fail"); + } catch (IllegalArgumentException e) { + assertEquals("Account name should be provided", e.getMessage()); + } + } + + @Test + public void testHostMissingOrEmpty() { + try { + new LegacyEmailMessage.Builder("email") + .withAccountName("test_email") + .withPort(123) + .withMethod("none") + .withFrom("test@email.com") + .withRecipients(Arrays.asList("test2@email.com", "test3@email.com")) + .withSubject("Test Subject") + .withMessage("Hello world") + .build(); + fail("Building legacy email message with missing host should fail"); + } catch (IllegalArgumentException e) { + assertEquals("Host name should be provided", e.getMessage()); + } + + try { + new LegacyEmailMessage.Builder("email") + .withAccountName("test_email") + .withHost("") + .withPort(123) + .withMethod("none") + .withFrom("test@email.com") + .withRecipients(Arrays.asList("test2@email.com", "test3@email.com")) + .withSubject("Test Subject") + .withMessage("Hello world") + .build(); + fail("Building legacy email message with empty host should fail"); + } catch (IllegalArgumentException e) { + assertEquals("Host name should be provided", e.getMessage()); + } + } + + @Test + public void testFromMissingOrEmpty() { + try { + new LegacyEmailMessage.Builder("email") + .withAccountName("test_email") + .withHost("smtp.test.com") + .withPort(123) + .withMethod("none") + .withRecipients(Arrays.asList("test2@email.com", "test3@email.com")) + .withSubject("Test Subject") + .withMessage("Hello world") + .build(); + fail("Building legacy email message with missing from should fail"); + } catch (IllegalArgumentException e) { + assertEquals("From address should be provided", e.getMessage()); + } + + try { + new LegacyEmailMessage.Builder("email") + .withAccountName("test_email") + .withHost("smtp.test.com") + .withPort(123) + .withMethod("none") + .withFrom("") + .withRecipients(Arrays.asList("test2@email.com", "test3@email.com")) + .withSubject("Test Subject") + .withMessage("Hello world") + .build(); + fail("Building legacy email message with empty from should fail"); + } catch (IllegalArgumentException e) { + assertEquals("From address should be provided", e.getMessage()); + } + } + + @Test + public void testRecipientsMissingOrEmpty() { + try { + new LegacyEmailMessage.Builder("email") + .withAccountName("test_email") + .withHost("smtp.test.com") + .withPort(123) + .withMethod("none") + .withFrom("test@email.com") + .withSubject("Test Subject") + .withMessage("Hello world") + .build(); + fail("Building legacy email message with missing recipients should fail"); + } catch (IllegalArgumentException e) { + assertEquals("List of recipients should be provided", e.getMessage()); + } + + try { + new LegacyEmailMessage.Builder("email") + .withAccountName("test_email") + .withHost("smtp.test.com") + .withPort(123) + .withMethod("none") + .withFrom("test@email.com") + .withRecipients(List.of()) + .withSubject("Test Subject") + .withMessage("Hello world") + .build(); + fail("Building legacy email message with empty recipients should fail"); + } catch (IllegalArgumentException e) { + assertEquals("List of recipients should be provided", e.getMessage()); + } + } + + @Test + public void testSubjectDefaultsToDestinationNameWhenMissingOrEmpty() { + LegacyEmailMessage message = new LegacyEmailMessage.Builder("email") + .withAccountName("test_email") + .withHost("smtp.test.com") + .withPort(123) + .withMethod("none") + .withFrom("test@email.com") + .withRecipients(Arrays.asList("test2@email.com", "test3@email.com")) + .withMessage("Hello world") + .build(); + + assertEquals("email", message.getSubject()); + + message = new LegacyEmailMessage.Builder("email") + .withAccountName("test_email") + .withHost("smtp.test.com") + .withPort(123) + .withMethod("none") + .withFrom("test@email.com") + .withRecipients(Arrays.asList("test2@email.com", "test3@email.com")) + .withSubject("") + .withMessage("Hello world") + .build(); + + assertEquals("email", message.getSubject()); + } +} From 315b710f43b728ce2947ee916fdedca2243302f9 Mon Sep 17 00:00:00 2001 From: Saurabh Singh Date: Mon, 25 Apr 2022 15:37:16 -0700 Subject: [PATCH 125/140] Add release notes for version 2.0.0.0-rc1 (#162) Signed-off-by: Saurabh Singh Signed-off-by: Zelin Hao --- ...-common-utils.release-notes-2.0.0.0-rc1.md | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 release-notes/opensearch-common-utils.release-notes-2.0.0.0-rc1.md diff --git a/release-notes/opensearch-common-utils.release-notes-2.0.0.0-rc1.md b/release-notes/opensearch-common-utils.release-notes-2.0.0.0-rc1.md new file mode 100644 index 00000000..84418524 --- /dev/null +++ b/release-notes/opensearch-common-utils.release-notes-2.0.0.0-rc1.md @@ -0,0 +1,29 @@ +## Version 2.0.0.0-rc1 2022-04-25 + +Compatible with OpenSearch 2.0.0-rc1 + +### Enhancements + + * Add SQL/PPL transport request/response models for SQL plugin ([#155](https://github.com/opensearch-project/common-utils/pull/155)) + * Support sending email message via Notifications pass-through API ([#158](https://github.com/opensearch-project/common-utils/pull/158)) + +### Infrastructure + + * Upgrade gradle artifacts to 7.3.3 ([#135](https://github.com/opensearch-project/common-utils/pull/135) + * Update common-utils to depend on the OpenSearch repositories plugin ([#137](https://github.com/opensearch-project/common-utils/pull/137)) + * Add sign-off option for version workflow PR ([#143](https://github.com/opensearch-project/common-utils/pull/143)) + * Add qualifier default to alpha1 in build.gradle ([#151](https://github.com/opensearch-project/common-utils/pull/151)) + * Update issue templates from github for bugs and features ([#154](https://github.com/opensearch-project/common-utils/pull/154)) + * Remove support for JDK 14 ([#159](https://github.com/opensearch-project/common-utils/pull/159)) + +### Refactoring + + * Remove feature and feature_list usage for Notifications ([#136](https://github.com/opensearch-project/common-utils/pull/136)) + * Rename references for Get Channels API for Notifications ([#140](https://github.com/opensearch-project/common-utils/pull/140)) + * Remove allowedConfigFeatureList from GetPluginFeaturesResponse for Notifications ([#144](https://github.com/opensearch-project/common-utils/pull/144)) + * Remove NotificationEvent Request, Response and SearchResults ([#153](https://github.com/opensearch-project/common-utils/pull/153)) + * Add NotificationEvent to SendNotificationResponse and Removal of NotificationID ([#156](https://github.com/opensearch-project/common-utils/pull/156)) + +### Documentation + + * Add release notes for version 2.0.0-rc1 ([#162](https://github.com/opensearch-project/common-utils/pull/162)) From bb58b594866a375dde3a731501c0bf68477bc811 Mon Sep 17 00:00:00 2001 From: Aditya Jindal <13850971+aditjind@users.noreply.github.com> Date: Thu, 5 May 2022 19:23:49 -0700 Subject: [PATCH 126/140] Removing RC1 as the qualifier from Common Utils (#168) Signed-off-by: Aditya Jindal Signed-off-by: Zelin Hao --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index b3680fcd..eb2e8bc9 100644 --- a/build.gradle +++ b/build.gradle @@ -6,9 +6,9 @@ buildscript { ext { opensearch_group = "org.opensearch" - opensearch_version = System.getProperty("opensearch.version", "2.0.0-rc1-SNAPSHOT") + opensearch_version = System.getProperty("opensearch.version", "2.0.0-SNAPSHOT") isSnapshot = "true" == System.getProperty("build.snapshot", "true") - buildVersionQualifier = System.getProperty("build.version_qualifier", "rc1") + buildVersionQualifier = System.getProperty("build.version_qualifier", "") kotlin_version = System.getProperty("kotlin.version", "1.6.10") } From da757569086c7d9bd84fc339d9e11d0ec8607709 Mon Sep 17 00:00:00 2001 From: Subhobrata Dey Date: Mon, 9 May 2022 14:44:02 -0700 Subject: [PATCH 127/140] add code coverage badge (#169) Signed-off-by: Subhobrata Dey Signed-off-by: Zelin Hao --- .codecov.yml | 12 ++++++++++++ .github/workflows/ci.yml | 3 +-- 2 files changed, 13 insertions(+), 2 deletions(-) create mode 100644 .codecov.yml diff --git a/.codecov.yml b/.codecov.yml new file mode 100644 index 00000000..e711a04d --- /dev/null +++ b/.codecov.yml @@ -0,0 +1,12 @@ +codecov: + require_ci_to_pass: yes + +coverage: + precision: 2 + round: down + range: "75...100" + status: + project: + default: + target: 75% # the required coverage value + threshold: 1% # the leniency in hitting the target \ No newline at end of file diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5e017740..0bcc5e2c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -38,6 +38,5 @@ jobs: - name: Upload Coverage Report uses: codecov/codecov-action@v1 with: - file: ./build/reports/jacoco/test/jacocoTestReport.xml - flags: plugin + token: ${{ secrets.CODECOV_TOKEN }} From 03d4324ec2f7f7ff68562b0b21a6023471879631 Mon Sep 17 00:00:00 2001 From: Mohammad Qureshi <47198598+qreshi@users.noreply.github.com> Date: Wed, 11 May 2022 16:45:44 -0700 Subject: [PATCH 128/140] Change BaseModel to extend ToXContentObject instead of ToXContent (#173) Signed-off-by: Mohammad Qureshi <47198598+qreshi@users.noreply.github.com> Signed-off-by: Zelin Hao --- .../org/opensearch/commons/notifications/model/BaseModel.kt | 4 ++-- .../commons/notifications/model/NotificationEvent.kt | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/BaseModel.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/BaseModel.kt index 5ead5594..056fcc6e 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/BaseModel.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/BaseModel.kt @@ -5,9 +5,9 @@ package org.opensearch.commons.notifications.model import org.opensearch.common.io.stream.Writeable -import org.opensearch.common.xcontent.ToXContent +import org.opensearch.common.xcontent.ToXContentObject /** * interface for representing objects. */ -interface BaseModel : Writeable, ToXContent +interface BaseModel : Writeable, ToXContentObject diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationEvent.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationEvent.kt index 6bc49d5f..2ab5426b 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationEvent.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationEvent.kt @@ -111,6 +111,7 @@ data class NotificationEvent( return try { XContentHelper.toXContent(this, XContentType.JSON, EMPTY_PARAMS, true).utf8ToString() } catch (e: IOException) { + log.debug("Failed to convert NotificationEvent to string", e) super.toString() + " threw " + e.toString() } } From 8bd0b488377d542bf54838f7cb97911d5e1c029e Mon Sep 17 00:00:00 2001 From: Subhobrata Dey Date: Mon, 16 May 2022 15:57:04 -0700 Subject: [PATCH 129/140] add code coverage badge (#171) Signed-off-by: Zelin Hao --- README.md | 1 + build-tools/opensearchplugin-coverage.gradle | 49 ++++++++++++++++++++ build.gradle | 1 + 3 files changed, 51 insertions(+) create mode 100644 build-tools/opensearchplugin-coverage.gradle diff --git a/README.md b/README.md index fc95f76e..b900ee32 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,5 @@ +[![codecov](https://codecov.io/gh/opensearch-project/common-utils/branch/main/graph/badge.svg?token=CQ01D9MNQL)](https://codecov.io/gh/opensearch-project/common-utils) - [OpenSearch Common Utils](#opensearch-common-utils) - [Contributing](#contributing) diff --git a/build-tools/opensearchplugin-coverage.gradle b/build-tools/opensearchplugin-coverage.gradle new file mode 100644 index 00000000..2b4d21c0 --- /dev/null +++ b/build-tools/opensearchplugin-coverage.gradle @@ -0,0 +1,49 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * OpenSearch Plugin build tools don't work with the Gradle Jacoco Plugin to report coverage out of the box. + * https://github.com/elastic/elasticsearch/issues/28867. + * + * This code sets up coverage reporting manually for OpenSearch plugin tests. This is complicated because: + * 1. The OpenSearch integTest Task doesn't implement Gradle's JavaForkOptions so we have to manually start the jacoco agent with the test JVM + * 2. The cluster nodes are stopped using 'kill -9' which means jacoco can't dump it's execution output to a file on VM shutdown + * 3. The Java Security Manager prevents JMX from writing execution output to the file. + * + * To workaround these we start the cluster with jmx enabled and then use Jacoco's JMX MBean to get the execution data before the + * cluster is stopped and dump it to a file. Luckily our current security policy seems to allow this. This will also probably + * break if there are multiple nodes in the integTestCluster. But for now... it sorta works. + */ +apply plugin: 'jacoco' + +// Get gradle to generate the required jvm agent arg for us using a dummy tasks of type Test. Unfortunately Elastic's +// testing tasks don't derive from Test so the jacoco plugin can't do this automatically. +def jacocoDir = "${buildDir}/jacoco" +task dummyTest(type: Test) { + enabled = false + workingDir = file("/") // Force absolute path to jacoco agent jar + jacoco { + destinationFile = file("${jacocoDir}/test.exec") + destinationFile.parentFile.mkdirs() + jmx = true + } +} + +jacocoTestReport { + dependsOn test + executionData dummyTest.jacoco.destinationFile + getSourceDirectories().from(sourceSets.main.allSource) + getClassDirectories().from(sourceSets.main.output) + reports { + html.enabled = true // human readable + xml.enabled = true // for coverlay + } +} + +project.gradle.projectsEvaluated { + jacocoTestReport.dependsOn test +} + +check.dependsOn jacocoTestReport diff --git a/build.gradle b/build.gradle index eb2e8bc9..67e4bef1 100644 --- a/build.gradle +++ b/build.gradle @@ -63,6 +63,7 @@ apply plugin: 'io.gitlab.arturbosch.detekt' apply plugin: 'org.jetbrains.kotlin.jvm' apply plugin: 'org.jetbrains.kotlin.plugin.allopen' apply plugin: 'opensearch.repositories' +apply from: 'build-tools/opensearchplugin-coverage.gradle' configurations { ktlint From b29a78c9f4ac04a067735f4ec6981aa7162d40fc Mon Sep 17 00:00:00 2001 From: Subhobrata Dey Date: Mon, 16 May 2022 21:46:53 -0700 Subject: [PATCH 130/140] fix code coverage badge (#175) Signed-off-by: Subhobrata Dey Signed-off-by: Zelin Hao --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index b900ee32..47a0b97b 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ -[![codecov](https://codecov.io/gh/opensearch-project/common-utils/branch/main/graph/badge.svg?token=CQ01D9MNQL)](https://codecov.io/gh/opensearch-project/common-utils) + + + - [OpenSearch Common Utils](#opensearch-common-utils) - [Contributing](#contributing) From 185d840ae7f5864baed5eceffe2e4f6ed0c0e84e Mon Sep 17 00:00:00 2001 From: Subhobrata Dey Date: Tue, 17 May 2022 11:02:52 -0700 Subject: [PATCH 131/140] fix code coverage badge (#176) Signed-off-by: Subhobrata Dey Signed-off-by: Zelin Hao --- README.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 47a0b97b..98ee4ce2 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,6 @@ +[![codecov](https://codecov.io/gh/opensearch-project/common-utils/branch/main/graph/badge.svg)](https://codecov.io/gh/opensearch-project/common-utils) + - - - - [OpenSearch Common Utils](#opensearch-common-utils) - [Contributing](#contributing) From 571ee4a0230af5c5476efc9b4bf87cf46791d311 Mon Sep 17 00:00:00 2001 From: Saurabh Singh Date: Wed, 18 May 2022 12:34:37 -0700 Subject: [PATCH 132/140] Add release notes for version 2.0.0.0 (#177) Signed-off-by: Saurabh Singh Signed-off-by: Zelin Hao --- ...arch-common-utils.release-notes-2.0.0.0.md | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 release-notes/opensearch-common-utils.release-notes-2.0.0.0.md diff --git a/release-notes/opensearch-common-utils.release-notes-2.0.0.0.md b/release-notes/opensearch-common-utils.release-notes-2.0.0.0.md new file mode 100644 index 00000000..70295ccc --- /dev/null +++ b/release-notes/opensearch-common-utils.release-notes-2.0.0.0.md @@ -0,0 +1,32 @@ +## Version 2.0.0.0 2022-05-18 + +Compatible with OpenSearch 2.0.0 + +### Enhancements + + * Add SQL/PPL transport request/response models for SQL plugin ([#155](https://github.com/opensearch-project/common-utils/pull/155)) + * Support sending email message via Notifications pass-through API ([#158](https://github.com/opensearch-project/common-utils/pull/158)) + +### Infrastructure + + * Upgrade gradle artifacts to 7.3.3 ([#135](https://github.com/opensearch-project/common-utils/pull/135) + * Update common-utils to depend on the OpenSearch repositories plugin ([#137](https://github.com/opensearch-project/common-utils/pull/137)) + * Add sign-off option for version workflow PR ([#143](https://github.com/opensearch-project/common-utils/pull/143)) + * Add qualifier default to alpha1 in build.gradle ([#151](https://github.com/opensearch-project/common-utils/pull/151)) + * Update issue templates from github for bugs and features ([#154](https://github.com/opensearch-project/common-utils/pull/154)) + * Remove support for JDK 14 ([#159](https://github.com/opensearch-project/common-utils/pull/159)) + * Remove RC1 as the qualifier from Common Utils ([#168](https://github.com/opensearch-project/common-utils/pull/168)) + +### Refactoring + + * Remove feature and feature_list usage for Notifications ([#136](https://github.com/opensearch-project/common-utils/pull/136)) + * Rename references for Get Channels API for Notifications ([#140](https://github.com/opensearch-project/common-utils/pull/140)) + * Remove allowedConfigFeatureList from GetPluginFeaturesResponse for Notifications ([#144](https://github.com/opensearch-project/common-utils/pull/144)) + * Remove NotificationEvent Request, Response and SearchResults ([#153](https://github.com/opensearch-project/common-utils/pull/153)) + * Add NotificationEvent to SendNotificationResponse and Removal of NotificationID ([#156](https://github.com/opensearch-project/common-utils/pull/156)) + * Change BaseModel to extend ToXContentObject instead of ToXContent ([#173](https://github.com/opensearch-project/common-utils/pull/173)) + +### Documentation + + * Add release notes for version 2.0.0-rc1 ([#162](https://github.com/opensearch-project/common-utils/pull/162)) + * Add release notes for version 2.0.0.0 ([#177](https://github.com/opensearch-project/common-utils/pull/177)) From fe79cb329a936b2394006d2e3b883caddcd92892 Mon Sep 17 00:00:00 2001 From: "Daniel Doubrovkine (dB.)" Date: Tue, 24 May 2022 14:02:00 -0400 Subject: [PATCH 133/140] Remove duplicate DCO workflow. (#181) Signed-off-by: dblock Signed-off-by: Zelin Hao --- .github/workflows/dco.yml | 18 ------------------ 1 file changed, 18 deletions(-) delete mode 100644 .github/workflows/dco.yml diff --git a/.github/workflows/dco.yml b/.github/workflows/dco.yml deleted file mode 100644 index 53ed5304..00000000 --- a/.github/workflows/dco.yml +++ /dev/null @@ -1,18 +0,0 @@ -name: Developer Certificate of Origin Check - -on: [pull_request] - -jobs: - check: - runs-on: ubuntu-latest - - steps: - - name: Get PR Commits - id: 'get-pr-commits' - uses: tim-actions/get-pr-commits@v1.1.0 - with: - token: ${{ secrets.GITHUB_TOKEN }} - - name: DCO Check - uses: tim-actions/dco@v1.1.0 - with: - commits: ${{ steps.get-pr-commits.outputs.commits }} \ No newline at end of file From a6b0eb586b7563dba691885deaa2a6af9f9736d3 Mon Sep 17 00:00:00 2001 From: Ankit Kala Date: Thu, 23 Jun 2022 00:08:18 +0530 Subject: [PATCH 134/140] Bump up the version to 2.1 (#190) Signed-off-by: Ankit Kala Signed-off-by: Zelin Hao --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 67e4bef1..280a92e7 100644 --- a/build.gradle +++ b/build.gradle @@ -6,7 +6,7 @@ buildscript { ext { opensearch_group = "org.opensearch" - opensearch_version = System.getProperty("opensearch.version", "2.0.0-SNAPSHOT") + opensearch_version = System.getProperty("opensearch.version", "2.1.0-SNAPSHOT") isSnapshot = "true" == System.getProperty("build.snapshot", "true") buildVersionQualifier = System.getProperty("build.version_qualifier", "") kotlin_version = System.getProperty("kotlin.version", "1.6.10") From e02f7126b1dd449c3b0b77174cf441cfd2718fdf Mon Sep 17 00:00:00 2001 From: Subhobrata Dey Date: Wed, 22 Jun 2022 14:19:40 -0700 Subject: [PATCH 135/140] Upgrade gradle to 7.4.2 (#191) Signed-off-by: Zelin Hao --- gradle/wrapper/gradle-wrapper.jar | Bin 59536 -> 59821 bytes gradle/wrapper/gradle-wrapper.properties | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 7454180f2ae8848c63b8b4dea2cb829da983f2fa..41d9927a4d4fb3f96a785543079b8df6723c946b 100644 GIT binary patch delta 8958 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 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 2e6e5897..aa991fce 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.2-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists From 8b00c4651ae09a5394749cb0c206628a4d23aa16 Mon Sep 17 00:00:00 2001 From: "opensearch-trigger-bot[bot]" <98922864+opensearch-trigger-bot[bot]@users.noreply.github.com> Date: Wed, 6 Jul 2022 15:28:18 -0700 Subject: [PATCH 136/140] Added 2.1 release notes. (#194) (#196) (cherry picked from commit 739d155a0f6ed03c83e5cb014abaef6432d8ca23) Signed-off-by: Subhobrata Dey Co-authored-by: Subhobrata Dey Signed-off-by: Zelin Hao --- .../opensearch-common-utils.release-notes-2.1.0.0.md | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 release-notes/opensearch-common-utils.release-notes-2.1.0.0.md diff --git a/release-notes/opensearch-common-utils.release-notes-2.1.0.0.md b/release-notes/opensearch-common-utils.release-notes-2.1.0.0.md new file mode 100644 index 00000000..3bf4465f --- /dev/null +++ b/release-notes/opensearch-common-utils.release-notes-2.1.0.0.md @@ -0,0 +1,10 @@ +## Version 2.1.0.0 2022-07-06 + +Compatible with OpenSearch 2.1.0 + +### Maintenance +* Upgrade gradle to 7.4.2. ([#191](https://github.com/opensearch-project/common-utils/pull/191)) +* Bump up the version to 2.1. ([#190](https://github.com/opensearch-project/common-utils/pull/190)) + +### Documentation +* Added 2.1 release notes. ([#194](https://github.com/opensearch-project/common-utils/pull/194)) \ No newline at end of file From ca5393458eb40c6843dc1b555f708a60d9535847 Mon Sep 17 00:00:00 2001 From: Mohammad Qureshi <47198598+qreshi@users.noreply.github.com> Date: Mon, 25 Jul 2022 10:02:57 -0700 Subject: [PATCH 137/140] Bump 2.x branch to 2.2 (#204) Signed-off-by: Mohammad Qureshi <47198598+qreshi@users.noreply.github.com> Signed-off-by: Zelin Hao --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 280a92e7..674ac630 100644 --- a/build.gradle +++ b/build.gradle @@ -6,7 +6,7 @@ buildscript { ext { opensearch_group = "org.opensearch" - opensearch_version = System.getProperty("opensearch.version", "2.1.0-SNAPSHOT") + opensearch_version = System.getProperty("opensearch.version", "2.2.0-SNAPSHOT") isSnapshot = "true" == System.getProperty("build.snapshot", "true") buildVersionQualifier = System.getProperty("build.version_qualifier", "") kotlin_version = System.getProperty("kotlin.version", "1.6.10") From b262edd8d1ac6b44bd2b37b5dc105641e6288163 Mon Sep 17 00:00:00 2001 From: "opensearch-trigger-bot[bot]" <98922864+opensearch-trigger-bot[bot]@users.noreply.github.com> Date: Thu, 4 Aug 2022 14:11:16 -0700 Subject: [PATCH 138/140] Staging for version increment automation (#200) (#211) * Version increment automation Signed-off-by: pgodithi * Version increment automation: task rename updateVersion Signed-off-by: pgodithi (cherry picked from commit 366bf16496f43474a45c47b99bb4f91edc4109fb) Signed-off-by: prudhvigodithi Co-authored-by: Prudhvi Godithi Signed-off-by: Zelin Hao --- build.gradle | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/build.gradle b/build.gradle index 674ac630..7849fd91 100644 --- a/build.gradle +++ b/build.gradle @@ -199,3 +199,15 @@ publishing { gradle.startParameter.setShowStacktrace(ShowStacktrace.ALWAYS) gradle.startParameter.setLogLevel(LogLevel.DEBUG) } + +// updateVersion: Task to auto increment to the next development iteration +task updateVersion { + onlyIf { System.getProperty('newVersion') } + doLast { + ext.newVersion = System.getProperty('newVersion') + println "Setting version to ${newVersion}." + // String tokenization to support -SNAPSHOT + // Include the required files that needs to be updated with new Version + ant.replaceregexp(file:'build.gradle', match: '"opensearch.version", "\\d.*"', replace: '"opensearch.version", "' + newVersion.tokenize('-')[0] + '-SNAPSHOT"', flags:'g', byline:true) + } +} \ No newline at end of file From 4076e153c19b5dc44b5788ae184f95199457f8b2 Mon Sep 17 00:00:00 2001 From: Saurabh Singh Date: Tue, 9 Aug 2022 11:43:58 -0700 Subject: [PATCH 139/140] Added 2.2 release notes. (#216) Signed-off-by: Saurabh Singh Signed-off-by: Zelin Hao --- .../opensearch-common-utils.release-notes-2.2.0.0.md | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 release-notes/opensearch-common-utils.release-notes-2.2.0.0.md diff --git a/release-notes/opensearch-common-utils.release-notes-2.2.0.0.md b/release-notes/opensearch-common-utils.release-notes-2.2.0.0.md new file mode 100644 index 00000000..b77f7244 --- /dev/null +++ b/release-notes/opensearch-common-utils.release-notes-2.2.0.0.md @@ -0,0 +1,10 @@ +## Version 2.2.0.0 2022-08-09 + +Compatible with OpenSearch 2.2.0 + +### Infrastructure +* Execute version auto increment in staging ([#200](https://github.com/opensearch-project/common-utils/pull/200)) +* Bump up the version to 2.2. ([#204](https://github.com/opensearch-project/common-utils/pull/204)) + +### Documentation +* Added 2.2 release notes. ([#212](https://github.com/opensearch-project/common-utils/pull/212)) \ No newline at end of file From 7299233b91565c5ca44b8589c04e31020aaa8d23 Mon Sep 17 00:00:00 2001 From: opensearch-ci-bot Date: Thu, 11 Aug 2022 20:43:24 +0000 Subject: [PATCH 140/140] Incremented version to 2.2.1 Signed-off-by: GitHub Signed-off-by: Zelin Hao --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 7849fd91..53b5b260 100644 --- a/build.gradle +++ b/build.gradle @@ -6,7 +6,7 @@ buildscript { ext { opensearch_group = "org.opensearch" - opensearch_version = System.getProperty("opensearch.version", "2.2.0-SNAPSHOT") + opensearch_version = System.getProperty("opensearch.version", "2.2.1-SNAPSHOT") isSnapshot = "true" == System.getProperty("build.snapshot", "true") buildVersionQualifier = System.getProperty("build.version_qualifier", "") kotlin_version = System.getProperty("kotlin.version", "1.6.10")