You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@dolphinscheduler.apache.org by ga...@apache.org on 2020/11/02 06:59:27 UTC
[incubator-dolphinscheduler] 09/09: [feature#3356] alert-spi
support DingTalk&WeChat (#3869)
This is an automated email from the ASF dual-hosted git repository.
gaojun2048 pushed a commit to branch alert_plugin_design
in repository https://gitbox.apache.org/repos/asf/incubator-dolphinscheduler.git
commit ce3d7d5b1259f7c43f5e346ed8860a4a1cee3dd0
Author: Kirs <ac...@163.com>
AuthorDate: Mon Nov 2 10:08:28 2020 +0800
[feature#3356] alert-spi support DingTalk&WeChat (#3869)
* [feature-3665][ui]Add element-ui (#3666)
* [feature-3665][ui]Add element-ui
* add license
* Add form-create plug-in and alarm group management add sample demo
* Modify node version
* fix
* fix
* [feature][ui]Alert plugin design (#3734)
* [feature-3665][ui]Add element-ui (#3666)
* [feature-3665][ui]Add element-ui
* add license
* Add form-create plug-in and alarm group management add sample demo
* Modify node version
* fix
* fix
* [Feature-3682][ui]Add form-create plug-in and alarm group management add sample demo (#3683)
* Add form-create plug-in and alarm group management add sample demo
* Modify node version
* fix
* fix
* [feature][ui] Add alarm instance page
* [feature-3665][ui]Add element-ui (#3666)
* [feature-3665][ui]Add element-ui
* add license
* Add form-create plug-in and alarm group management add sample demo
* Modify node version
* fix
* fix
* [Feature-3189][alert,spi,dao,plugin-api] base code of dolphinscheduler spi and alert plugin implement (#3601)
* DS SPI
* Add DolphinScheduler SPI , and rebuilt the code of the Alert plug-in based on SPI
* Add DolphinScheduler SPI , and rebuilt the code of the Alert plug-in based on SPI
* add TODO
* delete
* compile
* spi commit
* Plugin Alert
* fix some bug
* add todo
* change web ui from alpacajs to form-create
* remove module
* add plugin schema
* add license header
* update alert and spi module version
* update the alert plugin sub module version
* comment the maven.local.repository param
* move utils from spi to common module
* add license header
* add license header and delete some chinese comment
* update spi packages
* delete no use alert_xx.properties
* update mysql.connector.version back to 5.1.34
* delete no use comment in pom.xml
* update email stmp password
* add license
* add semicolon to sql/upgrade/1.4.0_schema/mysql/dolphinscheduler_ddl.sql file
* format the code style
* format new clase file with checkstyle
* update plugin params to Builder model
* move JSONUtils to SPI because plugin can not dependency common module
* move JSONUtils to SPI because plugin can not dependency common module
* delete collection dependency
* replace PluginParamsTransfer to spi PluginParamsTransfer
* update dolphinscheduler-maven-plugin to 1.0.0
* update license
* update apache-rat-plugin add exclude '.iml' file
* check license
* ArtifactResolver only use in development and configPlugins is not empty
* ArtifactResolver only use in development and configPlugins is not empty
* ArtifactResolver only use in development and configPlugins is not empty
* default datasource should be postgresql
* add license files
* add license files
* postgresql port should be 5432
* postgresql test
* mv show_type to spi
add license header to AlertConstants
* check style fix
* copy check style file from branch dev
* alert show_type set by plugin
* alert show_type set by plugin
* add PluginDefineMapper to dolphinscheduler-server/src/test/java/org/apache/dolphinscheduler/server/registry/DependencyConfig.java
* add Bean to TaskCallbackServiceTestConfig
* add Bean to TaskCallbackServiceTestConfig
* fix check style
* check style fix
* [feature-3665][ui]Add element-ui (#3666)
* [feature-3665][ui]Add element-ui
* add license
* fix check style
* [Feature-3682][ui]Add form-create plug-in and alarm group management add sample demo (#3683)
* Add form-create plug-in and alarm group management add sample demo
* Modify node version
* fix
* fix
* check style fix
* rollback test change
* rollback test change
* rollback dao pom change
* [feature-3665][ui]Add element-ui (#3666)
* [feature-3665][ui]Add element-ui
* add license
* Add form-create plug-in and alarm group management add sample demo
* Modify node version
* fix
* fix
* add ut to pom.xml
* add upgrade schema to global schema
* fix ut failed
* fix ut failed
* fix ut failed
* fix ut failed
* add test EmailAlertPluginTest to pom.xml
* fix ut failed
* fix ut failed
* fix check style
* update license header to presto license header
* presto license header not check
* fix ut coverage
* fix ut coverage
* fix ut
* fix ut
* fix ut
* fix ut coverage
* fix ut coverage
* fix ut coverage
* fix ut coverage
* fix ut coverage
* fix ut coverage
Co-authored-by: break60 <79...@qq.com>
* [feature#3356] alert-spi support DingTalk
this closes # 3356
* add test
* code style
* we chat alert
* support we chat alert
* support we chat alert
* support we chat alert,update ding talk alert
* code style
* add test
* code style
* clean old code
* clean old code
* code smell
* code style
* add test
* simple config
* code style
* code style
* code style
* delete old file
* fix log content error
Co-authored-by: break60 <79...@qq.com>
Co-authored-by: gaojun2048 <32...@users.noreply.github.com>
---
.../dolphinscheduler-alert-dingtalk/pom.xml | 46 +++
.../alert/dingtalk/DingTalkAlertChannel.java | 41 +++
.../dingtalk/DingTalkAlertChannelFactory.java | 89 ++++++
.../plugin/alert/dingtalk/DingTalkAlertPlugin.java | 34 +++
.../alert/dingtalk/DingTalkParamsConstants.java | 54 ++++
.../plugin/alert/dingtalk/DingTalkSender.java | 204 +++++++++++++
.../dingtalk/DingTalkAlertChannelFactoryTest.java | 48 +++
.../plugin/alert/dingtalk/DingTalkSenderTest.java | 57 ++++
.../dolphinscheduler-alert-wechat/pom.xml | 42 +++
.../plugin/alert/wechat/WeChatAlertChannel.java | 41 +++
.../alert/wechat/WeChatAlertChannelFactory.java | 94 ++++++
.../plugin/alert/wechat/WeChatAlertConstants.java | 34 +++
.../alert/wechat/WeChatAlertParamsConstants.java | 56 ++++
.../plugin/alert/wechat/WeChatAlertPlugin.java | 34 +++
.../plugin/alert/wechat/WeChatSender.java | 328 +++++++++++++++++++++
.../wechat/WeChatAlertChannelFactoryTest.java | 48 +++
.../plugin/alert/wechat/WeChatSenderTest.java | 89 ++++++
.../alert/manager/DingTalkManager.java | 55 ----
.../alert/manager/EnterpriseWeChatManager.java | 63 ----
.../alert/utils/DingTalkUtils.java | 138 ---------
.../alert/utils/EnterpriseWeChatUtils.java | 290 ------------------
.../alert/utils/DingTalkUtilsTest.java | 110 -------
.../alert/utils/EnterpriseWeChatUtilsTest.java | 307 -------------------
dolphinscheduler-spi/pom.xml | 2 +
.../dolphinscheduler/spi/utils/JSONUtils.java | 2 +-
pom.xml | 10 +-
26 files changed, 1349 insertions(+), 967 deletions(-)
diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-dingtalk/pom.xml b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-dingtalk/pom.xml
index 7a42257..8b47172 100644
--- a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-dingtalk/pom.xml
+++ b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-dingtalk/pom.xml
@@ -29,4 +29,50 @@
<artifactId>dolphinscheduler-alert-dingtalk</artifactId>
+ <dependencies>
+
+ <dependency>
+ <groupId>org.apache.dolphinscheduler</groupId>
+ <artifactId>dolphinscheduler-spi</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.httpcomponents</groupId>
+ <artifactId>httpclient</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>ch.qos.logback</groupId>
+ <artifactId>logback-classic</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-annotations</artifactId>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-core</artifactId>
+ <type>jar</type>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
</project>
\ No newline at end of file
diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-dingtalk/src/main/java/org/apache/dolphinscheduler/plugin/alert/dingtalk/DingTalkAlertChannel.java b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-dingtalk/src/main/java/org/apache/dolphinscheduler/plugin/alert/dingtalk/DingTalkAlertChannel.java
new file mode 100644
index 0000000..7adfacc
--- /dev/null
+++ b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-dingtalk/src/main/java/org/apache/dolphinscheduler/plugin/alert/dingtalk/DingTalkAlertChannel.java
@@ -0,0 +1,41 @@
+/*
+ * 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.dingtalk;
+
+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 org.apache.dolphinscheduler.spi.params.PluginParamsTransfer;
+
+import java.util.Map;
+
+/**
+ * DingTalkAlertChannel
+ */
+public class DingTalkAlertChannel implements AlertChannel {
+
+ @Override
+ public AlertResult process(AlertInfo alertInfo) {
+
+ AlertData alertData = alertInfo.getAlertData();
+ String alertParams = alertInfo.getAlertParams();
+ Map<String, String> paramsMap = PluginParamsTransfer.getPluginParamsMap(alertParams);
+ return new DingTalkSender(paramsMap).sendDingTalkMsg(alertData.getTitle(), alertData.getContent());
+ }
+}
diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-dingtalk/src/main/java/org/apache/dolphinscheduler/plugin/alert/dingtalk/DingTalkAlertChannelFactory.java b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-dingtalk/src/main/java/org/apache/dolphinscheduler/plugin/alert/dingtalk/DingTalkAlertChannelFactory.java
new file mode 100644
index 0000000..0126de4
--- /dev/null
+++ b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-dingtalk/src/main/java/org/apache/dolphinscheduler/plugin/alert/dingtalk/DingTalkAlertChannelFactory.java
@@ -0,0 +1,89 @@
+/*
+ * 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.dingtalk;
+
+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.PasswordParam;
+import org.apache.dolphinscheduler.spi.params.RadioParam;
+import org.apache.dolphinscheduler.spi.params.base.ParamsOptions;
+import org.apache.dolphinscheduler.spi.params.base.PluginParams;
+import org.apache.dolphinscheduler.spi.params.base.Validate;
+
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * DingTalkAlertChannelFactory
+ */
+public class DingTalkAlertChannelFactory implements AlertChannelFactory {
+ @Override
+ public String getName() {
+ return "ding talk alert";
+ }
+
+ @Override
+ public List<PluginParams> getParams() {
+ InputParam webHookParam = InputParam.newBuilder(DingTalkParamsConstants.NAME_DING_TALK_WEB_HOOK, DingTalkParamsConstants.DING_TALK_WEB_HOOK)
+ .addValidate(Validate.newBuilder()
+ .setRequired(true)
+ .build())
+ .build();
+ InputParam keywordParam = InputParam.newBuilder(DingTalkParamsConstants.NAME_DING_TALK_KEYWORD, DingTalkParamsConstants.DING_TALK_KEYWORD)
+ .addValidate(Validate.newBuilder()
+ .setRequired(true)
+ .build())
+ .build();
+ RadioParam isEnableProxy =
+ RadioParam.newBuilder(DingTalkParamsConstants.NAME_DING_TALK_PROXY_ENABLE, DingTalkParamsConstants.NAME_DING_TALK_PROXY_ENABLE)
+ .addParamsOptions(new ParamsOptions("YES", true, false))
+ .addParamsOptions(new ParamsOptions("NO", false, false))
+ .setValue(true)
+ .addValidate(Validate.newBuilder()
+ .setRequired(true)
+ .build())
+ .build();
+ InputParam proxyParam =
+ InputParam.newBuilder(DingTalkParamsConstants.NAME_DING_TALK_PROXY, DingTalkParamsConstants.DING_TALK_PROXY)
+ .addValidate(Validate.newBuilder()
+ .setRequired(true).build())
+ .build();
+
+ InputParam portParam = InputParam.newBuilder(DingTalkParamsConstants.NAME_DING_TALK_PORT, DingTalkParamsConstants.DING_TALK_PORT)
+ .addValidate(Validate.newBuilder()
+ .setRequired(true).build())
+ .build();
+
+ InputParam userParam =
+ InputParam.newBuilder(DingTalkParamsConstants.NAME_DING_TALK_USER, DingTalkParamsConstants.DING_TALK_USER)
+ .addValidate(Validate.newBuilder()
+ .setRequired(true).build())
+ .build();
+ PasswordParam passwordParam = PasswordParam.newBuilder(DingTalkParamsConstants.NAME_DING_TALK_PASSWORD, DingTalkParamsConstants.DING_TALK_PASSWORD)
+ .setPlaceholder("if enable use authentication, you need input password")
+ .build();
+
+ return Arrays.asList(webHookParam, keywordParam, isEnableProxy, proxyParam, portParam, userParam, passwordParam);
+ }
+
+ @Override
+ public AlertChannel create() {
+ return new DingTalkAlertChannel();
+ }
+}
diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-dingtalk/src/main/java/org/apache/dolphinscheduler/plugin/alert/dingtalk/DingTalkAlertPlugin.java b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-dingtalk/src/main/java/org/apache/dolphinscheduler/plugin/alert/dingtalk/DingTalkAlertPlugin.java
new file mode 100644
index 0000000..2d15f49
--- /dev/null
+++ b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-dingtalk/src/main/java/org/apache/dolphinscheduler/plugin/alert/dingtalk/DingTalkAlertPlugin.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.dingtalk;
+
+import org.apache.dolphinscheduler.spi.DolphinSchedulerPlugin;
+import org.apache.dolphinscheduler.spi.alert.AlertChannelFactory;
+
+import com.google.common.collect.ImmutableList;
+
+/**
+ * DingTalkAlertPlugin
+ */
+public class DingTalkAlertPlugin implements DolphinSchedulerPlugin {
+
+ @Override
+ public Iterable<AlertChannelFactory> getAlertChannelFactorys() {
+ return ImmutableList.of(new DingTalkAlertChannelFactory());
+ }
+}
diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-dingtalk/src/main/java/org/apache/dolphinscheduler/plugin/alert/dingtalk/DingTalkParamsConstants.java b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-dingtalk/src/main/java/org/apache/dolphinscheduler/plugin/alert/dingtalk/DingTalkParamsConstants.java
new file mode 100644
index 0000000..6608e83
--- /dev/null
+++ b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-dingtalk/src/main/java/org/apache/dolphinscheduler/plugin/alert/dingtalk/DingTalkParamsConstants.java
@@ -0,0 +1,54 @@
+/*
+ * 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.dingtalk;
+
+/**
+ * DingTalkParamsConstants
+ */
+public class DingTalkParamsConstants {
+
+
+ static final String DING_TALK_WEB_HOOK = "dingtalk.webhook";
+
+ static final String NAME_DING_TALK_WEB_HOOK = "dingTalkWebHook";
+
+ static final String DING_TALK_KEYWORD = "dingtalk.keyword";
+
+ static final String NAME_DING_TALK_KEYWORD = "dingTalkKeyword";
+
+ public static final String DING_TALK_PROXY_ENABLE = "dingtalk.isEnableProxy";
+
+ static final String NAME_DING_TALK_PROXY_ENABLE = "dingTalkIsEnableProxy";
+
+ static final String DING_TALK_PROXY = "dingtalk.proxy";
+
+ static final String NAME_DING_TALK_PROXY = "dingTalkProxy";
+
+ static final String DING_TALK_PORT = "dingtalk.port";
+
+ static final String NAME_DING_TALK_PORT = "dingTalkPort";
+
+ static final String DING_TALK_USER = "dingtalk.user";
+
+ static final String NAME_DING_TALK_USER = "dingTalkUser";
+
+ static final String DING_TALK_PASSWORD = "dingtalk.password";
+
+ static final String NAME_DING_TALK_PASSWORD = "dingTalkPassword";
+
+}
diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-dingtalk/src/main/java/org/apache/dolphinscheduler/plugin/alert/dingtalk/DingTalkSender.java b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-dingtalk/src/main/java/org/apache/dolphinscheduler/plugin/alert/dingtalk/DingTalkSender.java
new file mode 100644
index 0000000..e88d160
--- /dev/null
+++ b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-dingtalk/src/main/java/org/apache/dolphinscheduler/plugin/alert/dingtalk/DingTalkSender.java
@@ -0,0 +1,204 @@
+/*
+ * 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.dingtalk;
+
+import org.apache.dolphinscheduler.spi.alert.AlertResult;
+import org.apache.dolphinscheduler.spi.utils.JSONUtils;
+
+import org.apache.commons.codec.binary.StringUtils;
+import org.apache.http.HttpEntity;
+import org.apache.http.HttpHost;
+import org.apache.http.auth.AuthScope;
+import org.apache.http.auth.UsernamePasswordCredentials;
+import org.apache.http.client.CredentialsProvider;
+import org.apache.http.client.config.RequestConfig;
+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.BasicCredentialsProvider;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClients;
+import org.apache.http.util.EntityUtils;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Ding Talk Sender
+ */
+public class DingTalkSender {
+ private static final Logger logger = LoggerFactory.getLogger(DingTalkSender.class);
+
+ private String url;
+
+ private String keyword;
+
+ private Boolean enableProxy;
+
+ private String proxy;
+
+ private Integer port;
+
+ private String user;
+
+ private String password;
+
+ DingTalkSender(Map<String, String> config) {
+ url = config.get(DingTalkParamsConstants.NAME_DING_TALK_WEB_HOOK);
+ keyword = config.get(DingTalkParamsConstants.NAME_DING_TALK_KEYWORD);
+ enableProxy = Boolean.valueOf(config.get(DingTalkParamsConstants.NAME_DING_TALK_PROXY_ENABLE));
+ if (Boolean.TRUE.equals(enableProxy)) {
+ port = Integer.parseInt(config.get(DingTalkParamsConstants.NAME_DING_TALK_PORT));
+ proxy = config.get(DingTalkParamsConstants.NAME_DING_TALK_PROXY);
+ user = config.get(DingTalkParamsConstants.DING_TALK_USER);
+ password = config.get(DingTalkParamsConstants.NAME_DING_TALK_PASSWORD);
+ }
+
+ }
+
+ public AlertResult sendDingTalkMsg(String msg, String charset) {
+ AlertResult alertResult;
+ try {
+ String resp = sendMsg(msg, charset);
+ return checkSendDingTalkSendMsgResult(resp);
+ } catch (Exception e) {
+ logger.info("send ding talk alert msg exception : {}", e.getMessage());
+ alertResult = new AlertResult();
+ alertResult.setStatus("false");
+ alertResult.setMessage("send ding talk alert fail.");
+ }
+ return alertResult;
+ }
+
+ private String sendMsg(String msg, String charset) throws IOException {
+
+ String msgToJson = textToJsonString(msg + "#" + keyword);
+ HttpPost httpPost = constructHttpPost(url, msgToJson, charset);
+
+ CloseableHttpClient httpClient;
+ if (Boolean.TRUE.equals(enableProxy)) {
+ httpClient = getProxyClient(proxy, port, user, password);
+ RequestConfig rcf = getProxyConfig(proxy, port);
+ httpPost.setConfig(rcf);
+ } else {
+ httpClient = getDefaultClient();
+ }
+
+ try {
+ CloseableHttpResponse response = httpClient.execute(httpPost);
+ String resp;
+ try {
+ HttpEntity entity = response.getEntity();
+ resp = EntityUtils.toString(entity, charset);
+ EntityUtils.consume(entity);
+ } finally {
+ response.close();
+ }
+ logger.info("Ding Talk send [%s], resp:{%s}", msg, resp);
+ return resp;
+ } finally {
+ httpClient.close();
+ }
+ }
+
+ private static HttpPost constructHttpPost(String url, String msg, String charset) {
+ HttpPost post = new HttpPost(url);
+ StringEntity entity = new StringEntity(msg, charset);
+ post.setEntity(entity);
+ post.addHeader("Content-Type", "application/json; charset=utf-8");
+ return post;
+ }
+
+ private static CloseableHttpClient getProxyClient(String proxy, int port, String user, String password) {
+ HttpHost httpProxy = new HttpHost(proxy, port);
+ CredentialsProvider provider = new BasicCredentialsProvider();
+ provider.setCredentials(new AuthScope(httpProxy), new UsernamePasswordCredentials(user, password));
+ return HttpClients.custom().setDefaultCredentialsProvider(provider).build();
+ }
+
+ private static CloseableHttpClient getDefaultClient() {
+ return HttpClients.createDefault();
+ }
+
+ private static RequestConfig getProxyConfig(String proxy, int port) {
+ HttpHost httpProxy = new HttpHost(proxy, port);
+ return RequestConfig.custom().setProxy(httpProxy).build();
+ }
+
+ private static String textToJsonString(String text) {
+ Map<String, Object> items = new HashMap<>();
+ items.put("msgtype", "text");
+ Map<String, String> textContent = new HashMap<>();
+ byte[] byt = StringUtils.getBytesUtf8(text);
+ String txt = StringUtils.newStringUtf8(byt);
+ textContent.put("content", txt);
+ items.put("text", textContent);
+ return JSONUtils.toJsonString(items);
+ }
+
+ public static class DingTalkSendMsgResponse {
+ private Integer errcode;
+ private String errmsg;
+
+ public Integer getErrcode() {
+ return errcode;
+ }
+
+ public void setErrcode(Integer errcode) {
+ this.errcode = errcode;
+ }
+
+ public String getErrmsg() {
+ return errmsg;
+ }
+
+ public void setErrmsg(String errmsg) {
+ this.errmsg = errmsg;
+ }
+ }
+
+ private static AlertResult checkSendDingTalkSendMsgResult(String result) {
+ AlertResult alertResult = new AlertResult();
+ alertResult.setStatus("false");
+
+ if (null == result) {
+ alertResult.setMessage("send ding talk msg error");
+ logger.info("send ding talk msg error,ding talk server resp is null");
+ return alertResult;
+ }
+ DingTalkSendMsgResponse sendMsgResponse = JSONUtils.parseObject(result, DingTalkSendMsgResponse.class);
+ if (null == sendMsgResponse) {
+ alertResult.setMessage("send ding talk msg fail");
+ logger.info("send ding talk msg error,resp error");
+ return alertResult;
+ }
+ if (sendMsgResponse.errcode == 0) {
+ alertResult.setStatus("true");
+ alertResult.setMessage("send ding talk msg success");
+ return alertResult;
+ }
+ alertResult.setMessage(String.format("alert send ding talk msg error : %s", sendMsgResponse.getErrmsg()));
+ logger.info("alert send ding talk msg error : {}", sendMsgResponse.getErrmsg());
+ return alertResult;
+ }
+
+}
diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-dingtalk/src/test/java/org/apache/dolphinscheduler/plugin/alert/dingtalk/DingTalkAlertChannelFactoryTest.java b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-dingtalk/src/test/java/org/apache/dolphinscheduler/plugin/alert/dingtalk/DingTalkAlertChannelFactoryTest.java
new file mode 100644
index 0000000..2a26daa
--- /dev/null
+++ b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-dingtalk/src/test/java/org/apache/dolphinscheduler/plugin/alert/dingtalk/DingTalkAlertChannelFactoryTest.java
@@ -0,0 +1,48 @@
+/*
+ * 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.dingtalk;
+
+import org.apache.dolphinscheduler.spi.alert.AlertChannel;
+import org.apache.dolphinscheduler.spi.params.base.PluginParams;
+import org.apache.dolphinscheduler.spi.utils.JSONUtils;
+
+import java.util.List;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * DingTalkAlertChannelFactoryTest
+ */
+public class DingTalkAlertChannelFactoryTest {
+
+ @Test
+ public void testGetParams() {
+ DingTalkAlertChannelFactory dingTalkAlertChannelFactory = new DingTalkAlertChannelFactory();
+ List<PluginParams> params = dingTalkAlertChannelFactory.getParams();
+ JSONUtils.toJsonString(params);
+ Assert.assertEquals(7, params.size());
+ }
+
+ @Test
+ public void testCreate() {
+ DingTalkAlertChannelFactory dingTalkAlertChannelFactory = new DingTalkAlertChannelFactory();
+ AlertChannel alertChannel = dingTalkAlertChannelFactory.create();
+ Assert.assertNotNull(alertChannel);
+ }
+}
diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-dingtalk/src/test/java/org/apache/dolphinscheduler/plugin/alert/dingtalk/DingTalkSenderTest.java b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-dingtalk/src/test/java/org/apache/dolphinscheduler/plugin/alert/dingtalk/DingTalkSenderTest.java
new file mode 100644
index 0000000..4512402
--- /dev/null
+++ b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-dingtalk/src/test/java/org/apache/dolphinscheduler/plugin/alert/dingtalk/DingTalkSenderTest.java
@@ -0,0 +1,57 @@
+/*
+ * 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.dingtalk;
+
+import org.apache.dolphinscheduler.spi.alert.AlertResult;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * DingTalkSenderTest
+ */
+public class DingTalkSenderTest {
+
+ private static Map<String, String> dingTalkConfig = new HashMap<>();
+
+ @Before
+ public void initDingTalkConfig() {
+
+ dingTalkConfig.put(DingTalkParamsConstants.NAME_DING_TALK_KEYWORD, "keyWord");
+ dingTalkConfig.put(DingTalkParamsConstants.NAME_DING_TALK_WEB_HOOK, "url");
+ dingTalkConfig.put(DingTalkParamsConstants.NAME_DING_TALK_PROXY_ENABLE, "false");
+ dingTalkConfig.put(DingTalkParamsConstants.NAME_DING_TALK_PASSWORD, "password");
+ dingTalkConfig.put(DingTalkParamsConstants.NAME_DING_TALK_PORT, "9988");
+ dingTalkConfig.put(DingTalkParamsConstants.NAME_DING_TALK_USER, "user1,user2");
+ }
+
+ @Test
+ public void testSend() {
+ DingTalkSender dingTalkSender = new DingTalkSender(dingTalkConfig);
+ dingTalkSender.sendDingTalkMsg("keyWord+Welcome", "UTF-8");
+ dingTalkConfig.put(DingTalkParamsConstants.NAME_DING_TALK_PROXY_ENABLE, "true");
+ dingTalkSender = new DingTalkSender(dingTalkConfig);
+ AlertResult alertResult = dingTalkSender.sendDingTalkMsg("keyWord+Welcome", "UTF-8");
+ Assert.assertEquals("false",alertResult.getStatus());
+ }
+
+}
diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-wechat/pom.xml b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-wechat/pom.xml
index 62ac776..1600170 100644
--- a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-wechat/pom.xml
+++ b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-wechat/pom.xml
@@ -27,6 +27,48 @@
<groupId>org.apache.dolphinscheduler</groupId>
<artifactId>dolphinscheduler-alert-wechat</artifactId>
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.dolphinscheduler</groupId>
+ <artifactId>dolphinscheduler-spi</artifactId>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>ch.qos.logback</groupId>
+ <artifactId>logback-classic</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.httpcomponents</groupId>
+ <artifactId>httpclient</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-databind</artifactId>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-core</artifactId>
+ <type>jar</type>
+ <scope>test</scope>
+ </dependency>
+
+ </dependencies>
</project>
\ No newline at end of file
diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-wechat/src/main/java/org/apache/dolphinscheduler/plugin/alert/wechat/WeChatAlertChannel.java b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-wechat/src/main/java/org/apache/dolphinscheduler/plugin/alert/wechat/WeChatAlertChannel.java
new file mode 100644
index 0000000..4cdd4d3
--- /dev/null
+++ b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-wechat/src/main/java/org/apache/dolphinscheduler/plugin/alert/wechat/WeChatAlertChannel.java
@@ -0,0 +1,41 @@
+/*
+ * 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.wechat;
+
+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 org.apache.dolphinscheduler.spi.params.PluginParamsTransfer;
+
+import java.util.Map;
+
+/**
+ * WeChatAlertChannel
+ */
+public class WeChatAlertChannel implements AlertChannel {
+
+ @Override
+ public AlertResult process(AlertInfo info) {
+ AlertData alertData = info.getAlertData();
+ String alertParams = info.getAlertParams();
+ Map<String, String> paramsMap = PluginParamsTransfer.getPluginParamsMap(alertParams);
+ return new WeChatSender(paramsMap).sendEnterpriseWeChat(alertData.getTitle(), alertData.getContent());
+
+ }
+}
diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-wechat/src/main/java/org/apache/dolphinscheduler/plugin/alert/wechat/WeChatAlertChannelFactory.java b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-wechat/src/main/java/org/apache/dolphinscheduler/plugin/alert/wechat/WeChatAlertChannelFactory.java
new file mode 100644
index 0000000..539add5
--- /dev/null
+++ b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-wechat/src/main/java/org/apache/dolphinscheduler/plugin/alert/wechat/WeChatAlertChannelFactory.java
@@ -0,0 +1,94 @@
+/*
+ * 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.wechat;
+
+import org.apache.dolphinscheduler.spi.alert.AlertChannel;
+import org.apache.dolphinscheduler.spi.alert.AlertChannelFactory;
+import org.apache.dolphinscheduler.spi.alert.AlertConstants;
+import org.apache.dolphinscheduler.spi.alert.ShowType;
+import org.apache.dolphinscheduler.spi.params.InputParam;
+import org.apache.dolphinscheduler.spi.params.RadioParam;
+import org.apache.dolphinscheduler.spi.params.base.ParamsOptions;
+import org.apache.dolphinscheduler.spi.params.base.PluginParams;
+import org.apache.dolphinscheduler.spi.params.base.Validate;
+
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * WeChatAlertChannelFactory
+ */
+public class WeChatAlertChannelFactory implements AlertChannelFactory {
+
+ @Override
+ public String getName() {
+ return "we chat alert";
+ }
+
+ @Override
+ public List<PluginParams> getParams() {
+ InputParam corpIdParam = InputParam.newBuilder(WeChatAlertParamsConstants.NAME_ENTERPRISE_WE_CHAT_CORP_ID, WeChatAlertParamsConstants.ENTERPRISE_WE_CHAT_CORP_ID)
+ .setPlaceholder("please input corp id ")
+ .addValidate(Validate.newBuilder()
+ .setRequired(true)
+ .build())
+ .build();
+
+ InputParam secretParam = InputParam.newBuilder(WeChatAlertParamsConstants.NAME_ENTERPRISE_WE_CHAT_SECRET, WeChatAlertParamsConstants.ENTERPRISE_WE_CHAT_SECRET)
+ .setPlaceholder("please input secret ")
+ .addValidate(Validate.newBuilder()
+ .setRequired(true)
+ .build())
+ .build();
+
+ InputParam usersParam = InputParam.newBuilder(WeChatAlertParamsConstants.NAME_ENTERPRISE_WE_CHAT_USERS, WeChatAlertParamsConstants.ENTERPRISE_WE_CHAT_USERS)
+ .setPlaceholder("please input users ")
+ .addValidate(Validate.newBuilder()
+ .setRequired(true)
+ .build())
+ .build();
+
+ InputParam userSendMsgParam = InputParam.newBuilder(WeChatAlertParamsConstants.NAME_ENTERPRISE_WE_CHAT_USER_SEND_MSG, WeChatAlertParamsConstants.ENTERPRISE_WE_CHAT_USER_SEND_MSG)
+ .setPlaceholder("please input corp id ")
+ .addValidate(Validate.newBuilder()
+ .setRequired(true)
+ .build())
+ .build();
+
+ InputParam agentIdParam = InputParam.newBuilder(WeChatAlertParamsConstants.NAME_ENTERPRISE_WE_CHAT_AGENT_ID, WeChatAlertParamsConstants.ENTERPRISE_WE_CHAT_AGENT_ID)
+ .setPlaceholder("please input agent id ")
+ .addValidate(Validate.newBuilder()
+ .setRequired(true)
+ .build())
+ .build();
+
+ RadioParam showType = RadioParam.newBuilder(AlertConstants.SHOW_TYPE, AlertConstants.SHOW_TYPE)
+ .addParamsOptions(new ParamsOptions(ShowType.TABLE.getDescp(), ShowType.TABLE.getDescp(), false))
+ .addParamsOptions(new ParamsOptions(ShowType.TEXT.getDescp(), ShowType.TEXT.getDescp(), false))
+ .setValue(ShowType.TABLE.getDescp())
+ .addValidate(Validate.newBuilder().setRequired(true).build())
+ .build();
+
+ return Arrays.asList(corpIdParam, secretParam, usersParam, userSendMsgParam, agentIdParam, showType);
+ }
+
+ @Override
+ public AlertChannel create() {
+ return new WeChatAlertChannel();
+ }
+}
diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-wechat/src/main/java/org/apache/dolphinscheduler/plugin/alert/wechat/WeChatAlertConstants.java b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-wechat/src/main/java/org/apache/dolphinscheduler/plugin/alert/wechat/WeChatAlertConstants.java
new file mode 100644
index 0000000..904060c
--- /dev/null
+++ b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-wechat/src/main/java/org/apache/dolphinscheduler/plugin/alert/wechat/WeChatAlertConstants.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.wechat;
+
+/**
+ * WeChatAlertConstants
+ */
+public class WeChatAlertConstants {
+
+ static final String MARKDOWN_QUOTE = ">";
+
+ static final String MARKDOWN_ENTER = "\n";
+
+ static final String CHARSET = "UTF-8";
+
+ static final String WE_CHAT_PUSH_URL = "https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token={token}";
+
+ static final String WE_CHAT_TOKEN_URL = "https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid={corpId}&corpsecret={secret}";
+}
diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-wechat/src/main/java/org/apache/dolphinscheduler/plugin/alert/wechat/WeChatAlertParamsConstants.java b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-wechat/src/main/java/org/apache/dolphinscheduler/plugin/alert/wechat/WeChatAlertParamsConstants.java
new file mode 100644
index 0000000..600e31e
--- /dev/null
+++ b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-wechat/src/main/java/org/apache/dolphinscheduler/plugin/alert/wechat/WeChatAlertParamsConstants.java
@@ -0,0 +1,56 @@
+/*
+ * 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.wechat;
+
+/**
+ * WeChatAlertParamsConstants
+ */
+public class WeChatAlertParamsConstants {
+
+
+ static final String ENTERPRISE_WE_CHAT_CORP_ID = "enterprise.wechat.corp.id";
+
+ static final String NAME_ENTERPRISE_WE_CHAT_CORP_ID = "enterpriseWeChatCorpId";
+
+
+ static final String ENTERPRISE_WE_CHAT_SECRET = "enterprise.wechat.secret";
+
+ static final String NAME_ENTERPRISE_WE_CHAT_SECRET = "enterpriseWeChatSecret";
+
+ static final String ENTERPRISE_WE_CHAT_TEAM_SEND_MSG = "enterprise.wechat.team.send.msg";
+
+ static final String NAME_ENTERPRISE_WE_CHAT_TEAM_SEND_MSG = "enterpriseWeChatTeamSendMsg";
+
+
+ static final String ENTERPRISE_WE_CHAT_USER_SEND_MSG = "enterprise.wechat.user.send.msg";
+
+ static final String NAME_ENTERPRISE_WE_CHAT_USER_SEND_MSG = "enterpriseWeChatUserSendMsg";
+
+
+ static final String ENTERPRISE_WE_CHAT_AGENT_ID = "enterprise.wechat.agent.id";
+
+ static final String NAME_ENTERPRISE_WE_CHAT_AGENT_ID = "enterpriseWeChatAgentId";
+
+
+ static final String ENTERPRISE_WE_CHAT_USERS = "enterprise.wechat.users";
+
+
+ static final String NAME_ENTERPRISE_WE_CHAT_USERS = "enterpriseWeChatUsers";
+
+
+}
diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-wechat/src/main/java/org/apache/dolphinscheduler/plugin/alert/wechat/WeChatAlertPlugin.java b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-wechat/src/main/java/org/apache/dolphinscheduler/plugin/alert/wechat/WeChatAlertPlugin.java
new file mode 100644
index 0000000..56c3c01
--- /dev/null
+++ b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-wechat/src/main/java/org/apache/dolphinscheduler/plugin/alert/wechat/WeChatAlertPlugin.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.wechat;
+
+import org.apache.dolphinscheduler.spi.DolphinSchedulerPlugin;
+import org.apache.dolphinscheduler.spi.alert.AlertChannelFactory;
+
+import com.google.common.collect.ImmutableList;
+
+/**
+ * WeChatAlertPlugin
+ */
+public class WeChatAlertPlugin implements DolphinSchedulerPlugin {
+
+ @Override
+ public Iterable<AlertChannelFactory> getAlertChannelFactorys() {
+ return ImmutableList.of(new WeChatAlertChannelFactory());
+ }
+}
diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-wechat/src/main/java/org/apache/dolphinscheduler/plugin/alert/wechat/WeChatSender.java b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-wechat/src/main/java/org/apache/dolphinscheduler/plugin/alert/wechat/WeChatSender.java
new file mode 100644
index 0000000..52397f5
--- /dev/null
+++ b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-wechat/src/main/java/org/apache/dolphinscheduler/plugin/alert/wechat/WeChatSender.java
@@ -0,0 +1,328 @@
+/*
+ * 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.wechat;
+
+import static java.util.Objects.requireNonNull;
+
+import org.apache.dolphinscheduler.spi.alert.AlertConstants;
+import org.apache.dolphinscheduler.spi.alert.AlertResult;
+import org.apache.dolphinscheduler.spi.alert.ShowType;
+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.HttpGet;
+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.io.IOException;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * WeChatSender
+ */
+public class WeChatSender {
+
+ private static Logger logger = LoggerFactory.getLogger(WeChatSender.class);
+
+ private String weChatAgentId;
+
+ private String weChatUsers;
+
+ private String weChatTeamSendMsg;
+
+ private String weChatUserSendMsg;
+
+ private String weChatTokenUrlReplace;
+
+ private String weChatToken;
+
+ private String showType;
+
+
+ private static final String agentIdRegExp = "{agentId}";
+ private static final String msgRegExp = "{msg}";
+ private static final String userRegExp = "{toUser}";
+ private static final String corpIdRegex = "{corpId}";
+ private static final String secretRegex = "{secret}";
+ private static final String toPartyRegex = "{toParty}";
+ private static final String toUserRegex = "{toUser}";
+ private static final String tokenRegex = "{token}";
+
+ WeChatSender(Map<String, String> config) {
+ weChatAgentId = config.get(WeChatAlertParamsConstants.NAME_ENTERPRISE_WE_CHAT_AGENT_ID);
+ weChatUsers = config.get(WeChatAlertParamsConstants.NAME_ENTERPRISE_WE_CHAT_USERS);
+ String weChatCorpId = config.get(WeChatAlertParamsConstants.NAME_ENTERPRISE_WE_CHAT_CORP_ID);
+ String weChatSecret = config.get(WeChatAlertParamsConstants.NAME_ENTERPRISE_WE_CHAT_SECRET);
+ String weChatTokenUrl = WeChatAlertConstants.WE_CHAT_TOKEN_URL;
+ weChatTeamSendMsg = config.get(WeChatAlertParamsConstants.NAME_ENTERPRISE_WE_CHAT_TEAM_SEND_MSG);
+ weChatUserSendMsg = config.get(WeChatAlertParamsConstants.NAME_ENTERPRISE_WE_CHAT_USER_SEND_MSG);
+ showType = config.get(AlertConstants.SHOW_TYPE);
+ requireNonNull(showType, AlertConstants.SHOW_TYPE + " must not null");
+ weChatTokenUrlReplace = weChatTokenUrl
+ .replace(corpIdRegex, weChatCorpId)
+ .replace(secretRegex, weChatSecret);
+ weChatToken = getToken();
+ }
+
+ /**
+ * make user multi user message
+ *
+ * @param toUser the toUser
+ * @param agentId the agentId
+ * @param msg the msg
+ * @return Enterprise WeChat send message
+ */
+ private String makeUserSendMsg(Collection<String> toUser, String agentId, String msg) {
+ String listUser = mkString(toUser);
+ return weChatUserSendMsg.replace(userRegExp, listUser)
+ .replace(agentIdRegExp, agentId)
+ .replace(msgRegExp, msg);
+ }
+
+ /**
+ * send Enterprise WeChat
+ *
+ * @return Enterprise WeChat resp, demo: {"errcode":0,"errmsg":"ok","invaliduser":""}
+ * @throws Exception the Exception
+ */
+ public AlertResult sendEnterpriseWeChat(String title, String content) {
+ List<String> userList = Arrays.asList(weChatUsers.split(","));
+ String data = markdownByAlert(title, content);
+ String msg = makeUserSendMsg(userList, weChatAgentId, data);
+ String enterpriseWeChatPushUrlReplace = WeChatAlertConstants.WE_CHAT_PUSH_URL.replace(tokenRegex, weChatToken);
+ AlertResult alertResult;
+ try {
+ return checkWeChatSendMsgResult(post(enterpriseWeChatPushUrlReplace, msg));
+ } catch (Exception e) {
+ logger.info("send we chat alert msg exception : {}", e.getMessage());
+ alertResult = new AlertResult();
+ alertResult.setMessage("send we chat alert fail");
+ alertResult.setStatus("false");
+ }
+ return alertResult;
+ }
+
+ private static String post(String url, String data) throws IOException {
+ try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
+ HttpPost httpPost = new HttpPost(url);
+ httpPost.setEntity(new StringEntity(data, WeChatAlertConstants.CHARSET));
+ CloseableHttpResponse response = httpClient.execute(httpPost);
+ String resp;
+ try {
+ HttpEntity entity = response.getEntity();
+ resp = EntityUtils.toString(entity, WeChatAlertConstants.CHARSET);
+ EntityUtils.consume(entity);
+ } finally {
+ response.close();
+ }
+ logger.info("Enterprise WeChat send [{}], param:{}, resp:{}",
+ url, data, resp);
+ return resp;
+ }
+ }
+
+ /**
+ * convert table to markdown style
+ *
+ * @param title the title
+ * @param content the content
+ * @return markdown table content
+ */
+ private static String markdownTable(String title, String content) {
+ List<LinkedHashMap> mapItemsList = JSONUtils.toList(content, LinkedHashMap.class);
+ if (null == mapItemsList || mapItemsList.isEmpty()) {
+ logger.error("itemsList is null");
+ throw new RuntimeException("itemsList is null");
+ }
+ StringBuilder contents = new StringBuilder(200);
+ for (LinkedHashMap mapItems : mapItemsList) {
+ Set<Entry<String, Object>> entries = mapItems.entrySet();
+ Iterator<Entry<String, Object>> iterator = entries.iterator();
+ StringBuilder t = new StringBuilder(String.format("`%s`%s", title, WeChatAlertConstants.MARKDOWN_ENTER));
+
+ while (iterator.hasNext()) {
+
+ Map.Entry<String, Object> entry = iterator.next();
+ t.append(WeChatAlertConstants.MARKDOWN_QUOTE);
+ t.append(entry.getKey()).append(":").append(entry.getValue());
+ t.append(WeChatAlertConstants.MARKDOWN_ENTER);
+ }
+ contents.append(t);
+ }
+
+ return contents.toString();
+ }
+
+ /**
+ * convert text to markdown style
+ *
+ * @param title the title
+ * @param content the content
+ * @return markdown text
+ */
+ private static String markdownText(String title, String content) {
+ if (StringUtils.isNotEmpty(content)) {
+ List<LinkedHashMap> mapItemsList = JSONUtils.toList(content, LinkedHashMap.class);
+ if (null == mapItemsList || mapItemsList.isEmpty()) {
+ logger.error("itemsList is null");
+ throw new RuntimeException("itemsList is null");
+ }
+
+ StringBuilder contents = new StringBuilder(100);
+ contents.append(String.format("`%s`%n", title));
+ for (LinkedHashMap mapItems : mapItemsList) {
+
+ Set<Map.Entry<String, Object>> entries = mapItems.entrySet();
+ for (Entry<String, Object> entry : entries) {
+ contents.append(WeChatAlertConstants.MARKDOWN_QUOTE);
+ contents.append(entry.getKey()).append(":").append(entry.getValue());
+ contents.append(WeChatAlertConstants.MARKDOWN_ENTER);
+ }
+
+ }
+ return contents.toString();
+ }
+ return null;
+ }
+
+ /**
+ * Determine the mardown style based on the show type of the alert
+ *
+ * @return the markdown alert table/text
+ */
+ private String markdownByAlert(String title, String content) {
+ String result = "";
+ if (showType.equals(ShowType.TABLE.getDescp())) {
+ result = markdownTable(title, content);
+ } else if (showType.equals(ShowType.TEXT.getDescp())) {
+ result = markdownText(title, content);
+ }
+ return result;
+
+ }
+
+ private String getToken() {
+ try {
+ return get(weChatTokenUrlReplace);
+ } catch (IOException e) {
+ logger.info("we chat alert get token error{}", e.getMessage());
+ }
+ return null;
+ }
+
+ private static String get(String url) throws IOException {
+ String resp;
+
+ try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
+ HttpGet httpGet = new HttpGet(url);
+ try (CloseableHttpResponse response = httpClient.execute(httpGet)) {
+ HttpEntity entity = response.getEntity();
+ resp = EntityUtils.toString(entity, WeChatAlertConstants.CHARSET);
+ EntityUtils.consume(entity);
+ }
+
+ HashMap map = JSONUtils.parseObject(resp, HashMap.class);
+ if (map != null) {
+ return map.get("access_token").toString();
+ } else {
+ return null;
+ }
+ }
+ }
+
+ private static String mkString(Iterable<String> list) {
+
+ if (null == list || StringUtils.isEmpty("|")) {
+ return null;
+ }
+
+ StringBuilder sb = new StringBuilder();
+ boolean first = true;
+ for (String item : list) {
+ if (first) {
+ first = false;
+ } else {
+ sb.append("|");
+ }
+ sb.append(item);
+ }
+ return sb.toString();
+ }
+
+ public static class WeChatSendMsgResponse {
+ private Integer errcode;
+ private String errmsg;
+
+ public Integer getErrcode() {
+ return errcode;
+ }
+
+ public void setErrcode(Integer errcode) {
+ this.errcode = errcode;
+ }
+
+ public String getErrmsg() {
+ return errmsg;
+ }
+
+ public void setErrmsg(String errmsg) {
+ this.errmsg = errmsg;
+ }
+ }
+
+ private static AlertResult checkWeChatSendMsgResult(String result) {
+ AlertResult alertResult = new AlertResult();
+ alertResult.setStatus("false");
+
+ if (null == result) {
+ alertResult.setMessage("we chat send fail");
+ logger.info("send we chat msg error,resp is null");
+ return alertResult;
+ }
+ WeChatSendMsgResponse sendMsgResponse = JSONUtils.parseObject(result, WeChatSendMsgResponse.class);
+ if (null == sendMsgResponse) {
+ alertResult.setMessage("we chat send fail");
+ logger.info("send we chat msg error,resp error");
+ return alertResult;
+ }
+ if (sendMsgResponse.errcode == 0) {
+ alertResult.setStatus("true");
+ alertResult.setMessage("we chat alert send success");
+ return alertResult;
+ }
+ alertResult.setStatus("false");
+ alertResult.setMessage(sendMsgResponse.getErrmsg());
+ return alertResult;
+ }
+}
diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-wechat/src/test/java/org/apache/dolphinscheduler/plugin/alert/wechat/WeChatAlertChannelFactoryTest.java b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-wechat/src/test/java/org/apache/dolphinscheduler/plugin/alert/wechat/WeChatAlertChannelFactoryTest.java
new file mode 100644
index 0000000..cc62d5a
--- /dev/null
+++ b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-wechat/src/test/java/org/apache/dolphinscheduler/plugin/alert/wechat/WeChatAlertChannelFactoryTest.java
@@ -0,0 +1,48 @@
+/*
+ * 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.wechat;
+
+import org.apache.dolphinscheduler.spi.alert.AlertChannel;
+import org.apache.dolphinscheduler.spi.params.base.PluginParams;
+import org.apache.dolphinscheduler.spi.utils.JSONUtils;
+
+import java.util.List;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * WeChatAlertChannelFactoryTest
+ */
+public class WeChatAlertChannelFactoryTest {
+
+ @Test
+ public void testGetParams() {
+ WeChatAlertChannelFactory weChatAlertChannelFactory = new WeChatAlertChannelFactory();
+ List<PluginParams> params = weChatAlertChannelFactory.getParams();
+ JSONUtils.toJsonString(params);
+ Assert.assertEquals(6, params.size());
+ }
+
+ @Test
+ public void testCreate() {
+ WeChatAlertChannelFactory dingTalkAlertChannelFactory = new WeChatAlertChannelFactory();
+ AlertChannel alertChannel = dingTalkAlertChannelFactory.create();
+ Assert.assertNotNull(alertChannel);
+ }
+}
diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-wechat/src/test/java/org/apache/dolphinscheduler/plugin/alert/wechat/WeChatSenderTest.java b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-wechat/src/test/java/org/apache/dolphinscheduler/plugin/alert/wechat/WeChatSenderTest.java
new file mode 100644
index 0000000..a6c4c4f
--- /dev/null
+++ b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-wechat/src/test/java/org/apache/dolphinscheduler/plugin/alert/wechat/WeChatSenderTest.java
@@ -0,0 +1,89 @@
+/*
+ * 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.wechat;
+
+import org.apache.dolphinscheduler.spi.alert.AlertConstants;
+import org.apache.dolphinscheduler.spi.alert.AlertResult;
+import org.apache.dolphinscheduler.spi.alert.ShowType;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * WeChatSenderTest
+ */
+public class WeChatSenderTest {
+
+ private static Map<String, String> weChatConfig = new HashMap<>();
+
+ private String content = "[{\"id\":\"69\","
+ +
+ "\"name\":\"UserBehavior-0--1193959466\","
+ +
+ "\"Job name\":\"Start workflow\","
+ +
+ "\"State\":\"SUCCESS\","
+ +
+ "\"Recovery\":\"NO\","
+ +
+ "\"Run time\":\"1\","
+ +
+ "\"Start time\": \"2018-08-06 10:31:34.0\","
+ +
+ "\"End time\": \"2018-08-06 10:31:49.0\","
+ +
+ "\"Host\": \"192.168.xx.xx\","
+ +
+ "\"Notify group\" :\"4\"}]";
+
+ @Before
+ public void initDingTalkConfig() {
+ // Just for this test, I will delete these configurations before this PR is merged
+ weChatConfig.put(WeChatAlertParamsConstants.NAME_ENTERPRISE_WE_CHAT_AGENT_ID, "1000002");
+ weChatConfig.put(WeChatAlertParamsConstants.NAME_ENTERPRISE_WE_CHAT_CORP_ID, "ww8cc690c06761eaa3");
+ weChatConfig.put(WeChatAlertParamsConstants.NAME_ENTERPRISE_WE_CHAT_SECRET, "MYL0_O91ICNrdjkAhgeXIOAj4gEKIirf0-xoYnA25vg");
+ weChatConfig.put(WeChatAlertParamsConstants.NAME_ENTERPRISE_WE_CHAT_USER_SEND_MSG, "{\"touser\":\"{toUser}\",\"agentid\":{agentId}"
+ +
+ ",\"msgtype\":\"markdown\",\"markdown\":{\"content\":\"{msg}\"}}"
+ );
+ weChatConfig.put(WeChatAlertParamsConstants.NAME_ENTERPRISE_WE_CHAT_USERS, "Kris");
+ weChatConfig.put(WeChatAlertParamsConstants.NAME_ENTERPRISE_WE_CHAT_TEAM_SEND_MSG, "msg");
+ weChatConfig.put(AlertConstants.SHOW_TYPE, ShowType.TABLE.getDescp());
+ }
+
+ @Test
+ public void testSendWeChatTableMsg() {
+ WeChatSender weChatSender = new WeChatSender(weChatConfig);
+
+ AlertResult alertResult = weChatSender.sendEnterpriseWeChat("test", content);
+ Assert.assertEquals("true", alertResult.getStatus());
+ }
+
+ @Test
+ public void testSendWeChatTextMsg() {
+ weChatConfig.put(AlertConstants.SHOW_TYPE, ShowType.TEXT.getDescp());
+ WeChatSender weChatSender = new WeChatSender(weChatConfig);
+ AlertResult alertResult = weChatSender.sendEnterpriseWeChat("test", content);
+ Assert.assertEquals("true", alertResult.getStatus());
+ }
+
+}
diff --git a/dolphinscheduler-alert/src/main/java/org/apache/dolphinscheduler/alert/manager/DingTalkManager.java b/dolphinscheduler-alert/src/main/java/org/apache/dolphinscheduler/alert/manager/DingTalkManager.java
deleted file mode 100644
index 07de6a0..0000000
--- a/dolphinscheduler-alert/src/main/java/org/apache/dolphinscheduler/alert/manager/DingTalkManager.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * 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.alert.manager;
-
-import org.apache.dolphinscheduler.alert.utils.Constants;
-import org.apache.dolphinscheduler.alert.utils.DingTalkUtils;
-import org.apache.dolphinscheduler.spi.alert.AlertInfo;
-
-import java.io.IOException;
-import java.util.HashMap;
-import java.util.Map;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Ding Talk Manager
- */
-public class DingTalkManager {
- private static final Logger logger = LoggerFactory.getLogger(EnterpriseWeChatManager.class);
-
- public Map<String, Object> send(AlertInfo alert) {
- Map<String, Object> retMap = new HashMap<>();
- retMap.put(Constants.STATUS, false);
- logger.info("send message {}", alert.getAlertData().getTitle());
- try {
- String msg = buildMessage(alert);
- DingTalkUtils.sendDingTalkMsg(msg, Constants.UTF_8);
- } catch (IOException e) {
- logger.error(e.getMessage(), e);
- }
- retMap.put(Constants.STATUS, true);
- return retMap;
- }
-
- private String buildMessage(AlertInfo alert) {
- String msg = alert.getAlertData().getContent();
- return msg;
- }
-}
diff --git a/dolphinscheduler-alert/src/main/java/org/apache/dolphinscheduler/alert/manager/EnterpriseWeChatManager.java b/dolphinscheduler-alert/src/main/java/org/apache/dolphinscheduler/alert/manager/EnterpriseWeChatManager.java
deleted file mode 100644
index 0534d80..0000000
--- a/dolphinscheduler-alert/src/main/java/org/apache/dolphinscheduler/alert/manager/EnterpriseWeChatManager.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * 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.alert.manager;
-
-import org.apache.dolphinscheduler.alert.utils.Constants;
-import org.apache.dolphinscheduler.alert.utils.EnterpriseWeChatUtils;
-import org.apache.dolphinscheduler.spi.alert.AlertInfo;
-
-import java.io.IOException;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Enterprise WeChat Manager
- */
-public class EnterpriseWeChatManager {
- private static final Logger logger = LoggerFactory.getLogger(EnterpriseWeChatManager.class);
-
- /**
- * Enterprise We Chat send
- *
- * @param alertInfo the alert info
- * @param token the token
- * @return the send result
- */
- public Map<String, Object> send(AlertInfo alertInfo, String token) {
- Map<String, Object> retMap = new HashMap<>();
- retMap.put(Constants.STATUS, false);
- String agentId = EnterpriseWeChatUtils.ENTERPRISE_WE_CHAT_AGENT_ID;
- String users = EnterpriseWeChatUtils.ENTERPRISE_WE_CHAT_USERS;
- List<String> userList = Arrays.asList(users.split(","));
- logger.info("send message {}", alertInfo.getAlertData().getTitle());
- String msg = EnterpriseWeChatUtils.makeUserSendMsg(userList, agentId, EnterpriseWeChatUtils.markdownByAlert(alertInfo));
- try {
- EnterpriseWeChatUtils.sendEnterpriseWeChat(Constants.UTF_8, msg, token);
- } catch (IOException e) {
- logger.error(e.getMessage(), e);
- }
- retMap.put(Constants.STATUS, true);
- return retMap;
- }
-
-}
diff --git a/dolphinscheduler-alert/src/main/java/org/apache/dolphinscheduler/alert/utils/DingTalkUtils.java b/dolphinscheduler-alert/src/main/java/org/apache/dolphinscheduler/alert/utils/DingTalkUtils.java
deleted file mode 100644
index abac8ae..0000000
--- a/dolphinscheduler-alert/src/main/java/org/apache/dolphinscheduler/alert/utils/DingTalkUtils.java
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * 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.alert.utils;
-
-import org.apache.dolphinscheduler.common.utils.JSONUtils;
-
-import org.apache.commons.codec.binary.StringUtils;
-import org.apache.http.HttpEntity;
-import org.apache.http.HttpHost;
-import org.apache.http.auth.AuthScope;
-import org.apache.http.auth.UsernamePasswordCredentials;
-import org.apache.http.client.CredentialsProvider;
-import org.apache.http.client.config.RequestConfig;
-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.BasicCredentialsProvider;
-import org.apache.http.impl.client.CloseableHttpClient;
-import org.apache.http.impl.client.HttpClients;
-import org.apache.http.util.EntityUtils;
-
-import java.io.IOException;
-import java.util.HashMap;
-import java.util.Map;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * DingTalkUtils utils
- * support send msg to ding talk by robot message push function.
- * support proxy setting
- */
-public class DingTalkUtils {
- public static final Logger logger = LoggerFactory.getLogger(DingTalkUtils.class);
-
- public static final boolean isEnableDingTalk = PropertyUtils.getBoolean(Constants.DINGTALK_ENABLE);
- private static final String dingTaskUrl = PropertyUtils.getString(Constants.DINGTALK_WEBHOOK);
- private static final String keyword = PropertyUtils.getString(Constants.DINGTALK_KEYWORD);
- private static final Boolean isEnableProxy = PropertyUtils.getBoolean(Constants.DINGTALK_PROXY_ENABLE);
- private static final String proxy = PropertyUtils.getString(Constants.DINGTALK_PROXY);
- private static final String user = PropertyUtils.getString(Constants.DINGTALK_USER);
- private static final String passwd = PropertyUtils.getString(Constants.DINGTALK_PASSWORD);
- private static final Integer port = PropertyUtils.getInt(Constants.DINGTALK_PORT);
-
- /**
- * send message interface
- * only support text message format now.
- *
- * @param msg message context to send
- * @param charset charset type
- * @return result of sending msg
- * @throws IOException the IOException
- */
- public static String sendDingTalkMsg(String msg, String charset) throws IOException {
- String msgToJson = textToJsonString(msg + "#" + keyword);
- HttpPost httpPost = constructHttpPost(msgToJson, charset);
-
- CloseableHttpClient httpClient;
- if (isEnableProxy) {
- httpClient = getProxyClient();
- RequestConfig rcf = getProxyConfig();
- httpPost.setConfig(rcf);
- } else {
- httpClient = getDefaultClient();
- }
-
- try {
- CloseableHttpResponse response = httpClient.execute(httpPost);
- String resp;
- try {
- HttpEntity entity = response.getEntity();
- resp = EntityUtils.toString(entity, charset);
- EntityUtils.consume(entity);
- } finally {
- response.close();
- }
- logger.info("Ding Talk send [{}], resp:{%s}", msg, resp);
- return resp;
- } finally {
- httpClient.close();
- }
- }
-
- public static HttpPost constructHttpPost(String msg, String charset) {
- HttpPost post = new HttpPost(dingTaskUrl);
- StringEntity entity = new StringEntity(msg, charset);
- post.setEntity(entity);
- post.addHeader("Content-Type", "application/json; charset=utf-8");
- return post;
- }
-
- public static CloseableHttpClient getProxyClient() {
- HttpHost httpProxy = new HttpHost(proxy, port);
- CredentialsProvider provider = new BasicCredentialsProvider();
- provider.setCredentials(new AuthScope(httpProxy), new UsernamePasswordCredentials(user, passwd));
- CloseableHttpClient httpClient = HttpClients.custom().setDefaultCredentialsProvider(provider).build();
- return httpClient;
- }
-
- public static CloseableHttpClient getDefaultClient() {
- return HttpClients.createDefault();
- }
-
- public static RequestConfig getProxyConfig() {
- HttpHost httpProxy = new HttpHost(proxy, port);
- return RequestConfig.custom().setProxy(httpProxy).build();
- }
-
- public static String textToJsonString(String text) {
- Map<String, Object> items = new HashMap<String, Object>();
- items.put("msgtype", "text");
- Map<String, String> textContent = new HashMap<String, String>();
- byte[] byt = StringUtils.getBytesUtf8(text);
- String txt = StringUtils.newStringUtf8(byt);
- textContent.put("content", txt);
- items.put("text", textContent);
-
- return JSONUtils.toJsonString(items);
-
- }
-
-}
diff --git a/dolphinscheduler-alert/src/main/java/org/apache/dolphinscheduler/alert/utils/EnterpriseWeChatUtils.java b/dolphinscheduler-alert/src/main/java/org/apache/dolphinscheduler/alert/utils/EnterpriseWeChatUtils.java
deleted file mode 100644
index 17a49e3..0000000
--- a/dolphinscheduler-alert/src/main/java/org/apache/dolphinscheduler/alert/utils/EnterpriseWeChatUtils.java
+++ /dev/null
@@ -1,290 +0,0 @@
-/*
- * 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.alert.utils;
-
-import org.apache.dolphinscheduler.common.utils.JSONUtils;
-import org.apache.dolphinscheduler.common.utils.StringUtils;
-import org.apache.dolphinscheduler.spi.alert.AlertConstants;
-import org.apache.dolphinscheduler.spi.alert.AlertInfo;
-import org.apache.dolphinscheduler.spi.alert.ShowType;
-import org.apache.dolphinscheduler.spi.params.PluginParamsTransfer;
-
-import org.apache.http.HttpEntity;
-import org.apache.http.client.methods.CloseableHttpResponse;
-import org.apache.http.client.methods.HttpGet;
-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.io.IOException;
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Enterprise WeChat utils
- */
-public class EnterpriseWeChatUtils {
-
- public static final Logger logger = LoggerFactory.getLogger(EnterpriseWeChatUtils.class);
- public static final String ENTERPRISE_WE_CHAT_AGENT_ID = PropertyUtils.getString(Constants.ENTERPRISE_WECHAT_AGENT_ID);
- public static final String ENTERPRISE_WE_CHAT_USERS = PropertyUtils.getString(Constants.ENTERPRISE_WECHAT_USERS);
- private static final String ENTERPRISE_WE_CHAT_CORP_ID = PropertyUtils.getString(Constants.ENTERPRISE_WECHAT_CORP_ID);
- private static final String ENTERPRISE_WE_CHAT_SECRET = PropertyUtils.getString(Constants.ENTERPRISE_WECHAT_SECRET);
- private static final String ENTERPRISE_WE_CHAT_TOKEN_URL = PropertyUtils.getString(Constants.ENTERPRISE_WECHAT_TOKEN_URL);
- private static final String ENTERPRISE_WE_CHAT_TOKEN_URL_REPLACE = ENTERPRISE_WE_CHAT_TOKEN_URL == null ? null : ENTERPRISE_WE_CHAT_TOKEN_URL
- .replaceAll("\\{corpId}", ENTERPRISE_WE_CHAT_CORP_ID)
- .replaceAll("\\{secret}", ENTERPRISE_WE_CHAT_SECRET);
- private static final String ENTERPRISE_WE_CHAT_PUSH_URL = PropertyUtils.getString(Constants.ENTERPRISE_WECHAT_PUSH_URL);
- private static final String ENTERPRISE_WE_CHAT_TEAM_SEND_MSG = PropertyUtils.getString(Constants.ENTERPRISE_WECHAT_TEAM_SEND_MSG);
- private static final String ENTERPRISE_WE_CHAT_USER_SEND_MSG = PropertyUtils.getString(Constants.ENTERPRISE_WECHAT_USER_SEND_MSG);
-
- private static final String agentIdRegExp = "\\{agentId}";
- private static final String msgRegExp = "\\{msg}";
- private static final String userRegExp = "\\{toUser}";
-
- /**
- * get Enterprise WeChat is enable
- *
- * @return isEnable
- */
- public static boolean isEnable() {
- Boolean isEnable = null;
- try {
- isEnable = PropertyUtils.getBoolean(Constants.ENTERPRISE_WECHAT_ENABLE);
- } catch (Exception e) {
- logger.error(e.getMessage(), e);
- }
- if (isEnable == null) {
- return false;
- }
- return isEnable;
- }
-
- /**
- * get Enterprise WeChat token info
- *
- * @return token string info
- * @throws IOException the IOException
- */
- public static String getToken() throws IOException {
- String resp;
-
- CloseableHttpClient httpClient = HttpClients.createDefault();
- try {
- HttpGet httpGet = new HttpGet(ENTERPRISE_WE_CHAT_TOKEN_URL_REPLACE);
- CloseableHttpResponse response = httpClient.execute(httpGet);
- try {
- HttpEntity entity = response.getEntity();
- resp = EntityUtils.toString(entity, Constants.UTF_8);
- EntityUtils.consume(entity);
- } finally {
- response.close();
- }
-
- Map<String, String> map = JSONUtils.toMap(resp);
- if (map != null) {
- return map.get("access_token");
- } else {
- return null;
- }
- } finally {
- httpClient.close();
- }
- }
-
- /**
- * make team single Enterprise WeChat message
- *
- * @param toParty the toParty
- * @param agentId the agentId
- * @param msg the msg
- * @return Enterprise WeChat send message
- */
- public static String makeTeamSendMsg(String toParty, String agentId, String msg) {
- return ENTERPRISE_WE_CHAT_TEAM_SEND_MSG.replaceAll("\\{toParty}", toParty)
- .replaceAll(agentIdRegExp, agentId)
- .replaceAll(msgRegExp, msg);
- }
-
- /**
- * make team multi Enterprise WeChat message
- *
- * @param toParty the toParty
- * @param agentId the agentId
- * @param msg the msg
- * @return Enterprise WeChat send message
- */
- public static String makeTeamSendMsg(Collection<String> toParty, String agentId, String msg) {
- String listParty = FuncUtils.mkString(toParty, "|");
- return ENTERPRISE_WE_CHAT_TEAM_SEND_MSG.replaceAll("\\{toParty}", listParty)
- .replaceAll(agentIdRegExp, agentId)
- .replaceAll(msgRegExp, msg);
- }
-
- /**
- * make team single user message
- *
- * @param toUser the toUser
- * @param agentId the agentId
- * @param msg the msg
- * @return Enterprise WeChat send message
- */
- public static String makeUserSendMsg(String toUser, String agentId, String msg) {
- return ENTERPRISE_WE_CHAT_USER_SEND_MSG.replaceAll("\\{toUser}", toUser)
- .replaceAll(agentIdRegExp, agentId)
- .replaceAll(msgRegExp, msg);
- }
-
- /**
- * make team multi user message
- *
- * @param toUser the toUser
- * @param agentId the agentId
- * @param msg the msg
- * @return Enterprise WeChat send message
- */
- public static String makeUserSendMsg(Collection<String> toUser, String agentId, String msg) {
- String listUser = FuncUtils.mkString(toUser, "|");
- return ENTERPRISE_WE_CHAT_USER_SEND_MSG.replaceAll(userRegExp, listUser)
- .replaceAll(agentIdRegExp, agentId)
- .replaceAll(msgRegExp, msg);
- }
-
- /**
- * send Enterprise WeChat
- *
- * @param charset the charset
- * @param data the data
- * @param token the token
- * @return Enterprise WeChat resp, demo: {"errcode":0,"errmsg":"ok","invaliduser":""}
- * @throws IOException the IOException
- */
- public static String sendEnterpriseWeChat(String charset, String data, String token) throws IOException {
- String enterpriseWeChatPushUrlReplace = ENTERPRISE_WE_CHAT_PUSH_URL.replaceAll("\\{token}", token);
-
- CloseableHttpClient httpClient = HttpClients.createDefault();
- try {
- HttpPost httpPost = new HttpPost(enterpriseWeChatPushUrlReplace);
- httpPost.setEntity(new StringEntity(data, charset));
- CloseableHttpResponse response = httpClient.execute(httpPost);
- String resp;
- try {
- HttpEntity entity = response.getEntity();
- resp = EntityUtils.toString(entity, charset);
- EntityUtils.consume(entity);
- } finally {
- response.close();
- }
- logger.info("Enterprise WeChat send [{}], param:{}, resp:{}",
- ENTERPRISE_WE_CHAT_PUSH_URL, data, resp);
- return resp;
- } finally {
- httpClient.close();
- }
- }
-
- /**
- * convert table to markdown style
- *
- * @param title the title
- * @param content the content
- * @return markdown table content
- */
- public static String markdownTable(String title, String content) {
- List<LinkedHashMap> mapItemsList = JSONUtils.toList(content, LinkedHashMap.class);
- StringBuilder contents = new StringBuilder(200);
-
- if (null != mapItemsList) {
- for (LinkedHashMap mapItems : mapItemsList) {
- Set<Map.Entry<String, Object>> entries = mapItems.entrySet();
- Iterator<Map.Entry<String, Object>> iterator = entries.iterator();
- StringBuilder t = new StringBuilder(String.format("`%s`%s", title, Constants.MARKDOWN_ENTER));
-
- while (iterator.hasNext()) {
-
- Map.Entry<String, Object> entry = iterator.next();
- t.append(Constants.MARKDOWN_QUOTE);
- t.append(entry.getKey()).append(":").append(entry.getValue());
- t.append(Constants.MARKDOWN_ENTER);
- }
- contents.append(t);
- }
- }
- return contents.toString();
- }
-
- /**
- * convert text to markdown style
- *
- * @param title the title
- * @param content the content
- * @return markdown text
- */
- public static String markdownText(String title, String content) {
- if (StringUtils.isNotEmpty(content)) {
- List<LinkedHashMap> mapItemsList = JSONUtils.toList(content, LinkedHashMap.class);
- if (null != mapItemsList) {
- StringBuilder contents = new StringBuilder(100);
- contents.append(String.format("`%s`%n", title));
- for (LinkedHashMap mapItems : mapItemsList) {
-
- Set<Map.Entry<String, Object>> entries = mapItems.entrySet();
- Iterator<Map.Entry<String, Object>> iterator = entries.iterator();
- while (iterator.hasNext()) {
- Map.Entry<String, Object> entry = iterator.next();
- contents.append(Constants.MARKDOWN_QUOTE);
- contents.append(entry.getKey()).append(":").append(entry.getValue());
- contents.append(Constants.MARKDOWN_ENTER);
- }
-
- }
- return contents.toString();
- }
-
- }
- return null;
- }
-
- /**
- * Determine the mardown style based on the show type of the alert
- *
- * @return the markdown alert table/text
- */
- public static String markdownByAlert(AlertInfo alertInfo) {
- String result = "";
- Map<String, String> paramsMap = PluginParamsTransfer.getPluginParamsMap(alertInfo.getAlertParams());
- String showType = paramsMap.get(AlertConstants.SHOW_TYPE);
- if (showType.equals(ShowType.TABLE.getDescp())) {
- result = markdownTable(alertInfo.getAlertData().getTitle(), alertInfo.getAlertData().getContent());
- } else if (showType.equals(ShowType.TEXT.getDescp())) {
- result = markdownText(alertInfo.getAlertData().getTitle(), alertInfo.getAlertData().getContent());
- }
- return result;
-
- }
-
-}
diff --git a/dolphinscheduler-alert/src/test/java/org/apache/dolphinscheduler/alert/utils/DingTalkUtilsTest.java b/dolphinscheduler-alert/src/test/java/org/apache/dolphinscheduler/alert/utils/DingTalkUtilsTest.java
deleted file mode 100644
index 27c481e..0000000
--- a/dolphinscheduler-alert/src/test/java/org/apache/dolphinscheduler/alert/utils/DingTalkUtilsTest.java
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * 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.alert.utils;
-
-import org.apache.http.client.config.RequestConfig;
-import org.apache.http.impl.client.CloseableHttpClient;
-
-import java.io.IOException;
-
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mockito;
-import org.powermock.api.mockito.PowerMockito;
-import org.powermock.core.classloader.annotations.PowerMockIgnore;
-import org.powermock.core.classloader.annotations.PrepareForTest;
-import org.powermock.modules.junit4.PowerMockRunner;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-@PrepareForTest(PropertyUtils.class)
-@RunWith(PowerMockRunner.class)
-@PowerMockIgnore("javax.net.ssl.*")
-public class DingTalkUtilsTest {
- Logger logger = LoggerFactory.getLogger(DingTalkUtilsTest.class);
-
- private static final String mockUrl = "https://oapi.dingtalk.com/robot/send?access_token=test";
- private static final String mockKeyWords = "onway";
- private static final String msg = "ding talk test";
-
- @Before
- public void init() {
- PowerMockito.mockStatic(PropertyUtils.class);
- Mockito.when(PropertyUtils.getString(Constants.DINGTALK_WEBHOOK)).thenReturn(mockUrl);
- Mockito.when(PropertyUtils.getString(Constants.DINGTALK_KEYWORD)).thenReturn(mockKeyWords);
- Mockito.when(PropertyUtils.getBoolean(Constants.DINGTALK_PROXY_ENABLE)).thenReturn(true);
- Mockito.when(PropertyUtils.getString(Constants.DINGTALK_PROXY)).thenReturn("proxy.com.cn");
- Mockito.when(PropertyUtils.getString(Constants.DINGTALK_USER)).thenReturn("user");
- Mockito.when(PropertyUtils.getString(Constants.DINGTALK_PASSWORD)).thenReturn("pswd");
- Mockito.when(PropertyUtils.getInt(Constants.DINGTALK_PORT)).thenReturn(80);
- }
-
- @Test
- public void testCreateDefaultClient() {
- CloseableHttpClient client = DingTalkUtils.getDefaultClient();
- try {
- Assert.assertNotNull(client);
- client.close();
- } catch (IOException ex) {
- logger.info("close exception", ex.getMessage());
- new Throwable();
- }
- }
-
- @Test
- public void testCreateProxyClient() {
- CloseableHttpClient client = DingTalkUtils.getProxyClient();
- try {
- Assert.assertNotNull(client);
- client.close();
- } catch (IOException ex) {
- logger.info("close exception", ex.getMessage());
- new Throwable();
- }
-
- }
-
- @Test
- public void testProxyConfig() {
- RequestConfig rc = DingTalkUtils.getProxyConfig();
- Assert.assertEquals(rc.getProxy().getPort(), 80);
- Assert.assertEquals(rc.getProxy().getHostName(), "proxy.com.cn");
- }
-
- @Test
- public void testDingTalkMsgToJson() {
- String jsonString = DingTalkUtils.textToJsonString("this is test");
-
- logger.info(jsonString);
- String expect = "{\"text\":{\"content\":\"this is test\"},\"msgtype\":\"text\"}";
- Assert.assertEquals(expect, jsonString);
- }
-
- @Test
- public void testDingTalkMsgUtf8() {
- String msg = DingTalkUtils.textToJsonString("this is test:中文");
-
- logger.info("test support utf8, actual:" + msg);
- logger.info("test support utf8, actual:" + DingTalkUtils.isEnableDingTalk);
- String expect = "{\"text\":{\"content\":\"this is test:中文\"},\"msgtype\":\"text\"}";
- Assert.assertEquals(expect, msg);
- }
-
-}
diff --git a/dolphinscheduler-alert/src/test/java/org/apache/dolphinscheduler/alert/utils/EnterpriseWeChatUtilsTest.java b/dolphinscheduler-alert/src/test/java/org/apache/dolphinscheduler/alert/utils/EnterpriseWeChatUtilsTest.java
deleted file mode 100644
index d528d2c..0000000
--- a/dolphinscheduler-alert/src/test/java/org/apache/dolphinscheduler/alert/utils/EnterpriseWeChatUtilsTest.java
+++ /dev/null
@@ -1,307 +0,0 @@
-/*
- * 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.alert.utils;
-
-import org.apache.dolphinscheduler.common.enums.AlertType;
-import org.apache.dolphinscheduler.common.utils.JSONUtils;
-import org.apache.dolphinscheduler.dao.entity.Alert;
-import org.apache.dolphinscheduler.spi.alert.AlertConstants;
-import org.apache.dolphinscheduler.spi.alert.AlertData;
-import org.apache.dolphinscheduler.spi.alert.AlertInfo;
-import org.apache.dolphinscheduler.spi.alert.ShowType;
-import org.apache.dolphinscheduler.spi.params.PluginParamsTransfer;
-import org.apache.dolphinscheduler.spi.params.RadioParam;
-import org.apache.dolphinscheduler.spi.params.base.PluginParams;
-
-import java.util.ArrayList;
-import java.util.LinkedHashMap;
-import java.util.List;
-
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mockito;
-import org.powermock.api.mockito.PowerMockito;
-import org.powermock.core.classloader.annotations.PrepareForTest;
-import org.powermock.modules.junit4.PowerMockRunner;
-
-/**
- * Please manually modify the configuration file before testing.
- * file: alert.properties
- * enterprise.wechat.corp.id
- * enterprise.wechat.secret
- * enterprise.wechat.token.url
- * enterprise.wechat.push.url
- * enterprise.wechat.send.msg
- * enterprise.wechat.agent.id
- * enterprise.wechat.users
- */
-
-@PrepareForTest(PropertyUtils.class)
-@RunWith(PowerMockRunner.class)
-public class EnterpriseWeChatUtilsTest {
-
- private static final String toParty = "wwc99134b6fc1edb6";
- private static final String enterpriseWechatSecret = "Uuv2KFrkdf7SeKOsTDCpsTkpawXBMNRhFy6VKX5FV";
- private static final String enterpriseWechatAgentId = "1000004";
- private static final String enterpriseWechatUsers = "LiGang,journey";
- private static final String msg = "hello world";
-
- private static final String enterpriseWechatTeamSendMsg = "{\\\"toparty\\\":\\\"{toParty}\\\",\\\"agentid\\\":\\\"{agentId}\\\""
- +
- ",\\\"msgtype\\\":\\\"text\\\",\\\"text\\\":{\\\"content\\\":\\\"{msg}\\\"},\\\"safe\\\":\\\"0\\\"}";
- private static final String enterpriseWechatUserSendMsg = "{\\\"touser\\\":\\\"{toUser}\\\",\\\"agentid\\\":\\\"{agentId}\\\""
- +
- ",\\\"msgtype\\\":\\\"markdown\\\",\\\"markdown\\\":{\\\"content\\\":\\\"{msg}\\\"}}";
-
- @Before
- public void init() {
- PowerMockito.mockStatic(PropertyUtils.class);
- Mockito.when(PropertyUtils.getBoolean(Constants.ENTERPRISE_WECHAT_ENABLE)).thenReturn(true);
- Mockito.when(PropertyUtils.getString(Constants.ENTERPRISE_WECHAT_USER_SEND_MSG)).thenReturn(enterpriseWechatUserSendMsg);
- Mockito.when(PropertyUtils.getString(Constants.ENTERPRISE_WECHAT_TEAM_SEND_MSG)).thenReturn(enterpriseWechatTeamSendMsg);
- }
-
- @Test
- public void testIsEnable() {
- Boolean weChartEnable = EnterpriseWeChatUtils.isEnable();
- Assert.assertTrue(weChartEnable);
- }
-
- @Test
- public void testMakeTeamSendMsg1() {
- String sendMsg = EnterpriseWeChatUtils.makeTeamSendMsg(toParty, enterpriseWechatSecret, msg);
- Assert.assertTrue(sendMsg.contains(toParty));
- Assert.assertTrue(sendMsg.contains(enterpriseWechatSecret));
- Assert.assertTrue(sendMsg.contains(msg));
-
- }
-
- @Test
- public void testMakeTeamSendMsg2() {
- List<String> parties = new ArrayList<>();
- parties.add(toParty);
- parties.add("test1");
-
- String sendMsg = EnterpriseWeChatUtils.makeTeamSendMsg(parties, enterpriseWechatSecret, msg);
- Assert.assertTrue(sendMsg.contains(toParty));
- Assert.assertTrue(sendMsg.contains(enterpriseWechatSecret));
- Assert.assertTrue(sendMsg.contains(msg));
- }
-
- @Test
- public void tesMakeUserSendMsg1() {
-
- String sendMsg = EnterpriseWeChatUtils.makeUserSendMsg(enterpriseWechatUsers, enterpriseWechatAgentId, msg);
- Assert.assertTrue(sendMsg.contains(enterpriseWechatUsers));
- Assert.assertTrue(sendMsg.contains(enterpriseWechatAgentId));
- Assert.assertTrue(sendMsg.contains(msg));
- }
-
- @Test
- public void tesMakeUserSendMsg2() {
- List<String> users = new ArrayList<>();
- users.add("user1");
- users.add("user2");
-
- String sendMsg = EnterpriseWeChatUtils.makeUserSendMsg(users, enterpriseWechatAgentId, msg);
- Assert.assertTrue(sendMsg.contains(users.get(0)));
- Assert.assertTrue(sendMsg.contains(users.get(1)));
- Assert.assertTrue(sendMsg.contains(enterpriseWechatAgentId));
- Assert.assertTrue(sendMsg.contains(msg));
- }
-
- @Test
- public void testMarkdownByAlertForText() {
- Alert alertForText = createAlertForText();
- AlertData alertData = new AlertData();
- AlertInfo alertInfo = new AlertInfo();
- //TODO:
- List<PluginParams> paramsList = new ArrayList<>();
- RadioParam showType = new RadioParam.Builder(AlertConstants.SHOW_TYPE, AlertConstants.SHOW_TYPE)
- .setValue(ShowType.TEXT)
- .build();
- paramsList.add(showType);
- alertInfo.setAlertParams(PluginParamsTransfer.transferParamsToJson(paramsList));
- alertInfo.setAlertData(alertData);
- alertData.setTitle(alertForText.getTitle())
- //.setShowType(alertForText.getShowType().getDescp())
- .setContent(alertForText.getContent());
- String result = EnterpriseWeChatUtils.markdownByAlert(alertInfo);
- Assert.assertNotNull(result);
- }
-
- @Test
- public void testMarkdownByAlertForTable() {
- Alert alertForText = createAlertForTable();
- AlertData alertData = new AlertData();
- AlertInfo alertInfo = new AlertInfo();
- //TODO:
- List<PluginParams> paramsList = new ArrayList<>();
- RadioParam showType = new RadioParam.Builder(AlertConstants.SHOW_TYPE, AlertConstants.SHOW_TYPE)
- .setValue(ShowType.TABLE)
- .build();
- paramsList.add(showType);
- alertInfo.setAlertParams(PluginParamsTransfer.transferParamsToJson(paramsList));
- alertInfo.setAlertData(alertData);
- alertData.setTitle(alertForText.getTitle())
- //.setShowType(alertForText.getShowType().getDescp())
- .setContent(alertForText.getContent());
- String result = EnterpriseWeChatUtils.markdownByAlert(alertInfo);
- Assert.assertNotNull(result);
- }
-
- private Alert createAlertForText() {
- String content = "[{\"id\":\"69\","
- +
- "\"name\":\"UserBehavior-0--1193959466\","
- +
- "\"Job name\":\"Start workflow\","
- +
- "\"State\":\"SUCCESS\","
- +
- "\"Recovery\":\"NO\","
- +
- "\"Run time\":\"1\","
- +
- "\"Start time\": \"2018-08-06 10:31:34.0\","
- +
- "\"End time\": \"2018-08-06 10:31:49.0\","
- +
- "\"Host\": \"192.168.xx.xx\","
- +
- "\"Notify group\" :\"4\"}]";
-
- Alert alert = new Alert();
- alert.setTitle("Mysql Exception");
- //alert.setShowType(ShowType.TEXT);
- alert.setContent(content);
- alert.setAlertType(AlertType.EMAIL);
- alert.setAlertGroupId(4);
-
- return alert;
- }
-
- private String list2String() {
-
- LinkedHashMap<String, Object> map1 = new LinkedHashMap<>();
- map1.put("mysql service name", "mysql200");
- map1.put("mysql address", "192.168.xx.xx");
- map1.put("port", "3306");
- map1.put("no index of number", "80");
- map1.put("database client connections", "190");
-
- LinkedHashMap<String, Object> map2 = new LinkedHashMap<>();
- map2.put("mysql service name", "mysql210");
- map2.put("mysql address", "192.168.xx.xx");
- map2.put("port", "3306");
- map2.put("no index of number", "10");
- map2.put("database client connections", "90");
-
- List<LinkedHashMap<String, Object>> maps = new ArrayList<>();
- maps.add(0, map1);
- maps.add(1, map2);
- String mapjson = JSONUtils.toJsonString(maps);
- return mapjson;
- }
-
- private Alert createAlertForTable() {
- Alert alert = new Alert();
- alert.setTitle("Mysql Exception");
- //alert.setShowType(ShowType.TABLE.getDescp());
- String content = list2String();
- alert.setContent(content);
- alert.setAlertType(AlertType.EMAIL);
- alert.setAlertGroupId(1);
- return alert;
- }
-
-
- // @Test
- // public void testSendSingleTeamWeChat() {
- // try {
- // String token = EnterpriseWeChatUtils.getToken();
- // String msg = EnterpriseWeChatUtils.makeTeamSendMsg(partyId, agentId, "hello world");
- // String resp = EnterpriseWeChatUtils.sendEnterpriseWeChat("utf-8", msg, token);
- //
- // String errmsg = JSONUtils.parseObject(resp).getString("errmsg");
- // Assert.assertEquals("ok",errmsg);
- // } catch (IOException e) {
- // e.printStackTrace();
- // }
- // }
- //
- // @Test
- // public void testSendMultiTeamWeChat() {
- //
- // try {
- // String token = EnterpriseWeChatUtils.getToken();
- // String msg = EnterpriseWeChatUtils.makeTeamSendMsg(listPartyId, agentId, "hello world");
- // String resp = EnterpriseWeChatUtils.sendEnterpriseWeChat("utf-8", msg, token);
- //
- // String errmsg = JSONUtils.parseObject(resp).getString("errmsg");
- // Assert.assertEquals("ok",errmsg);
- // } catch (IOException e) {
- // e.printStackTrace();
- // }
- // }
- //
- // @Test
- // public void testSendSingleUserWeChat() {
- // try {
- // String token = EnterpriseWeChatUtils.getToken();
- // String msg = EnterpriseWeChatUtils.makeUserSendMsg(listUserId.stream().findFirst().get(), agentId, "your meeting room has been booked and will be synced to the 'mailbox' later \n" +
- // ">**matter details** \n" +
- // ">matter:<font color='info'>meeting</font> <br>" +
- // ">organizer:@miglioguan \n" +
- // ">participant:@miglioguan、@kunliu、@jamdeezhou、@kanexiong、@kisonwang \n" +
- // "> \n" +
- // ">meeting room:<font color='info'>Guangzhou TIT 1st Floor 301</font> \n" +
- // ">date:<font color='warning'>May 18, 2018</font> \n" +
- // ">time:<font color='comment'>9:00-11:00 am</font> \n" +
- // "> \n" +
- // ">please attend the meeting on time\n" +
- // "> \n" +
- // ">to modify the meeting information, please click: [Modify Meeting Information](https://work.weixin.qq.com)\"");
- //
- // String resp = EnterpriseWeChatUtils.sendEnterpriseWeChat("utf-8", msg, token);
- //
- // String errmsg = JSONUtils.parseObject(resp).getString("errmsg");
- // Assert.assertEquals("ok",errmsg);
- // } catch (IOException e) {
- // e.printStackTrace();
- // }
- // }
- //
- // @Test
- // public void testSendMultiUserWeChat() {
- // try {
- // String token = EnterpriseWeChatUtils.getToken();
- //
- // String msg = EnterpriseWeChatUtils.makeUserSendMsg(listUserId, agentId, "hello world");
- // String resp = EnterpriseWeChatUtils.sendEnterpriseWeChat("utf-8", msg, token);
- //
- // String errmsg = JSONUtils.parseObject(resp).getString("errmsg");
- // Assert.assertEquals("ok",errmsg);
- // } catch (IOException e) {
- // e.printStackTrace();
- // }
- // }
-
-}
diff --git a/dolphinscheduler-spi/pom.xml b/dolphinscheduler-spi/pom.xml
index 50ed17e..dd0bae8 100644
--- a/dolphinscheduler-spi/pom.xml
+++ b/dolphinscheduler-spi/pom.xml
@@ -35,10 +35,12 @@
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
</dependency>
+
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
+
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
diff --git a/dolphinscheduler-spi/src/main/java/org/apache/dolphinscheduler/spi/utils/JSONUtils.java b/dolphinscheduler-spi/src/main/java/org/apache/dolphinscheduler/spi/utils/JSONUtils.java
index e48686e..6542ef8 100644
--- a/dolphinscheduler-spi/src/main/java/org/apache/dolphinscheduler/spi/utils/JSONUtils.java
+++ b/dolphinscheduler-spi/src/main/java/org/apache/dolphinscheduler/spi/utils/JSONUtils.java
@@ -153,4 +153,4 @@ public class JSONUtils {
throw new RuntimeException("Json deserialization exception.", e);
}
}
-}
+}
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index d854a3a..eb43e00 100644
--- a/pom.xml
+++ b/pom.xml
@@ -687,9 +687,9 @@
<artifactId>dolphinscheduler-maven-plugin</artifactId>
<extensions>true</extensions>
<!--<configuration>-->
- <!--<allowedProvidedDependencies>-->
- <!--<allowedProvidedDependency>org.apache.dolphinscheduler:dolphinscheduler-common</allowedProvidedDependency>-->
- <!--</allowedProvidedDependencies>-->
+ <!--<allowedProvidedDependencies>-->
+ <!--<allowedProvidedDependency>org.apache.dolphinscheduler:dolphinscheduler-common</allowedProvidedDependency>-->
+ <!--</allowedProvidedDependencies>-->
<!--</configuration>-->
</plugin>
@@ -951,6 +951,10 @@
<include>**/plugin/alert/email/ExcelUtilsTest.java</include>
<include>**/plugin/alert/email/MailUtilsTest.java</include>
<include>**/plugin/alert/email/template/DefaultHTMLTemplateTest.java</include>
+ <include>**/plugin/alert/dingtalk/DingTalkSenderTest.java</include>
+ <include>**/plugin/alert/dingtalk/DingTalkAlertChannelFactoryTest.java</include>
+ <include>**/plugin/alert/wechat/WeChatSenderTest.java</include>
+ <include>**/plugin/alert/wechat/WeChatAlertChannelFactoryTest.java</include>
<include>**/spi/params/PluginParamsTransferTest.java</include>
<include>**/alert/plugin/EmailAlertPluginTest.java</include>
<include>**/alert/plugin/AlertPluginManagerTest.java</include>