From ff9165ab5cee9318d229060f8db413841a43328f Mon Sep 17 00:00:00 2001 From: Drew Baugher <46505179+dbbaughe@users.noreply.github.com> Date: Tue, 3 Aug 2021 11:08:28 -0700 Subject: [PATCH 1/9] 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> --- .../message/LegacyBaseMessage.java | 127 +++++++ .../message/LegacyChimeMessage.java | 99 ++++++ .../message/LegacyCustomWebhookMessage.java | 313 ++++++++++++++++++ .../message/LegacyDestinationType.java | 36 ++ .../message/LegacySlackMessage.java | 107 ++++++ .../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 | 186 +++++++++++ .../message/LegacySlackMessageTest.java | 110 ++++++ .../LegacyDestinationResponseTest.java | 82 +++++ .../NotificationsPluginInterfaceTests.kt | 24 ++ .../LegacyPublishNotificationRequestTests.kt | 42 +++ .../LegacyPublishNotificationResponseTests.kt | 29 ++ 18 files changed, 1583 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..cc8eab02 --- /dev/null +++ b/src/main/java/org/opensearch/commons/destination/message/LegacyBaseMessage.java @@ -0,0 +1,127 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file 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.StreamOutput; +import org.opensearch.common.io.stream.Writeable; + +/** + * This class holds the generic parameters required for a + * message. + */ +public abstract class LegacyBaseMessage implements Writeable { + + protected LegacyDestinationType destinationType; + protected String destinationName; + protected String url; + private 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(org.opensearch.common.io.stream.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..4b223574 --- /dev/null +++ b/src/main/java/org/opensearch/commons/destination/message/LegacyChimeMessage.java @@ -0,0 +1,99 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file 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 LegacyDestinationType destinationType, + final String destinationName, + final String url, + final String message + ) { + + super(destinationType, destinationName, message, url); + + if (LegacyDestinationType.CHIME != destinationType) { + throw new IllegalArgumentException("Channel Type does not match CHIME"); + } + + 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: " + destinationType + ", DestinationName:" + destinationName + ", Url: " + url + ", Message: " + message; + } + + public static class Builder { + private String message; + private final LegacyDestinationType destinationType; + private final String destinationName; + private String url; + + public Builder(String destinationName) { + this.destinationName = destinationName; + this.destinationType = LegacyDestinationType.CHIME; + } + + 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.destinationType, this.destinationName, this.url, this.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..df0fb962 --- /dev/null +++ b/src/main/java/org/opensearch/commons/destination/message/LegacyCustomWebhookMessage.java @@ -0,0 +1,313 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file 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 Map queryParams; + private Map headerParams; + private final String userName; + private final String password; + + private LegacyCustomWebhookMessage( + final LegacyDestinationType destinationType, + 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 userName, + final String password, + final String message + ) { + + super(destinationType, destinationName, message); + + if (LegacyDestinationType.CUSTOMWEBHOOK != destinationType) { + throw new IllegalArgumentException("Channel Type does not match CustomWebhook"); + } + + 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; + this.userName = userName; + this.password = password; + } + + public LegacyCustomWebhookMessage(StreamInput streamInput) throws IOException { + super(streamInput); + this.message = super.getMessageContent(); + this.url = streamInput.readOptionalString(); + this.scheme = streamInput.readOptionalString(); + this.host = streamInput.readOptionalString(); + this.method = streamInput.readOptionalString(); + this.port = streamInput.readOptionalInt(); + this.path = streamInput.readOptionalString(); + if (streamInput.readBoolean()) { + @SuppressWarnings("unchecked") + Map queryParams = (Map) (Map) streamInput.readMap(); + this.queryParams = queryParams; + } + if (streamInput.readBoolean()) { + @SuppressWarnings("unchecked") + Map headerParams = (Map) (Map) streamInput.readMap(); + this.headerParams = headerParams; + } + this.userName = streamInput.readOptionalString(); + this.password = streamInput.readOptionalString(); + } + + @Override + public String toString() { + return "DestinationType: " + + destinationType + + ", DestinationName:" + + destinationName + + ", Url: " + + url + + ", scheme: " + + scheme + + ", Host: " + + host + + ", Port: " + + port + + ", Path: " + + path + + ", Method: " + + method + + ", Message: " + + message; + } + + public static class Builder { + private String message; + private final LegacyDestinationType destinationType; + 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; + private String userName; + private String password; + + public Builder(String destinationName) { + this.destinationName = destinationName; + this.destinationType = LegacyDestinationType.CUSTOMWEBHOOK; + } + + 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.Builder withUserName(String userName) { + this.userName = userName; + return this; + } + + public LegacyCustomWebhookMessage.Builder withPassword(String password) { + this.password = password; + return this; + } + + public LegacyCustomWebhookMessage build() { + return new LegacyCustomWebhookMessage( + this.destinationType, + this.destinationName, + this.url, + this.scheme, + this.host, + this.port, + this.path, + this.method, + this.queryParams, + this.headerParams, + this.userName, + this.password, + 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()); + } + + @Override + public void writeTo(StreamOutput streamOutput) throws IOException { + super.writeTo(streamOutput); + streamOutput.writeOptionalString(url); + streamOutput.writeOptionalString(scheme); + streamOutput.writeOptionalString(host); + streamOutput.writeOptionalString(method); + streamOutput.writeOptionalInt(port); + streamOutput.writeOptionalString(path); + streamOutput.writeBoolean(queryParams != null); + if (queryParams != null) { + @SuppressWarnings("unchecked") + Map queryParams = (Map) (Map) this.queryParams; + streamOutput.writeMap(queryParams); + } + streamOutput.writeBoolean(headerParams != null); + if (headerParams != null) { + @SuppressWarnings("unchecked") + Map headerParams = (Map) (Map) this.headerParams; + streamOutput.writeMap(headerParams); + } + streamOutput.writeOptionalString(userName); + streamOutput.writeOptionalString(password); + } +} 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..4c2c556f --- /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 { + CHIME, + SLACK, + CUSTOMWEBHOOK +} 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..9fc1d164 --- /dev/null +++ b/src/main/java/org/opensearch/commons/destination/message/LegacySlackMessage.java @@ -0,0 +1,107 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file 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 String message; + + private LegacySlackMessage( + final LegacyDestinationType destinationType, + final String destinationName, + final String url, + final String message + ) { + + super(destinationType, destinationName, message, url); + + if (LegacyDestinationType.SLACK != destinationType) { + throw new IllegalArgumentException("Channel Type does not match Slack"); + } + + 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: " + destinationType + ", DestinationName:" + destinationName + ", Url: " + url + ", Message: " + message; + } + + public static class Builder { + private String message; + private LegacyDestinationType destinationType; + private String destinationName; + private String url; + + public Builder(String channelName) { + this.destinationName = channelName; + this.destinationType = LegacyDestinationType.SLACK; + } + + 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.destinationType, 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..bffac475 --- /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.CHIME -> LegacyChimeMessage(input) + LegacyDestinationType.CUSTOMWEBHOOK -> LegacyCustomWebhookMessage(input) + LegacyDestinationType.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..637fa249 --- /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 { + return builder + } +} 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..8a228749 --- /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.CHIME, message.destinationType); + 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.destinationType, message.destinationType); + 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..e850eada --- /dev/null +++ b/src/test/java/org/opensearch/commons/destination/message/LegacyCustomWebhookMessageTest.java @@ -0,0 +1,186 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file 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.CUSTOMWEBHOOK, message.destinationType); + 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.destinationType, message.destinationType); + assertEquals(newMessage.getMessageContent(), message.getMessageContent()); + assertEquals(newMessage.getUrl(), message.getUrl()); + } + + @Test + public void testRoundTrippingLegacyCustomWebhookMessageWithHost() 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(); + message.writeTo(out); + + StreamInput in = StreamInput.wrap(out.bytes().toBytesRef().bytes); + LegacyCustomWebhookMessage newMessage = new LegacyCustomWebhookMessage(in); + + assertEquals(newMessage.destinationName, message.destinationName); + assertEquals(newMessage.destinationType, message.destinationType); + assertEquals(newMessage.getMessageContent(), message.getMessageContent()); + assertEquals(newMessage.getHost(), message.getHost()); + assertEquals(newMessage.getMethod(), message.getMethod()); + assertEquals(newMessage.getPath(), message.getPath()); + assertEquals(newMessage.getQueryParams(), message.getQueryParams()); + assertEquals(newMessage.getHeaderParams(), message.getHeaderParams()); + assertEquals(newMessage.getPort(), message.getPort()); + assertEquals(newMessage.getScheme(), message.getScheme()); + } + + @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..3c29108d --- /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.SLACK, message.destinationType); + 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.destinationType, message.destinationType); + 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 b77a4dc5c8dc83522519b426c842073e5a9b2c31 Mon Sep 17 00:00:00 2001 From: Drew Baugher <46505179+dbbaughe@users.noreply.github.com> Date: Wed, 11 Aug 2021 09:30:58 -0700 Subject: [PATCH 2/9] Fixes import and removes username/password that is not used by ISM Signed-off-by: Drew Baugher <46505179+dbbaughe@users.noreply.github.com> --- .../message/LegacyBaseMessage.java | 3 ++- .../message/LegacyCustomWebhookMessage.java | 24 ------------------- 2 files changed, 2 insertions(+), 25 deletions(-) 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 cc8eab02..366f12d9 100644 --- a/src/main/java/org/opensearch/commons/destination/message/LegacyBaseMessage.java +++ b/src/main/java/org/opensearch/commons/destination/message/LegacyBaseMessage.java @@ -33,6 +33,7 @@ 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; @@ -67,7 +68,7 @@ public abstract class LegacyBaseMessage implements Writeable { this.url = url; } - LegacyBaseMessage(org.opensearch.common.io.stream.StreamInput streamInput) throws IOException { + LegacyBaseMessage(StreamInput streamInput) throws IOException { this.destinationType = streamInput.readEnum(LegacyDestinationType.class); this.destinationName = streamInput.readString(); this.url = streamInput.readOptionalString(); 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 df0fb962..197a5fe6 100644 --- a/src/main/java/org/opensearch/commons/destination/message/LegacyCustomWebhookMessage.java +++ b/src/main/java/org/opensearch/commons/destination/message/LegacyCustomWebhookMessage.java @@ -51,8 +51,6 @@ public class LegacyCustomWebhookMessage extends LegacyBaseMessage { private String path; private Map queryParams; private Map headerParams; - private final String userName; - private final String password; private LegacyCustomWebhookMessage( final LegacyDestinationType destinationType, @@ -65,8 +63,6 @@ private LegacyCustomWebhookMessage( final String method, final Map queryParams, final Map headerParams, - final String userName, - final String password, final String message ) { @@ -111,8 +107,6 @@ private LegacyCustomWebhookMessage( this.host = host; this.queryParams = queryParams; this.headerParams = headerParams; - this.userName = userName; - this.password = password; } public LegacyCustomWebhookMessage(StreamInput streamInput) throws IOException { @@ -134,8 +128,6 @@ public LegacyCustomWebhookMessage(StreamInput streamInput) throws IOException { Map headerParams = (Map) (Map) streamInput.readMap(); this.headerParams = headerParams; } - this.userName = streamInput.readOptionalString(); - this.password = streamInput.readOptionalString(); } @Override @@ -172,8 +164,6 @@ public static class Builder { private String method; private Map queryParams; private Map headerParams; - private String userName; - private String password; public Builder(String destinationName) { this.destinationName = destinationName; @@ -225,16 +215,6 @@ public LegacyCustomWebhookMessage.Builder withUrl(String url) { return this; } - public LegacyCustomWebhookMessage.Builder withUserName(String userName) { - this.userName = userName; - return this; - } - - public LegacyCustomWebhookMessage.Builder withPassword(String password) { - this.password = password; - return this; - } - public LegacyCustomWebhookMessage build() { return new LegacyCustomWebhookMessage( this.destinationType, @@ -247,8 +227,6 @@ public LegacyCustomWebhookMessage build() { this.method, this.queryParams, this.headerParams, - this.userName, - this.password, this.message ); } @@ -307,7 +285,5 @@ public void writeTo(StreamOutput streamOutput) throws IOException { Map headerParams = (Map) (Map) this.headerParams; streamOutput.writeMap(headerParams); } - streamOutput.writeOptionalString(userName); - streamOutput.writeOptionalString(password); } } From 6f083e6e9b105f862f882f4919cc6f9b6d7f7011 Mon Sep 17 00:00:00 2001 From: Drew Baugher <46505179+dbbaughe@users.noreply.github.com> Date: Thu, 12 Aug 2021 15:28:54 -0700 Subject: [PATCH 3/9] Throws error for toXContent for legacy notification response Signed-off-by: Drew Baugher <46505179+dbbaughe@users.noreply.github.com> --- .../notifications/action/LegacyPublishNotificationResponse.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 637fa249..60f68e71 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/action/LegacyPublishNotificationResponse.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/action/LegacyPublishNotificationResponse.kt @@ -58,6 +58,6 @@ class LegacyPublishNotificationResponse : BaseResponse { // This class is only used across transport wire and does not need to implement toXContent override fun toXContent(builder: XContentBuilder, params: ToXContent.Params): XContentBuilder { - return builder + throw IllegalStateException("Legacy notification response is not intended for REST or persistence and does not support XContent.") } } From e9626677af86db4e238a4772b67b6f6a2ba4a0b7 Mon Sep 17 00:00:00 2001 From: Drew Baugher <46505179+dbbaughe@users.noreply.github.com> Date: Thu, 12 Aug 2021 15:31:29 -0700 Subject: [PATCH 4/9] Renames legacy destination types to have legacy prefix Signed-off-by: Drew Baugher <46505179+dbbaughe@users.noreply.github.com> --- .../commons/destination/message/LegacyChimeMessage.java | 4 ++-- .../destination/message/LegacyCustomWebhookMessage.java | 4 ++-- .../commons/destination/message/LegacyDestinationType.java | 6 +++--- .../commons/destination/message/LegacySlackMessage.java | 4 ++-- .../action/LegacyPublishNotificationRequest.kt | 6 +++--- .../commons/destination/message/LegacyChimeMessageTest.java | 2 +- .../destination/message/LegacyCustomWebhookMessageTest.java | 2 +- .../commons/destination/message/LegacySlackMessageTest.java | 2 +- 8 files changed, 15 insertions(+), 15 deletions(-) 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 4b223574..99df9a66 100644 --- a/src/main/java/org/opensearch/commons/destination/message/LegacyChimeMessage.java +++ b/src/main/java/org/opensearch/commons/destination/message/LegacyChimeMessage.java @@ -46,7 +46,7 @@ private LegacyChimeMessage( super(destinationType, destinationName, message, url); - if (LegacyDestinationType.CHIME != destinationType) { + if (LegacyDestinationType.LEGACY_CHIME != destinationType) { throw new IllegalArgumentException("Channel Type does not match CHIME"); } @@ -75,7 +75,7 @@ public static class Builder { public Builder(String destinationName) { this.destinationName = destinationName; - this.destinationType = LegacyDestinationType.CHIME; + this.destinationType = LegacyDestinationType.LEGACY_CHIME; } public LegacyChimeMessage.Builder withMessage(String 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 197a5fe6..bd678c45 100644 --- a/src/main/java/org/opensearch/commons/destination/message/LegacyCustomWebhookMessage.java +++ b/src/main/java/org/opensearch/commons/destination/message/LegacyCustomWebhookMessage.java @@ -68,7 +68,7 @@ private LegacyCustomWebhookMessage( super(destinationType, destinationName, message); - if (LegacyDestinationType.CUSTOMWEBHOOK != destinationType) { + if (LegacyDestinationType.LEGACY_CUSTOM_WEBHOOK != destinationType) { throw new IllegalArgumentException("Channel Type does not match CustomWebhook"); } @@ -167,7 +167,7 @@ public static class Builder { public Builder(String destinationName) { this.destinationName = destinationName; - this.destinationType = LegacyDestinationType.CUSTOMWEBHOOK; + this.destinationType = LegacyDestinationType.LEGACY_CUSTOM_WEBHOOK; } public LegacyCustomWebhookMessage.Builder withScheme(String scheme) { 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 4c2c556f..85689510 100644 --- a/src/main/java/org/opensearch/commons/destination/message/LegacyDestinationType.java +++ b/src/main/java/org/opensearch/commons/destination/message/LegacyDestinationType.java @@ -30,7 +30,7 @@ * Supported legacy notification destinations for Index Management */ public enum LegacyDestinationType { - CHIME, - SLACK, - CUSTOMWEBHOOK + 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 index 9fc1d164..c0b3852e 100644 --- a/src/main/java/org/opensearch/commons/destination/message/LegacySlackMessage.java +++ b/src/main/java/org/opensearch/commons/destination/message/LegacySlackMessage.java @@ -46,7 +46,7 @@ private LegacySlackMessage( super(destinationType, destinationName, message, url); - if (LegacyDestinationType.SLACK != destinationType) { + if (LegacyDestinationType.LEGACY_SLACK != destinationType) { throw new IllegalArgumentException("Channel Type does not match Slack"); } @@ -79,7 +79,7 @@ public static class Builder { public Builder(String channelName) { this.destinationName = channelName; - this.destinationType = LegacyDestinationType.SLACK; + this.destinationType = LegacyDestinationType.LEGACY_SLACK; } public LegacySlackMessage.Builder withMessage(String message) { 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 bffac475..e5807102 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/action/LegacyPublishNotificationRequest.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/action/LegacyPublishNotificationRequest.kt @@ -57,9 +57,9 @@ class LegacyPublishNotificationRequest : ActionRequest { @Throws(IOException::class) constructor(input: StreamInput) : super(input) { baseMessage = when (requireNotNull(input.readEnum(LegacyDestinationType::class.java)) { "Destination type cannot be null" }) { - LegacyDestinationType.CHIME -> LegacyChimeMessage(input) - LegacyDestinationType.CUSTOMWEBHOOK -> LegacyCustomWebhookMessage(input) - LegacyDestinationType.SLACK -> LegacySlackMessage(input) + LegacyDestinationType.LEGACY_CHIME -> LegacyChimeMessage(input) + LegacyDestinationType.LEGACY_CUSTOM_WEBHOOK -> LegacyCustomWebhookMessage(input) + LegacyDestinationType.LEGACY_SLACK -> LegacySlackMessage(input) } feature = input.readString() } 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 8a228749..84b16fb0 100644 --- a/src/test/java/org/opensearch/commons/destination/message/LegacyChimeMessageTest.java +++ b/src/test/java/org/opensearch/commons/destination/message/LegacyChimeMessageTest.java @@ -45,7 +45,7 @@ public void testBuildingLegacyChimeMessage() { .build(); assertEquals("custom_webhook", message.destinationName); - assertEquals(LegacyDestinationType.CHIME, message.destinationType); + assertEquals(LegacyDestinationType.LEGACY_CHIME, message.destinationType); assertEquals("Hello world", message.getMessageContent()); assertEquals("https://amazon.com", message.url); } 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 e850eada..3710bf55 100644 --- a/src/test/java/org/opensearch/commons/destination/message/LegacyCustomWebhookMessageTest.java +++ b/src/test/java/org/opensearch/commons/destination/message/LegacyCustomWebhookMessageTest.java @@ -49,7 +49,7 @@ public void testBuildingLegacyCustomWebhookMessage() { .build(); assertEquals("custom_webhook", message.destinationName); - assertEquals(LegacyDestinationType.CUSTOMWEBHOOK, message.destinationType); + assertEquals(LegacyDestinationType.LEGACY_CUSTOM_WEBHOOK, message.destinationType); assertEquals("Hello world", message.getMessageContent()); assertEquals("https://amazon.com", message.getUrl()); } 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 3c29108d..7745186d 100644 --- a/src/test/java/org/opensearch/commons/destination/message/LegacySlackMessageTest.java +++ b/src/test/java/org/opensearch/commons/destination/message/LegacySlackMessageTest.java @@ -45,7 +45,7 @@ public void testBuildingLegacySlackMessage() { .build(); assertEquals("custom_webhook", message.destinationName); - assertEquals(LegacyDestinationType.SLACK, message.destinationType); + assertEquals(LegacyDestinationType.LEGACY_SLACK, message.destinationType); assertEquals("Hello world", message.getMessageContent()); assertEquals("https://amazon.com", message.url); } From d839f89019b88b26273e49a7807a62ee274e6dca Mon Sep 17 00:00:00 2001 From: Drew Baugher <46505179+dbbaughe@users.noreply.github.com> Date: Thu, 12 Aug 2021 15:36:43 -0700 Subject: [PATCH 5/9] Obfuscates message to remove from logs in toString method Signed-off-by: Drew Baugher <46505179+dbbaughe@users.noreply.github.com> --- .../commons/destination/message/LegacyChimeMessage.java | 2 +- .../destination/message/LegacyCustomWebhookMessage.java | 3 +-- .../commons/destination/message/LegacySlackMessage.java | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) 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 99df9a66..153ca0c7 100644 --- a/src/main/java/org/opensearch/commons/destination/message/LegacyChimeMessage.java +++ b/src/main/java/org/opensearch/commons/destination/message/LegacyChimeMessage.java @@ -64,7 +64,7 @@ public LegacyChimeMessage(StreamInput streamInput) throws IOException { @Override public String toString() { - return "DestinationType: " + destinationType + ", DestinationName:" + destinationName + ", Url: " + url + ", Message: " + message; + return "DestinationType: " + destinationType + ", DestinationName:" + destinationName + ", Url: " + url + ", Message: <...>"; } public static class Builder { 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 bd678c45..3df398d9 100644 --- a/src/main/java/org/opensearch/commons/destination/message/LegacyCustomWebhookMessage.java +++ b/src/main/java/org/opensearch/commons/destination/message/LegacyCustomWebhookMessage.java @@ -148,8 +148,7 @@ public String toString() { + path + ", Method: " + method - + ", Message: " - + message; + + ", Message: <...>"; } public static class Builder { 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 c0b3852e..a17c3472 100644 --- a/src/main/java/org/opensearch/commons/destination/message/LegacySlackMessage.java +++ b/src/main/java/org/opensearch/commons/destination/message/LegacySlackMessage.java @@ -68,7 +68,7 @@ public LegacySlackMessage(StreamInput streamInput) throws IOException { @Override public String toString() { - return "DestinationType: " + destinationType + ", DestinationName:" + destinationName + ", Url: " + url + ", Message: " + message; + return "DestinationType: " + destinationType + ", DestinationName:" + destinationName + ", Url: " + url + ", Message: <...>"; } public static class Builder { From d5a38f587a4b397278fc76d1bc586290508908d2 Mon Sep 17 00:00:00 2001 From: Drew Baugher <46505179+dbbaughe@users.noreply.github.com> Date: Thu, 12 Aug 2021 15:41:25 -0700 Subject: [PATCH 6/9] Makes destinationt type private and updates places to use getter Signed-off-by: Drew Baugher <46505179+dbbaughe@users.noreply.github.com> --- .../commons/destination/message/LegacyBaseMessage.java | 2 +- .../commons/destination/message/LegacyChimeMessage.java | 2 +- .../destination/message/LegacyCustomWebhookMessage.java | 2 +- .../commons/destination/message/LegacySlackMessage.java | 2 +- .../commons/destination/message/LegacyChimeMessageTest.java | 4 ++-- .../destination/message/LegacyCustomWebhookMessageTest.java | 6 +++--- .../commons/destination/message/LegacySlackMessageTest.java | 4 ++-- 7 files changed, 11 insertions(+), 11 deletions(-) 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 366f12d9..b91416e3 100644 --- a/src/main/java/org/opensearch/commons/destination/message/LegacyBaseMessage.java +++ b/src/main/java/org/opensearch/commons/destination/message/LegacyBaseMessage.java @@ -43,7 +43,7 @@ */ public abstract class LegacyBaseMessage implements Writeable { - protected LegacyDestinationType destinationType; + private final LegacyDestinationType destinationType; protected String destinationName; protected String url; private String 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 index 153ca0c7..c2ac6bde 100644 --- a/src/main/java/org/opensearch/commons/destination/message/LegacyChimeMessage.java +++ b/src/main/java/org/opensearch/commons/destination/message/LegacyChimeMessage.java @@ -64,7 +64,7 @@ public LegacyChimeMessage(StreamInput streamInput) throws IOException { @Override public String toString() { - return "DestinationType: " + destinationType + ", DestinationName:" + destinationName + ", Url: " + url + ", Message: <...>"; + return "DestinationType: " + getChannelType() + ", DestinationName:" + destinationName + ", Url: " + url + ", Message: <...>"; } public static class Builder { 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 3df398d9..58491e33 100644 --- a/src/main/java/org/opensearch/commons/destination/message/LegacyCustomWebhookMessage.java +++ b/src/main/java/org/opensearch/commons/destination/message/LegacyCustomWebhookMessage.java @@ -133,7 +133,7 @@ public LegacyCustomWebhookMessage(StreamInput streamInput) throws IOException { @Override public String toString() { return "DestinationType: " - + destinationType + + getChannelType() + ", DestinationName:" + destinationName + ", Url: " 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 a17c3472..ff0737f7 100644 --- a/src/main/java/org/opensearch/commons/destination/message/LegacySlackMessage.java +++ b/src/main/java/org/opensearch/commons/destination/message/LegacySlackMessage.java @@ -68,7 +68,7 @@ public LegacySlackMessage(StreamInput streamInput) throws IOException { @Override public String toString() { - return "DestinationType: " + destinationType + ", DestinationName:" + destinationName + ", Url: " + url + ", Message: <...>"; + return "DestinationType: " + getChannelType() + ", DestinationName:" + destinationName + ", Url: " + url + ", Message: <...>"; } public static class Builder { 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 84b16fb0..4477789e 100644 --- a/src/test/java/org/opensearch/commons/destination/message/LegacyChimeMessageTest.java +++ b/src/test/java/org/opensearch/commons/destination/message/LegacyChimeMessageTest.java @@ -45,7 +45,7 @@ public void testBuildingLegacyChimeMessage() { .build(); assertEquals("custom_webhook", message.destinationName); - assertEquals(LegacyDestinationType.LEGACY_CHIME, message.destinationType); + assertEquals(LegacyDestinationType.LEGACY_CHIME, message.getChannelType()); assertEquals("Hello world", message.getMessageContent()); assertEquals("https://amazon.com", message.url); } @@ -63,7 +63,7 @@ public void testRoundTrippingLegacyChimeMessage() throws IOException { LegacyChimeMessage newMessage = new LegacyChimeMessage(in); assertEquals(newMessage.destinationName, message.destinationName); - assertEquals(newMessage.destinationType, message.destinationType); + assertEquals(newMessage.getChannelType(), message.getChannelType()); assertEquals(newMessage.getMessageContent(), message.getMessageContent()); assertEquals(newMessage.url, message.url); } 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 3710bf55..7d0cce0f 100644 --- a/src/test/java/org/opensearch/commons/destination/message/LegacyCustomWebhookMessageTest.java +++ b/src/test/java/org/opensearch/commons/destination/message/LegacyCustomWebhookMessageTest.java @@ -49,7 +49,7 @@ public void testBuildingLegacyCustomWebhookMessage() { .build(); assertEquals("custom_webhook", message.destinationName); - assertEquals(LegacyDestinationType.LEGACY_CUSTOM_WEBHOOK, message.destinationType); + assertEquals(LegacyDestinationType.LEGACY_CUSTOM_WEBHOOK, message.getChannelType()); assertEquals("Hello world", message.getMessageContent()); assertEquals("https://amazon.com", message.getUrl()); } @@ -67,7 +67,7 @@ public void testRoundTrippingLegacyCustomWebhookMessageWithUrl() throws IOExcept LegacyCustomWebhookMessage newMessage = new LegacyCustomWebhookMessage(in); assertEquals(newMessage.destinationName, message.destinationName); - assertEquals(newMessage.destinationType, message.destinationType); + assertEquals(newMessage.getChannelType(), message.getChannelType()); assertEquals(newMessage.getMessageContent(), message.getMessageContent()); assertEquals(newMessage.getUrl(), message.getUrl()); } @@ -95,7 +95,7 @@ public void testRoundTrippingLegacyCustomWebhookMessageWithHost() throws IOExcep LegacyCustomWebhookMessage newMessage = new LegacyCustomWebhookMessage(in); assertEquals(newMessage.destinationName, message.destinationName); - assertEquals(newMessage.destinationType, message.destinationType); + assertEquals(newMessage.getChannelType(), message.getChannelType()); assertEquals(newMessage.getMessageContent(), message.getMessageContent()); assertEquals(newMessage.getHost(), message.getHost()); assertEquals(newMessage.getMethod(), message.getMethod()); 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 7745186d..a520fc8e 100644 --- a/src/test/java/org/opensearch/commons/destination/message/LegacySlackMessageTest.java +++ b/src/test/java/org/opensearch/commons/destination/message/LegacySlackMessageTest.java @@ -45,7 +45,7 @@ public void testBuildingLegacySlackMessage() { .build(); assertEquals("custom_webhook", message.destinationName); - assertEquals(LegacyDestinationType.LEGACY_SLACK, message.destinationType); + assertEquals(LegacyDestinationType.LEGACY_SLACK, message.getChannelType()); assertEquals("Hello world", message.getMessageContent()); assertEquals("https://amazon.com", message.url); } @@ -63,7 +63,7 @@ public void testRoundTrippingLegacySlackMessage() throws IOException { LegacySlackMessage newMessage = new LegacySlackMessage(in); assertEquals(newMessage.destinationName, message.destinationName); - assertEquals(newMessage.destinationType, message.destinationType); + assertEquals(newMessage.getChannelType(), message.getChannelType()); assertEquals(newMessage.getMessageContent(), message.getMessageContent()); assertEquals(newMessage.url, message.url); } From 0b8488a3f88108709de36e8e35578417544c22dc Mon Sep 17 00:00:00 2001 From: Drew Baugher <46505179+dbbaughe@users.noreply.github.com> Date: Thu, 12 Aug 2021 15:49:14 -0700 Subject: [PATCH 7/9] Inlines destination type Signed-off-by: Drew Baugher <46505179+dbbaughe@users.noreply.github.com> --- .../message/LegacyChimeMessage.java | 22 ++++++------------- .../message/LegacyCustomWebhookMessage.java | 15 +++++-------- .../message/LegacySlackMessage.java | 20 ++++------------- 3 files changed, 16 insertions(+), 41 deletions(-) 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 c2ac6bde..b457d9aa 100644 --- a/src/main/java/org/opensearch/commons/destination/message/LegacyChimeMessage.java +++ b/src/main/java/org/opensearch/commons/destination/message/LegacyChimeMessage.java @@ -37,18 +37,8 @@ public class LegacyChimeMessage extends LegacyBaseMessage { private final String message; - private LegacyChimeMessage( - final LegacyDestinationType destinationType, - final String destinationName, - final String url, - final String message - ) { - - super(destinationType, destinationName, message, url); - - if (LegacyDestinationType.LEGACY_CHIME != destinationType) { - throw new IllegalArgumentException("Channel Type does not match CHIME"); - } + 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"); @@ -69,13 +59,11 @@ public String toString() { public static class Builder { private String message; - private final LegacyDestinationType destinationType; private final String destinationName; private String url; public Builder(String destinationName) { this.destinationName = destinationName; - this.destinationType = LegacyDestinationType.LEGACY_CHIME; } public LegacyChimeMessage.Builder withMessage(String message) { @@ -89,10 +77,14 @@ public LegacyChimeMessage.Builder withUrl(String url) { } public LegacyChimeMessage build() { - return new LegacyChimeMessage(this.destinationType, this.destinationName, this.url, this.message); + 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 index 58491e33..df34cce2 100644 --- a/src/main/java/org/opensearch/commons/destination/message/LegacyCustomWebhookMessage.java +++ b/src/main/java/org/opensearch/commons/destination/message/LegacyCustomWebhookMessage.java @@ -53,7 +53,6 @@ public class LegacyCustomWebhookMessage extends LegacyBaseMessage { private Map headerParams; private LegacyCustomWebhookMessage( - final LegacyDestinationType destinationType, final String destinationName, final String url, final String scheme, @@ -65,12 +64,7 @@ private LegacyCustomWebhookMessage( final Map headerParams, final String message ) { - - super(destinationType, destinationName, message); - - if (LegacyDestinationType.LEGACY_CUSTOM_WEBHOOK != destinationType) { - throw new IllegalArgumentException("Channel Type does not match CustomWebhook"); - } + super(LegacyDestinationType.LEGACY_CUSTOM_WEBHOOK, destinationName, message); if (!Strings.isNullOrEmpty(url)) { setUrl(url.trim()); @@ -153,7 +147,6 @@ public String toString() { public static class Builder { private String message; - private final LegacyDestinationType destinationType; private final String destinationName; private String url; private String scheme; @@ -166,7 +159,6 @@ public static class Builder { public Builder(String destinationName) { this.destinationName = destinationName; - this.destinationType = LegacyDestinationType.LEGACY_CUSTOM_WEBHOOK; } public LegacyCustomWebhookMessage.Builder withScheme(String scheme) { @@ -216,7 +208,6 @@ public LegacyCustomWebhookMessage.Builder withUrl(String url) { public LegacyCustomWebhookMessage build() { return new LegacyCustomWebhookMessage( - this.destinationType, this.destinationName, this.url, this.scheme, @@ -263,6 +254,10 @@ 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); 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 ff0737f7..f426894a 100644 --- a/src/main/java/org/opensearch/commons/destination/message/LegacySlackMessage.java +++ b/src/main/java/org/opensearch/commons/destination/message/LegacySlackMessage.java @@ -35,20 +35,10 @@ * This class holds the content of an Slack message */ public class LegacySlackMessage extends LegacyBaseMessage { - private String message; + private final String message; - private LegacySlackMessage( - final LegacyDestinationType destinationType, - final String destinationName, - final String url, - final String message - ) { - - super(destinationType, destinationName, message, url); - - if (LegacyDestinationType.LEGACY_SLACK != destinationType) { - throw new IllegalArgumentException("Channel Type does not match Slack"); - } + 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); @@ -73,13 +63,11 @@ public String toString() { public static class Builder { private String message; - private LegacyDestinationType destinationType; private String destinationName; private String url; public Builder(String channelName) { this.destinationName = channelName; - this.destinationType = LegacyDestinationType.LEGACY_SLACK; } public LegacySlackMessage.Builder withMessage(String message) { @@ -93,7 +81,7 @@ public LegacySlackMessage.Builder withUrl(String url) { } public LegacySlackMessage build() { - return new LegacySlackMessage(this.destinationType, this.destinationName, this.url, this.message); + return new LegacySlackMessage(this.destinationName, this.url, this.message); } } From 8875a876a7eed358e38bf8456a3c047fa4269ef1 Mon Sep 17 00:00:00 2001 From: Drew Baugher <46505179+dbbaughe@users.noreply.github.com> Date: Thu, 12 Aug 2021 15:51:10 -0700 Subject: [PATCH 8/9] Makes base message content final Signed-off-by: Drew Baugher <46505179+dbbaughe@users.noreply.github.com> --- .../commons/destination/message/LegacyBaseMessage.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 b91416e3..b5122f31 100644 --- a/src/main/java/org/opensearch/commons/destination/message/LegacyBaseMessage.java +++ b/src/main/java/org/opensearch/commons/destination/message/LegacyBaseMessage.java @@ -46,7 +46,7 @@ public abstract class LegacyBaseMessage implements Writeable { private final LegacyDestinationType destinationType; protected String destinationName; protected String url; - private String content; + private final String content; LegacyBaseMessage(final LegacyDestinationType destinationType, final String destinationName, final String content) { if (destinationType == null) { From c530c44364c3122963c54d492c93986ac73a3ffe Mon Sep 17 00:00:00 2001 From: Drew Baugher <46505179+dbbaughe@users.noreply.github.com> Date: Thu, 12 Aug 2021 17:12:09 -0700 Subject: [PATCH 9/9] 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/LegacyCustomWebhookMessage.java | 31 +++++++------------ .../LegacyCustomWebhookMessageTest.java | 23 +++++--------- 2 files changed, 18 insertions(+), 36 deletions(-) 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 df34cce2..9645b327 100644 --- a/src/main/java/org/opensearch/commons/destination/message/LegacyCustomWebhookMessage.java +++ b/src/main/java/org/opensearch/commons/destination/message/LegacyCustomWebhookMessage.java @@ -49,7 +49,7 @@ public class LegacyCustomWebhookMessage extends LegacyBaseMessage { private final String method; private final int port; private String path; - private Map queryParams; + private final Map queryParams; private Map headerParams; private LegacyCustomWebhookMessage( @@ -107,16 +107,12 @@ public LegacyCustomWebhookMessage(StreamInput streamInput) throws IOException { super(streamInput); this.message = super.getMessageContent(); this.url = streamInput.readOptionalString(); - this.scheme = streamInput.readOptionalString(); - this.host = streamInput.readOptionalString(); + this.scheme = null; + this.host = null; this.method = streamInput.readOptionalString(); - this.port = streamInput.readOptionalInt(); - this.path = streamInput.readOptionalString(); - if (streamInput.readBoolean()) { - @SuppressWarnings("unchecked") - Map queryParams = (Map) (Map) streamInput.readMap(); - this.queryParams = queryParams; - } + this.port = -1; + this.path = null; + this.queryParams = null; if (streamInput.readBoolean()) { @SuppressWarnings("unchecked") Map headerParams = (Map) (Map) streamInput.readMap(); @@ -261,18 +257,13 @@ 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. + if (Strings.isNullOrEmpty(getUrl())) { + throw new IllegalStateException("Cannot use LegacyCustomWebhookMessage across transport wire without defining full url."); + } streamOutput.writeOptionalString(url); - streamOutput.writeOptionalString(scheme); - streamOutput.writeOptionalString(host); streamOutput.writeOptionalString(method); - streamOutput.writeOptionalInt(port); - streamOutput.writeOptionalString(path); - streamOutput.writeBoolean(queryParams != null); - if (queryParams != null) { - @SuppressWarnings("unchecked") - Map queryParams = (Map) (Map) this.queryParams; - streamOutput.writeMap(queryParams); - } streamOutput.writeBoolean(headerParams != null); if (headerParams != null) { @SuppressWarnings("unchecked") 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 7d0cce0f..fba614fd 100644 --- a/src/test/java/org/opensearch/commons/destination/message/LegacyCustomWebhookMessageTest.java +++ b/src/test/java/org/opensearch/commons/destination/message/LegacyCustomWebhookMessageTest.java @@ -73,7 +73,7 @@ public void testRoundTrippingLegacyCustomWebhookMessageWithUrl() throws IOExcept } @Test - public void testRoundTrippingLegacyCustomWebhookMessageWithHost() throws IOException { + public void testRoundTrippingLegacyCustomWebhookMessageWithHostFails() throws IOException { Map queryParams = new HashMap(); queryParams.put("token", "sometoken"); Map headers = new HashMap(); @@ -89,21 +89,12 @@ public void testRoundTrippingLegacyCustomWebhookMessageWithHost() throws IOExcep .withScheme("https") .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.getHost(), message.getHost()); - assertEquals(newMessage.getMethod(), message.getMethod()); - assertEquals(newMessage.getPath(), message.getPath()); - assertEquals(newMessage.getQueryParams(), message.getQueryParams()); - assertEquals(newMessage.getHeaderParams(), message.getHeaderParams()); - assertEquals(newMessage.getPort(), message.getPort()); - assertEquals(newMessage.getScheme(), message.getScheme()); + 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