Skip to content

Commit 45d053b

Browse files
adityaj1107zhongnansudai-chenjoshuali925
authored
Merge changes in the main branch to the 1.x branch. (#42)
* 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 <aditjind@amazon.com> * add method type in CustomWebhook data model (#39) Signed-off-by: Zhongnan Su <szhongna@amazon.com> * Fix class loader issue for notifications response (#40) * Fix class loader issue for notifications Signed-off-by: Joshua Li <joshuali925@gmail.com> * Fix formatting Signed-off-by: Joshua Li <joshuali925@gmail.com> * Refactor creation of action listener object Signed-off-by: Joshua Li <joshuali925@gmail.com> * Fix indentation Signed-off-by: Joshua Li <joshuali925@gmail.com> * Remove unused suppresses Signed-off-by: Joshua Li <joshuali925@gmail.com> * Add UT for notification API Signed-off-by: Chen Dai <daichen@amazon.com> * Add UT for notification API Signed-off-by: Chen Dai <daichen@amazon.com> * Add UT for send notification API Signed-off-by: Chen Dai <daichen@amazon.com> * Fix Github workflow failure Signed-off-by: Chen Dai <daichen@amazon.com> * Fix Github workflow failure Signed-off-by: Chen Dai <daichen@amazon.com> * Refactor UT code Signed-off-by: Chen Dai <daichen@amazon.com> Co-authored-by: Joshua Li <joshuali925@gmail.com> Co-authored-by: Zhongnan Su <szhongna@amazon.com> Co-authored-by: Chen Dai <46505291+dai-chen@users.noreply.github.com> Co-authored-by: Joshua Li <joshuali925@gmail.com>
1 parent d05a50e commit 45d053b

File tree

7 files changed

+391
-14
lines changed

7 files changed

+391
-14
lines changed
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
## Version 1.0.0.0 2021-07-01
2+
3+
Compatible with OpenSearch 1.0.0
4+
5+
### Enhancements
6+
7+
* Notification plugin interface and models ([#31](https://github.com/opensearch-project/common-utils/pull/31))
8+
9+
### Infrastructure
10+
11+
* Support for kotlin and JUnit5 with mockito ([#29](https://github.com/opensearch-project/common-utils/pull/29))
12+
* Removing Kotlin Runtime library bundled into library ([#30](https://github.com/opensearch-project/common-utils/pull/30))
13+
* Bump to version 1.0.0.0 #34 ([#34](https://github.com/opensearch-project/common-utils/pull/34))
14+
15+
### Documentation
16+
17+
* Update OpenSearch branch to 1.0 ([#28](https://github.com/opensearch-project/common-utils/pull/28))
18+
* Cleanup READMEs. ([#32](https://github.com/opensearch-project/common-utils/pull/32))
19+
20+
### Maintainence
21+
22+
* Update issue template with multiple labels ([#18](https://github.com/opensearch-project/common-utils/pull/18))
23+
* Rename namespaces from OpenDistro to OpenSearch ([#20](https://github.com/opensearch-project/common-utils/pull/20))
24+
* Rename classes, variables, methods to incorporate OpenSearch ([#21](https://github.com/opensearch-project/common-utils/pull/21))
25+
* Rename remaining identifiers to OpenSearch ([#23](https://github.com/opensearch-project/common-utils/pull/23))
26+
* Version changed to rc1 #24 ([#24](https://github.com/opensearch-project/common-utils/pull/24))
27+
* Rename consts as per changes in security plugin ([#25](https://github.com/opensearch-project/common-utils/pull/25))
28+
* Move workflow tags to rc1 ([#26](https://github.com/opensearch-project/common-utils/pull/26))
29+
* Add rc1 release notes ([#27](https://github.com/opensearch-project/common-utils/pull/27))

src/main/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterface.kt

Lines changed: 35 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,11 @@
2727
package org.opensearch.commons.notifications
2828

2929
import org.opensearch.action.ActionListener
30+
import org.opensearch.action.ActionResponse
3031
import org.opensearch.client.node.NodeClient
32+
import org.opensearch.common.io.stream.Writeable
3133
import org.opensearch.commons.ConfigConstants.OPENSEARCH_SECURITY_USER_INFO_THREAD_CONTEXT
34+
import org.opensearch.commons.notifications.action.BaseResponse
3235
import org.opensearch.commons.notifications.action.CreateNotificationConfigRequest
3336
import org.opensearch.commons.notifications.action.CreateNotificationConfigResponse
3437
import org.opensearch.commons.notifications.action.DeleteNotificationConfigRequest
@@ -56,6 +59,7 @@ import org.opensearch.commons.notifications.action.UpdateNotificationConfigRespo
5659
import org.opensearch.commons.notifications.model.ChannelMessage
5760
import org.opensearch.commons.notifications.model.EventSource
5861
import org.opensearch.commons.utils.SecureClientWrapper
62+
import org.opensearch.commons.utils.recreateObject
5963

6064
/**
6165
* All the transport action plugin interfaces for the Notification plugin
@@ -76,7 +80,7 @@ object NotificationsPluginInterface {
7680
client.execute(
7781
CREATE_NOTIFICATION_CONFIG_ACTION_TYPE,
7882
request,
79-
listener
83+
wrapActionListener(listener) { response -> recreateObject(response) { CreateNotificationConfigResponse(it) } }
8084
)
8185
}
8286

@@ -94,7 +98,7 @@ object NotificationsPluginInterface {
9498
client.execute(
9599
UPDATE_NOTIFICATION_CONFIG_ACTION_TYPE,
96100
request,
97-
listener
101+
wrapActionListener(listener) { response -> recreateObject(response) { UpdateNotificationConfigResponse(it) } }
98102
)
99103
}
100104

@@ -112,7 +116,7 @@ object NotificationsPluginInterface {
112116
client.execute(
113117
DELETE_NOTIFICATION_CONFIG_ACTION_TYPE,
114118
request,
115-
listener
119+
wrapActionListener(listener) { response -> recreateObject(response) { DeleteNotificationConfigResponse(it) } }
116120
)
117121
}
118122

@@ -130,7 +134,7 @@ object NotificationsPluginInterface {
130134
client.execute(
131135
GET_NOTIFICATION_CONFIG_ACTION_TYPE,
132136
request,
133-
listener
137+
wrapActionListener(listener) { response -> recreateObject(response) { GetNotificationConfigResponse(it) } }
134138
)
135139
}
136140

@@ -148,7 +152,7 @@ object NotificationsPluginInterface {
148152
client.execute(
149153
GET_NOTIFICATION_EVENT_ACTION_TYPE,
150154
request,
151-
listener
155+
wrapActionListener(listener) { response -> recreateObject(response) { GetNotificationEventResponse(it) } }
152156
)
153157
}
154158

@@ -166,7 +170,7 @@ object NotificationsPluginInterface {
166170
client.execute(
167171
GET_PLUGIN_FEATURES_ACTION_TYPE,
168172
request,
169-
listener
173+
wrapActionListener(listener) { response -> recreateObject(response) { GetPluginFeaturesResponse(it) } }
170174
)
171175
}
172176

@@ -184,7 +188,7 @@ object NotificationsPluginInterface {
184188
client.execute(
185189
GET_FEATURE_CHANNEL_LIST_ACTION_TYPE,
186190
request,
187-
listener
191+
wrapActionListener(listener) { response -> recreateObject(response) { GetFeatureChannelListResponse(it) } }
188192
)
189193
}
190194

@@ -209,7 +213,30 @@ object NotificationsPluginInterface {
209213
wrapper.execute(
210214
SEND_NOTIFICATION_ACTION_TYPE,
211215
SendNotificationRequest(eventSource, channelMessage, channelIds, threadContext),
212-
listener
216+
wrapActionListener(listener) { response -> recreateObject(response) { SendNotificationResponse(it) } }
213217
)
214218
}
219+
220+
/**
221+
* Wrap action listener on concrete response class by a new created one on ActionResponse.
222+
* This is required because the response may be loaded by different classloader across plugins.
223+
* The onResponse(ActionResponse) avoids type cast exception and give a chance to recreate
224+
* the response object.
225+
*/
226+
@Suppress("UNCHECKED_CAST")
227+
private fun <Response : BaseResponse> wrapActionListener(
228+
listener: ActionListener<Response>,
229+
recreate: (Writeable) -> Response
230+
): ActionListener<Response> {
231+
return object : ActionListener<ActionResponse> {
232+
override fun onResponse(response: ActionResponse) {
233+
val recreated = response as? Response ?: recreate(response)
234+
listener.onResponse(recreated)
235+
}
236+
237+
override fun onFailure(exception: java.lang.Exception) {
238+
listener.onFailure(exception)
239+
}
240+
} as ActionListener<Response>
241+
}
215242
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package org.opensearch.commons.notifications.model
2+
3+
import org.opensearch.commons.utils.EnumParser
4+
5+
enum class HttpMethodType(val tag: String) {
6+
POST("POST") {
7+
override fun toString(): String {
8+
return tag
9+
}
10+
},
11+
PUT("PUT") {
12+
override fun toString(): String {
13+
return tag
14+
}
15+
},
16+
PATCH("PATCH") {
17+
override fun toString(): String {
18+
return tag
19+
}
20+
};
21+
22+
companion object {
23+
private val tagMap = values().associateBy { it.tag }
24+
25+
val enumParser = EnumParser { fromTagOrDefault(it) }
26+
27+
/**
28+
* Get HttpMethodType from tag or POST if not found
29+
* @param tag the tag
30+
* @return MethodType corresponding to tag. POST if invalid tag.
31+
*/
32+
fun fromTagOrDefault(tag: String): HttpMethodType {
33+
return tagMap[tag] ?: POST
34+
}
35+
}
36+
}

src/main/kotlin/org/opensearch/commons/notifications/model/Webhook.kt

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ import org.opensearch.common.xcontent.XContentBuilder
3535
import org.opensearch.common.xcontent.XContentParser
3636
import org.opensearch.common.xcontent.XContentParserUtils
3737
import org.opensearch.commons.notifications.NotificationConstants.HEADER_PARAMS_TAG
38+
import org.opensearch.commons.notifications.NotificationConstants.METHOD_TAG
3839
import org.opensearch.commons.notifications.NotificationConstants.URL_TAG
3940
import org.opensearch.commons.utils.STRING_READER
4041
import org.opensearch.commons.utils.STRING_WRITER
@@ -47,7 +48,8 @@ import java.io.IOException
4748
*/
4849
data class Webhook(
4950
val url: String,
50-
val headerParams: Map<String, String> = mapOf()
51+
val headerParams: Map<String, String> = mapOf(),
52+
val method: HttpMethodType = HttpMethodType.POST
5153
) : BaseConfigData {
5254

5355
init {
@@ -77,6 +79,7 @@ data class Webhook(
7779
fun parse(parser: XContentParser): Webhook {
7880
var url: String? = null
7981
var headerParams: Map<String, String> = mapOf()
82+
var method = HttpMethodType.POST
8083

8184
XContentParserUtils.ensureExpectedToken(
8285
XContentParser.Token.START_OBJECT,
@@ -89,14 +92,15 @@ data class Webhook(
8992
when (fieldName) {
9093
URL_TAG -> url = parser.text()
9194
HEADER_PARAMS_TAG -> headerParams = parser.mapStrings()
95+
METHOD_TAG -> method = HttpMethodType.fromTagOrDefault(parser.text())
9296
else -> {
9397
parser.skipChildren()
9498
log.info("Unexpected field: $fieldName, while parsing Webhook destination")
9599
}
96100
}
97101
}
98102
url ?: throw IllegalArgumentException("$URL_TAG field absent")
99-
return Webhook(url, headerParams)
103+
return Webhook(url, headerParams, method)
100104
}
101105
}
102106

@@ -108,6 +112,7 @@ data class Webhook(
108112
return builder.startObject()
109113
.field(URL_TAG, url)
110114
.field(HEADER_PARAMS_TAG, headerParams)
115+
.field(METHOD_TAG, method.tag)
111116
.endObject()
112117
}
113118

@@ -117,7 +122,8 @@ data class Webhook(
117122
*/
118123
constructor(input: StreamInput) : this(
119124
url = input.readString(),
120-
headerParams = input.readMap(STRING_READER, STRING_READER)
125+
headerParams = input.readMap(STRING_READER, STRING_READER),
126+
method = input.readEnum(HttpMethodType::class.java)
121127
)
122128

123129
/**
@@ -126,5 +132,6 @@ data class Webhook(
126132
override fun writeTo(output: StreamOutput) {
127133
output.writeString(url)
128134
output.writeMap(headerParams, STRING_WRITER, STRING_WRITER)
135+
output.writeEnum(method)
129136
}
130137
}

0 commit comments

Comments
 (0)