From ee95d07a90f0190e1b55e2bb6ef8d906dc998f87 Mon Sep 17 00:00:00 2001
From: ruanwenjun <861923274@qq.com>
Date: Fri, 30 Apr 2021 10:11:32 +0800
Subject: [PATCH] [Feature][Alert plugin] Support slack alert (#5382) (#5384)
* [Feature][Alert plugin] Support slack alert (#5382)
* fix code smell
* add markdown table
---
.../dolphinscheduler-alert-slack/pom.xml | 84 ++++++++++
.../plugin/alert/slack/SlackAlertChannel.java | 43 +++++
.../alert/slack/SlackAlertChannelFactory.java | 66 ++++++++
.../plugin/alert/slack/SlackAlertPlugin.java | 34 ++++
.../alert/slack/SlackParamsConstants.java | 34 ++++
.../plugin/alert/slack/SlackSender.java | 149 ++++++++++++++++++
.../slack/SlackAlertChannelFactoryTest.java | 48 ++++++
.../alert/slack/SlackAlertPluginTest.java | 36 +++++
.../plugin/alert/slack/SlackSenderTest.java | 39 +++++
dolphinscheduler-alert-plugin/pom.xml | 2 +-
pom.xml | 6 +-
11 files changed, 538 insertions(+), 3 deletions(-)
create mode 100644 dolphinscheduler-alert-plugin/dolphinscheduler-alert-slack/pom.xml
create mode 100644 dolphinscheduler-alert-plugin/dolphinscheduler-alert-slack/src/main/java/org/apache/dolphinscheduler/plugin/alert/slack/SlackAlertChannel.java
create mode 100644 dolphinscheduler-alert-plugin/dolphinscheduler-alert-slack/src/main/java/org/apache/dolphinscheduler/plugin/alert/slack/SlackAlertChannelFactory.java
create mode 100644 dolphinscheduler-alert-plugin/dolphinscheduler-alert-slack/src/main/java/org/apache/dolphinscheduler/plugin/alert/slack/SlackAlertPlugin.java
create mode 100644 dolphinscheduler-alert-plugin/dolphinscheduler-alert-slack/src/main/java/org/apache/dolphinscheduler/plugin/alert/slack/SlackParamsConstants.java
create mode 100644 dolphinscheduler-alert-plugin/dolphinscheduler-alert-slack/src/main/java/org/apache/dolphinscheduler/plugin/alert/slack/SlackSender.java
create mode 100644 dolphinscheduler-alert-plugin/dolphinscheduler-alert-slack/src/test/java/org/apache/dolphinscheduler/plugin/alert/slack/SlackAlertChannelFactoryTest.java
create mode 100644 dolphinscheduler-alert-plugin/dolphinscheduler-alert-slack/src/test/java/org/apache/dolphinscheduler/plugin/alert/slack/SlackAlertPluginTest.java
create mode 100644 dolphinscheduler-alert-plugin/dolphinscheduler-alert-slack/src/test/java/org/apache/dolphinscheduler/plugin/alert/slack/SlackSenderTest.java
diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-slack/pom.xml b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-slack/pom.xml
new file mode 100644
index 0000000000..9b7452a099
--- /dev/null
+++ b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-slack/pom.xml
@@ -0,0 +1,84 @@
+
+
+
+
+ dolphinscheduler-alert-plugin
+ org.apache.dolphinscheduler
+ ${revision}
+
+ 4.0.0
+
+ org.apache.dolphinscheduler
+ dolphinscheduler-alert-slack
+ dolphinscheduler-plugin
+
+
+
+
+ org.apache.dolphinscheduler
+ dolphinscheduler-spi
+ provided
+
+
+
+ org.apache.httpcomponents
+ httpclient
+
+
+
+ com.google.guava
+ guava
+
+
+
+ ch.qos.logback
+ logback-classic
+
+
+
+ org.slf4j
+ slf4j-api
+
+
+
+ com.fasterxml.jackson.core
+ jackson-annotations
+ provided
+
+
+
+ junit
+ junit
+ test
+
+
+
+ org.mockito
+ mockito-core
+ jar
+ test
+
+
+
+
+ dolphinscheduler-alert-slack-${project.version}
+
+
+
\ No newline at end of file
diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-slack/src/main/java/org/apache/dolphinscheduler/plugin/alert/slack/SlackAlertChannel.java b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-slack/src/main/java/org/apache/dolphinscheduler/plugin/alert/slack/SlackAlertChannel.java
new file mode 100644
index 0000000000..6399d8bca9
--- /dev/null
+++ b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-slack/src/main/java/org/apache/dolphinscheduler/plugin/alert/slack/SlackAlertChannel.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dolphinscheduler.plugin.alert.slack;
+
+import org.apache.dolphinscheduler.spi.alert.AlertChannel;
+import org.apache.dolphinscheduler.spi.alert.AlertData;
+import org.apache.dolphinscheduler.spi.alert.AlertInfo;
+import org.apache.dolphinscheduler.spi.alert.AlertResult;
+
+import java.util.Map;
+
+/**
+ * SlackAlertChannel
+ */
+public class SlackAlertChannel implements AlertChannel {
+
+ @Override
+ public AlertResult process(AlertInfo alertInfo) {
+ AlertData alertData = alertInfo.getAlertData();
+ Map alertParams = alertInfo.getAlertParams();
+ if (alertParams == null || alertParams.size() == 0) {
+ return new AlertResult("false", "Slack alert params is empty");
+ }
+ SlackSender slackSender = new SlackSender(alertParams);
+ String response = slackSender.sendMessage(alertData.getTitle(), alertData.getContent());
+ return new AlertResult("ok".equals(response) ? "true" : "false", response);
+ }
+}
diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-slack/src/main/java/org/apache/dolphinscheduler/plugin/alert/slack/SlackAlertChannelFactory.java b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-slack/src/main/java/org/apache/dolphinscheduler/plugin/alert/slack/SlackAlertChannelFactory.java
new file mode 100644
index 0000000000..f3f135ebec
--- /dev/null
+++ b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-slack/src/main/java/org/apache/dolphinscheduler/plugin/alert/slack/SlackAlertChannelFactory.java
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dolphinscheduler.plugin.alert.slack;
+
+import org.apache.dolphinscheduler.spi.alert.AlertChannel;
+import org.apache.dolphinscheduler.spi.alert.AlertChannelFactory;
+import org.apache.dolphinscheduler.spi.params.InputParam;
+import org.apache.dolphinscheduler.spi.params.base.PluginParams;
+import org.apache.dolphinscheduler.spi.params.base.Validate;
+
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * Slack alert factory, see {@link AlertChannelFactory}
+ */
+public class SlackAlertChannelFactory implements AlertChannelFactory {
+
+ @Override
+ public String getName() {
+ return "Slack";
+ }
+
+ @Override
+ public List getParams() {
+ List paramsList = new LinkedList<>();
+
+ InputParam webHookParam = InputParam.newBuilder(SlackParamsConstants.SLACK_WEN_HOOK_URL_NAME, SlackParamsConstants.SLACK_WEB_HOOK_URL)
+ .addValidate(Validate.newBuilder()
+ .setRequired(true)
+ .build())
+ .setPlaceholder("Input WebHook Url")
+ .build();
+
+ InputParam botName = InputParam.newBuilder(SlackParamsConstants.SLACK_BOT_NAME, SlackParamsConstants.SLACK_BOT)
+ .addValidate(Validate.newBuilder()
+ .setRequired(true)
+ .build())
+ .setPlaceholder("Input the bot username")
+ .build();
+
+ paramsList.add(webHookParam);
+ paramsList.add(botName);
+ return paramsList;
+ }
+
+ @Override
+ public AlertChannel create() {
+ return new SlackAlertChannel();
+ }
+}
diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-slack/src/main/java/org/apache/dolphinscheduler/plugin/alert/slack/SlackAlertPlugin.java b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-slack/src/main/java/org/apache/dolphinscheduler/plugin/alert/slack/SlackAlertPlugin.java
new file mode 100644
index 0000000000..59c45ae4ac
--- /dev/null
+++ b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-slack/src/main/java/org/apache/dolphinscheduler/plugin/alert/slack/SlackAlertPlugin.java
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dolphinscheduler.plugin.alert.slack;
+
+import org.apache.dolphinscheduler.spi.DolphinSchedulerPlugin;
+import org.apache.dolphinscheduler.spi.alert.AlertChannelFactory;
+
+import com.google.common.collect.ImmutableList;
+
+/**
+ * Slack alert plugin
+ */
+public class SlackAlertPlugin implements DolphinSchedulerPlugin {
+
+ @Override
+ public Iterable getAlertChannelFactorys() {
+ return ImmutableList.of(new SlackAlertChannelFactory());
+ }
+}
diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-slack/src/main/java/org/apache/dolphinscheduler/plugin/alert/slack/SlackParamsConstants.java b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-slack/src/main/java/org/apache/dolphinscheduler/plugin/alert/slack/SlackParamsConstants.java
new file mode 100644
index 0000000000..fd191c5d55
--- /dev/null
+++ b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-slack/src/main/java/org/apache/dolphinscheduler/plugin/alert/slack/SlackParamsConstants.java
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dolphinscheduler.plugin.alert.slack;
+
+public class SlackParamsConstants {
+
+ private SlackParamsConstants() {
+
+ }
+
+ public static final String SLACK_WEB_HOOK_URL = "WebHook";
+ public static final String SLACK_WEN_HOOK_URL_NAME = "webHook";
+ public static final String SLACK_BOT = "Username";
+ public static final String SLACK_BOT_NAME = "username";
+ public static final String TEXT = "text";
+ public static final String ATTACHMENT = "attachments";
+
+ public static final Integer MAX_SHOW_NUMBER = 100;
+}
diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-slack/src/main/java/org/apache/dolphinscheduler/plugin/alert/slack/SlackSender.java b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-slack/src/main/java/org/apache/dolphinscheduler/plugin/alert/slack/SlackSender.java
new file mode 100644
index 0000000000..21a8286211
--- /dev/null
+++ b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-slack/src/main/java/org/apache/dolphinscheduler/plugin/alert/slack/SlackSender.java
@@ -0,0 +1,149 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dolphinscheduler.plugin.alert.slack;
+
+import org.apache.dolphinscheduler.spi.utils.JSONUtils;
+import org.apache.dolphinscheduler.spi.utils.StringUtils;
+
+import org.apache.http.HttpEntity;
+import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.entity.StringEntity;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClients;
+import org.apache.http.util.EntityUtils;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Objects;
+import java.util.stream.Collectors;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Preconditions;
+
+public class SlackSender {
+
+ private static final Logger logger = LoggerFactory.getLogger(SlackSender.class);
+
+ private String webHookUrl;
+
+ private String botName;
+
+ public SlackSender(Map slackAlertParam) {
+ webHookUrl = slackAlertParam.get(SlackParamsConstants.SLACK_WEN_HOOK_URL_NAME);
+ botName = slackAlertParam.get(SlackParamsConstants.SLACK_BOT_NAME);
+ Preconditions.checkArgument(!Objects.isNull(webHookUrl), "SlackWebHookURL can not be null");
+ Preconditions.checkArgument(webHookUrl.startsWith("https://hooks.slack.com/services/"), "SlackWebHookURL invalidate");
+ Preconditions.checkArgument(!Objects.isNull(botName), "slack bot name can not be null");
+ }
+
+ /**
+ * Send message to slack channel
+ *
+ * @param title title
+ * @param content content
+ * @return slack response
+ */
+ public String sendMessage(String title, String content) {
+ try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
+ Map paramMap = new HashMap<>();
+ paramMap.put(SlackParamsConstants.SLACK_BOT_NAME, botName);
+ paramMap.put(SlackParamsConstants.TEXT, title);
+ if (StringUtils.isNotEmpty(content)) {
+ Map attachmentTable = new HashMap<>();
+ attachmentTable.put(SlackParamsConstants.TEXT, generateMarkDownTable(content));
+ List