You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@dolphinscheduler.apache.org by li...@apache.org on 2020/05/14 02:22:11 UTC
[incubator-dolphinscheduler] branch dev updated: support ali
nail(ding talk) , issue:2458 (#2594)
This is an automated email from the ASF dual-hosted git repository.
lidongdai pushed a commit to branch dev
in repository https://gitbox.apache.org/repos/asf/incubator-dolphinscheduler.git
The following commit(s) were added to refs/heads/dev by this push:
new de3a81c support ali nail(ding talk) , issue:2458 (#2594)
de3a81c is described below
commit de3a81cab5df8674db455381a0354290a11b5203
Author: xiaozhaoying <st...@126.com>
AuthorDate: Thu May 14 10:18:22 2020 +0800
support ali nail(ding talk) , issue:2458 (#2594)
* Create TextMessage.java
* Create DingTalkUtils.java
* Update alert.properties
* Update Constants.java
* Update Constants.java
* Create DingTalkMsgFormatter.java
* Update alert.properties
* Create DingTalkMsgFormatterTest.java
* Create DingTalkUtilsTest.java
* Update DingTalkUtils.java
* Create DingTalkManager.java
* Update EmailAlertPlugin.java
* feature: test send msg with proxy
* fix:delete comment and add exception info
* Update DingTalkUtilsTest.java
* Update DingTalkUtils.java
* Update DingTalkManager.java
* Update EmailAlertPlugin.java
* Update DingTalkUtilsTest.java
* Update DingTalkMsgFormatter.java
* Update DingTalkUtils.java
* Update DingTalkMsgFormatterTest.java
* Update DingTalkUtilsTest.java
* Update TextMessage.java
* Update DingTalkManager.java
* Delete TextMessage.java
* fix: add test case
* fix:add http client test case
* fix:delete ignore test case
* Update pom.xml
Co-authored-by: dailidong <da...@gmail.com>
---
.../alert/manager/DingTalkManager.java | 53 ++++++++
.../alert/plugin/EmailAlertPlugin.java | 8 ++
.../dolphinscheduler/alert/utils/Constants.java | 18 +++
.../alert/utils/DingTalkUtils.java | 136 +++++++++++++++++++++
.../src/main/resources/alert.properties | 11 ++
.../alert/utils/DingTalkUtilsTest.java | 125 +++++++++++++++++++
pom.xml | 1 +
7 files changed, 352 insertions(+)
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
new file mode 100644
index 0000000..6840794
--- /dev/null
+++ b/dolphinscheduler-alert/src/main/java/org/apache/dolphinscheduler/alert/manager/DingTalkManager.java
@@ -0,0 +1,53 @@
+/*
+ * 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.plugin.model.AlertInfo;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * 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/plugin/EmailAlertPlugin.java b/dolphinscheduler-alert/src/main/java/org/apache/dolphinscheduler/alert/plugin/EmailAlertPlugin.java
index d20306b..3ec6da3 100644
--- a/dolphinscheduler-alert/src/main/java/org/apache/dolphinscheduler/alert/plugin/EmailAlertPlugin.java
+++ b/dolphinscheduler-alert/src/main/java/org/apache/dolphinscheduler/alert/plugin/EmailAlertPlugin.java
@@ -16,9 +16,11 @@
*/
package org.apache.dolphinscheduler.alert.plugin;
+import org.apache.dolphinscheduler.alert.manager.DingTalkManager;
import org.apache.dolphinscheduler.alert.manager.EmailManager;
import org.apache.dolphinscheduler.alert.manager.EnterpriseWeChatManager;
import org.apache.dolphinscheduler.alert.utils.Constants;
+import org.apache.dolphinscheduler.alert.utils.DingTalkUtils;
import org.apache.dolphinscheduler.alert.utils.EnterpriseWeChatUtils;
import org.apache.dolphinscheduler.common.utils.CollectionUtils;
import org.apache.dolphinscheduler.common.utils.StringUtils;
@@ -44,6 +46,7 @@ public class EmailAlertPlugin implements AlertPlugin {
private static final EmailManager emailManager = new EmailManager();
private static final EnterpriseWeChatManager weChatManager = new EnterpriseWeChatManager();
+ private static final DingTalkManager dingTalkManager = new DingTalkManager();
public EmailAlertPlugin() {
this.pluginName = new PluginName();
@@ -121,6 +124,11 @@ public class EmailAlertPlugin implements AlertPlugin {
logger.error(e.getMessage(), e);
}
}
+
+ if (DingTalkUtils.isEnableDingTalk) {
+ logger.info("Ding Talk is enable.");
+ dingTalkManager.send(info);
+ }
} else {
retMaps.put(Constants.MESSAGE, "alert send error.");
diff --git a/dolphinscheduler-alert/src/main/java/org/apache/dolphinscheduler/alert/utils/Constants.java b/dolphinscheduler-alert/src/main/java/org/apache/dolphinscheduler/alert/utils/Constants.java
index 8fa38c6..e1b127b 100644
--- a/dolphinscheduler-alert/src/main/java/org/apache/dolphinscheduler/alert/utils/Constants.java
+++ b/dolphinscheduler-alert/src/main/java/org/apache/dolphinscheduler/alert/utils/Constants.java
@@ -156,6 +156,23 @@ public class Constants {
public static final String ENTERPRISE_WECHAT_AGENT_ID = "enterprise.wechat.agent.id";
public static final String ENTERPRISE_WECHAT_USERS = "enterprise.wechat.users";
+
+
+ public static final String DINGTALK_WEBHOOK = "dingtalk.webhook";
+
+ public static final String DINGTALK_KEYWORD = "dingtalk.keyword";
+
+ public static final String DINGTALK_PROXY_ENABLE = "dingtalk.isEnableProxy";
+
+ public static final String DINGTALK_PROXY = "dingtalk.proxy";
+
+ public static final String DINGTALK_PORT = "dingtalk.port";
+
+ public static final String DINGTALK_USER = "dingtalk.user";
+
+ public static final String DINGTALK_PASSWORD = "dingtalk.password";
+
+ public static final String DINGTALK_ENABLE = "dingtalk.isEnable";
/**
* plugin config
@@ -173,4 +190,5 @@ public class Constants {
public static final String PLUGIN_DEFAULT_EMAIL_RECEIVERCCS = "receiverCcs";
public static final String RETMAP_MSG = "msg";
+
}
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
new file mode 100644
index 0000000..f2c9cd8
--- /dev/null
+++ b/dolphinscheduler-alert/src/main/java/org/apache/dolphinscheduler/alert/utils/DingTalkUtils.java
@@ -0,0 +1,136 @@
+/*
+ * 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 com.alibaba.fastjson.JSON;
+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 org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * 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 JSON.toJSONString(items);
+
+ }
+
+}
diff --git a/dolphinscheduler-alert/src/main/resources/alert.properties b/dolphinscheduler-alert/src/main/resources/alert.properties
index 19b55fe..4e48e7d 100644
--- a/dolphinscheduler-alert/src/main/resources/alert.properties
+++ b/dolphinscheduler-alert/src/main/resources/alert.properties
@@ -36,6 +36,7 @@ mail.smtp.ssl.trust=xxx.xxx.com
# Enterprise WeChat configuration
enterprise.wechat.enable=false
+
#enterprise.wechat.corp.id=xxxxxxx
#enterprise.wechat.secret=xxxxxxx
#enterprise.wechat.agent.id=xxxxxxx
@@ -47,3 +48,13 @@ enterprise.wechat.enable=false
plugin.dir=/Users/xx/your/path/to/plugin/dir
+#ding talk configuration
+dingtalk.isEnable=flase
+dingtalk.webhook=https://oapi.dingtalk.com/robot/send?access_token=xxxxx
+dingtalk.keyword=
+dingtalk.proxy=
+dingtalk.port=80
+dingtalk.user=
+dingtalk.password=
+dingtalk.isEnableProxy=false
+
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
new file mode 100644
index 0000000..2149858
--- /dev/null
+++ b/dolphinscheduler-alert/src/test/java/org/apache/dolphinscheduler/alert/utils/DingTalkUtilsTest.java
@@ -0,0 +1,125 @@
+/*
+ * 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 com.alibaba.fastjson.JSON;
+import org.apache.http.client.config.RequestConfig;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Ignore;
+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;
+
+import java.io.IOException;
+
+import static org.junit.Assert.*;
+
+@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
+// @Ignore
+// public void testSendMsg() {
+// try {
+// String msgTosend = "msg to send";
+// logger.info(PropertyUtils.getString(Constants.DINGTALK_WEBHOOK));
+// String rsp = DingTalkUtils.sendDingTalkMsg(msgTosend, Constants.UTF_8);
+// logger.info("send msg result:{}",rsp);
+// String errmsg = JSON.parseObject(rsp).getString("errmsg");
+// Assert.assertEquals("ok", errmsg);
+// } catch (Exception e) {
+// e.printStackTrace();
+// }
+// }
+
+ @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/pom.xml b/pom.xml
index 7e291d2..4883598 100644
--- a/pom.xml
+++ b/pom.xml
@@ -687,6 +687,7 @@
<version>${maven-surefire-plugin.version}</version>
<configuration>
<includes>
+ <include>**/alert/utils/DingTalkUtilsTest.java</include>
<include>**/alert/template/AlertTemplateFactoryTest.java</include>
<include>**/alert/template/impl/DefaultHTMLTemplateTest.java</include>
<include>**/alert/utils/EnterpriseWeChatUtilsTest.java</include>