merge from dev
commit
49204a6b13
4
LICENSE
4
LICENSE
|
|
@ -216,3 +216,7 @@ The text of each license is the standard Apache 2.0 license.
|
|||
ScriptRunner from https://github.com/mybatis/mybatis-3 Apache 2.0
|
||||
mvnw files from https://github.com/takari/maven-wrapper Apache 2.0
|
||||
PropertyPlaceholderHelper from https://github.com/spring-projects/spring-framework Apache 2.0
|
||||
DolphinPluginClassLoader from https://github.com/prestosql/presto Apache 2.0
|
||||
DolphinPluginDiscovery from https://github.com/prestosql/presto Apache 2.0
|
||||
DolphinPluginLoader from https://github.com/prestosql/presto Apache 2.0
|
||||
|
||||
|
|
|
|||
2
NOTICE
2
NOTICE
|
|
@ -1,5 +1,5 @@
|
|||
Apache DolphinScheduler (incubating)
|
||||
Copyright 2019-2020 The Apache Software Foundation
|
||||
Copyright 2019-2021 The Apache Software Foundation
|
||||
|
||||
This product includes software developed at
|
||||
The Apache Software Foundation (http://www.apache.org/).
|
||||
|
|
|
|||
|
|
@ -0,0 +1,25 @@
|
|||
#
|
||||
# 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.
|
||||
#
|
||||
dependencies:
|
||||
- name: postgresql
|
||||
version: 8.x.x
|
||||
repository: https://charts.bitnami.com/bitnami
|
||||
condition: postgresql.enabled
|
||||
- name: zookeeper
|
||||
version: 5.x.x
|
||||
repository: https://charts.bitnami.com/bitnami
|
||||
condition: redis.enabled
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
#
|
||||
# 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.
|
||||
#
|
||||
dependencies:
|
||||
- name: postgresql
|
||||
version: 8.x.x
|
||||
repository: https://charts.bitnami.com/bitnami
|
||||
condition: postgresql.enabled
|
||||
- name: zookeeper
|
||||
version: 5.x.x
|
||||
repository: https://charts.bitnami.com/bitnami
|
||||
condition: redis.enabled
|
||||
|
|
@ -0,0 +1,82 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
~ 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.
|
||||
-->
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>dolphinscheduler-alert-plugin</artifactId>
|
||||
<groupId>org.apache.dolphinscheduler</groupId>
|
||||
<version>1.3.4-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>org.apache.dolphinscheduler</groupId>
|
||||
<artifactId>dolphinscheduler-alert-dingtalk</artifactId>
|
||||
<packaging>dolphinscheduler-plugin</packaging>
|
||||
|
||||
<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>
|
||||
|
||||
<build>
|
||||
<finalName>dolphinscheduler-alert-dingtalk-${project.version}</finalName>
|
||||
</build>
|
||||
|
||||
</project>
|
||||
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
|
@ -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 "DingTalk";
|
||||
}
|
||||
|
||||
@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(false)
|
||||
.build())
|
||||
.build();
|
||||
InputParam proxyParam =
|
||||
InputParam.newBuilder(DingTalkParamsConstants.NAME_DING_TALK_PROXY, DingTalkParamsConstants.DING_TALK_PROXY)
|
||||
.addValidate(Validate.newBuilder()
|
||||
.setRequired(false).build())
|
||||
.build();
|
||||
|
||||
InputParam portParam = InputParam.newBuilder(DingTalkParamsConstants.NAME_DING_TALK_PORT, DingTalkParamsConstants.DING_TALK_PORT)
|
||||
.addValidate(Validate.newBuilder()
|
||||
.setRequired(false).build())
|
||||
.build();
|
||||
|
||||
InputParam userParam =
|
||||
InputParam.newBuilder(DingTalkParamsConstants.NAME_DING_TALK_USER, DingTalkParamsConstants.DING_TALK_USER)
|
||||
.addValidate(Validate.newBuilder()
|
||||
.setRequired(false).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();
|
||||
}
|
||||
}
|
||||
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
||||
/**
|
||||
* DingTalkParamsConstants
|
||||
*/
|
||||
public class DingTalkParamsConstants {
|
||||
|
||||
public DingTalkParamsConstants() {
|
||||
throw new IllegalStateException("Utility class");
|
||||
}
|
||||
|
||||
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";
|
||||
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,128 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
~ 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.
|
||||
-->
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>dolphinscheduler-alert-plugin</artifactId>
|
||||
<groupId>org.apache.dolphinscheduler</groupId>
|
||||
<version>1.3.4-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>org.apache.dolphinscheduler</groupId>
|
||||
<artifactId>dolphinscheduler-alert-email</artifactId>
|
||||
<!-- can be load as a Alert Plugin when development and run server in IDE -->
|
||||
<packaging>dolphinscheduler-plugin</packaging>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.apache.dolphinscheduler</groupId>
|
||||
<artifactId>dolphinscheduler-spi</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-annotations</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-collections4</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.poi</groupId>
|
||||
<artifactId>poi</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>org.apache.commons</groupId>
|
||||
<artifactId>commons-email</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-annotations</artifactId>
|
||||
<scope>provided</scope>
|
||||
</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>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.powermock</groupId>
|
||||
<artifactId>powermock-module-junit4</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.powermock</groupId>
|
||||
<artifactId>powermock-api-mockito2</artifactId>
|
||||
<scope>test</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-core</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<finalName>dolphinscheduler-alert-email-${project.version}</finalName>
|
||||
</build>
|
||||
|
||||
</project>
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
* 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.email;
|
||||
|
||||
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;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* email alert channel . use email to seed the alertInfo
|
||||
*/
|
||||
public class EmailAlertChannel implements AlertChannel {
|
||||
private static final Logger logger = LoggerFactory.getLogger(EmailAlertChannel.class);
|
||||
|
||||
@Override
|
||||
public AlertResult process(AlertInfo info) {
|
||||
|
||||
AlertData alert = info.getAlertData();
|
||||
String alertParams = info.getAlertParams();
|
||||
Map<String, String> paramsMap = PluginParamsTransfer.getPluginParamsMap(alertParams);
|
||||
MailSender mailSender = new MailSender(paramsMap);
|
||||
AlertResult alertResult = mailSender.sendMails(alert.getTitle(), alert.getContent());
|
||||
|
||||
//send flag
|
||||
boolean flag = false;
|
||||
|
||||
if (alertResult == null) {
|
||||
alertResult = new AlertResult();
|
||||
alertResult.setStatus("false");
|
||||
alertResult.setMessage("alert send error.");
|
||||
logger.info("alert send error : {}", alertResult.getMessage());
|
||||
return alertResult;
|
||||
}
|
||||
|
||||
flag = Boolean.parseBoolean(String.valueOf(alertResult.getStatus()));
|
||||
|
||||
if (flag) {
|
||||
logger.info("alert send success");
|
||||
alertResult.setMessage("email send success.");
|
||||
} else {
|
||||
alertResult.setMessage("alert send error.");
|
||||
logger.info("alert send error : {}", alertResult.getMessage());
|
||||
}
|
||||
|
||||
return alertResult;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,137 @@
|
|||
/*
|
||||
* 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.email;
|
||||
|
||||
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.PasswordParam;
|
||||
import org.apache.dolphinscheduler.spi.params.RadioParam;
|
||||
import org.apache.dolphinscheduler.spi.params.base.DataType;
|
||||
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.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* email alert factory
|
||||
*/
|
||||
public class EmailAlertChannelFactory implements AlertChannelFactory {
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Email";
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<PluginParams> getParams() {
|
||||
|
||||
List<PluginParams> paramsList = new ArrayList<>();
|
||||
InputParam receivesParam = InputParam.newBuilder(MailParamsConstants.NAME_PLUGIN_DEFAULT_EMAIL_RECEIVERS, MailParamsConstants.PLUGIN_DEFAULT_EMAIL_RECEIVERS)
|
||||
.setPlaceholder("please input receives")
|
||||
.addValidate(Validate.newBuilder()
|
||||
.setRequired(true)
|
||||
.build())
|
||||
.build();
|
||||
|
||||
InputParam receiveCcsParam = InputParam.newBuilder(MailParamsConstants.NAME_PLUGIN_DEFAULT_EMAIL_RECEIVERCCS, MailParamsConstants.PLUGIN_DEFAULT_EMAIL_RECEIVERCCS)
|
||||
.build();
|
||||
|
||||
InputParam mailSmtpHost = InputParam.newBuilder(MailParamsConstants.NAME_MAIL_SMTP_HOST, MailParamsConstants.MAIL_SMTP_HOST)
|
||||
.addValidate(Validate.newBuilder().setRequired(true).build())
|
||||
.build();
|
||||
|
||||
InputParam mailSmtpPort = InputParam.newBuilder(MailParamsConstants.NAME_MAIL_SMTP_PORT, MailParamsConstants.MAIL_SMTP_PORT)
|
||||
.setValue(25)
|
||||
.addValidate(Validate.newBuilder()
|
||||
.setRequired(true)
|
||||
.setType(DataType.NUMBER.getDataType())
|
||||
.build())
|
||||
.build();
|
||||
|
||||
InputParam mailSender = InputParam.newBuilder(MailParamsConstants.NAME_MAIL_SENDER, MailParamsConstants.MAIL_SENDER)
|
||||
.addValidate(Validate.newBuilder().setRequired(true).build())
|
||||
.build();
|
||||
|
||||
RadioParam enableSmtpAuth = RadioParam.newBuilder(MailParamsConstants.NAME_MAIL_SMTP_AUTH, MailParamsConstants.MAIL_SMTP_AUTH)
|
||||
.addParamsOptions(new ParamsOptions("YES", true, false))
|
||||
.addParamsOptions(new ParamsOptions("NO", false, false))
|
||||
.setValue(true)
|
||||
.addValidate(Validate.newBuilder().setRequired(true).build())
|
||||
.build();
|
||||
|
||||
InputParam mailUser = InputParam.newBuilder(MailParamsConstants.NAME_MAIL_USER, MailParamsConstants.MAIL_USER)
|
||||
.setPlaceholder("if enable use authentication, you need input user")
|
||||
.build();
|
||||
|
||||
PasswordParam mailPassword = PasswordParam.newBuilder(MailParamsConstants.NAME_MAIL_PASSWD, MailParamsConstants.MAIL_PASSWD)
|
||||
.setPlaceholder("if enable use authentication, you need input password")
|
||||
.build();
|
||||
|
||||
RadioParam enableTls = RadioParam.newBuilder(MailParamsConstants.NAME_MAIL_SMTP_STARTTLS_ENABLE, MailParamsConstants.MAIL_SMTP_STARTTLS_ENABLE)
|
||||
.addParamsOptions(new ParamsOptions("YES", true, false))
|
||||
.addParamsOptions(new ParamsOptions("NO", false, false))
|
||||
.setValue(false)
|
||||
.addValidate(Validate.newBuilder().setRequired(true).build())
|
||||
.build();
|
||||
|
||||
RadioParam enableSsl = RadioParam.newBuilder(MailParamsConstants.NAME_MAIL_SMTP_SSL_ENABLE, MailParamsConstants.MAIL_SMTP_SSL_ENABLE)
|
||||
.addParamsOptions(new ParamsOptions("YES", true, false))
|
||||
.addParamsOptions(new ParamsOptions("NO", false, false))
|
||||
.setValue(false)
|
||||
.addValidate(Validate.newBuilder().setRequired(true).build())
|
||||
.build();
|
||||
|
||||
InputParam sslTrust = InputParam.newBuilder(MailParamsConstants.NAME_MAIL_SMTP_SSL_TRUST, MailParamsConstants.MAIL_SMTP_SSL_TRUST)
|
||||
.setValue("*")
|
||||
.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))
|
||||
.addParamsOptions(new ParamsOptions(ShowType.ATTACHMENT.getDescp(), ShowType.ATTACHMENT.getDescp(), false))
|
||||
.addParamsOptions(new ParamsOptions(ShowType.TABLEATTACHMENT.getDescp(), ShowType.TABLEATTACHMENT.getDescp(), false))
|
||||
.setValue(ShowType.TABLE.getDescp())
|
||||
.addValidate(Validate.newBuilder().setRequired(true).build())
|
||||
.build();
|
||||
|
||||
paramsList.add(receivesParam);
|
||||
paramsList.add(receiveCcsParam);
|
||||
paramsList.add(mailSmtpHost);
|
||||
paramsList.add(mailSmtpPort);
|
||||
paramsList.add(mailSender);
|
||||
paramsList.add(enableSmtpAuth);
|
||||
paramsList.add(mailUser);
|
||||
paramsList.add(mailPassword);
|
||||
paramsList.add(enableTls);
|
||||
paramsList.add(enableSsl);
|
||||
paramsList.add(sslTrust);
|
||||
paramsList.add(showType);
|
||||
|
||||
return paramsList;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AlertChannel create() {
|
||||
return new EmailAlertChannel();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* 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.email;
|
||||
|
||||
import org.apache.dolphinscheduler.spi.DolphinSchedulerPlugin;
|
||||
import org.apache.dolphinscheduler.spi.alert.AlertChannelFactory;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
/**
|
||||
* email alert plugin
|
||||
*/
|
||||
public class EmailAlertPlugin implements DolphinSchedulerPlugin {
|
||||
@Override
|
||||
public Iterable<AlertChannelFactory> getAlertChannelFactorys() {
|
||||
return ImmutableList.of(new EmailAlertChannelFactory());
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,75 @@
|
|||
/*
|
||||
* 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.email;
|
||||
|
||||
public class EmailConstants {
|
||||
|
||||
|
||||
public static final String XLS_FILE_PATH = "xls.file.path";
|
||||
|
||||
public static final String MAIL_TRANSPORT_PROTOCOL = "mail.transport.protocol";
|
||||
|
||||
public static final String DEFAULT_SMTP_PORT = "25";
|
||||
|
||||
public static final String TEXT_HTML_CHARSET_UTF_8 = "text/html;charset=utf-8";
|
||||
|
||||
public static final int NUMBER_1000 = 1000;
|
||||
|
||||
public static final String TR = "<tr>";
|
||||
|
||||
public static final String TD = "<td>";
|
||||
|
||||
public static final String TD_END = "</td>";
|
||||
|
||||
public static final String TR_END = "</tr>";
|
||||
|
||||
public static final String TITLE = "title";
|
||||
|
||||
public static final String CONTENT = "content";
|
||||
|
||||
public static final String TH = "<th>";
|
||||
|
||||
public static final String TH_END = "</th>";
|
||||
|
||||
public static final String MARKDOWN_QUOTE = ">";
|
||||
|
||||
public static final String MARKDOWN_ENTER = "\n";
|
||||
|
||||
public static final String HTML_HEADER_PREFIX = new StringBuilder("<!DOCTYPE HTML PUBLIC '-//W3C//DTD HTML 4.01 Transitional//EN' 'http://www.w3.org/TR/html4/loose.dtd'>")
|
||||
.append("<html>")
|
||||
.append("<head>")
|
||||
.append("<title>dolphinscheduler</title>")
|
||||
.append("<meta name='Keywords' content=''>")
|
||||
.append("<meta name='Description' content=''>")
|
||||
.append("<style type=\"text/css\">")
|
||||
.append("table {margin-top:0px;padding-top:0px;border:1px solid;font-size: 14px;color: #333333;border-width: 1px;border-color: #666666;border-collapse: collapse;}")
|
||||
.append("table th {border-width: 1px;padding: 8px;border-style: solid;border-color: #666666;background-color: #dedede;text-align: left;}")
|
||||
.append("table td {border-width: 1px;padding: 8px;border-style: solid;border-color: #666666;background-color: #ffffff;text-align: left;}")
|
||||
.append("</style>")
|
||||
.append("</head>")
|
||||
.append("<body style=\"margin:0;padding:0\"><table border=\"1px\" cellpadding=\"5px\" cellspacing=\"-10px\"> ")
|
||||
.toString();
|
||||
|
||||
public static final String TABLE_BODY_HTML_TAIL = "</table></body></html>";
|
||||
|
||||
public static final String UTF_8 = "UTF-8";
|
||||
|
||||
public static final String EXCEL_SUFFIX_XLS = ".xls";
|
||||
|
||||
public static final String SINGLE_SLASH = "/";
|
||||
}
|
||||
|
|
@ -15,11 +15,11 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.apache.dolphinscheduler.alert.utils;
|
||||
package org.apache.dolphinscheduler.plugin.alert.email;
|
||||
|
||||
import org.apache.dolphinscheduler.common.utils.CollectionUtils;
|
||||
import org.apache.dolphinscheduler.common.utils.JSONUtils;
|
||||
import org.apache.dolphinscheduler.spi.utils.JSONUtils;
|
||||
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.apache.poi.hssf.usermodel.HSSFCell;
|
||||
import org.apache.poi.hssf.usermodel.HSSFRow;
|
||||
import org.apache.poi.hssf.usermodel.HSSFSheet;
|
||||
|
|
@ -31,6 +31,7 @@ import java.io.File;
|
|||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
|
@ -43,12 +44,12 @@ import org.slf4j.LoggerFactory;
|
|||
*/
|
||||
public class ExcelUtils {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(ExcelUtils.class);
|
||||
|
||||
private ExcelUtils() {
|
||||
throw new IllegalStateException(ExcelUtils.class.getName());
|
||||
public ExcelUtils() {
|
||||
throw new IllegalStateException("Utility class");
|
||||
}
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(ExcelUtils.class);
|
||||
|
||||
/**
|
||||
* generate excel file
|
||||
*
|
||||
|
|
@ -71,7 +72,9 @@ public class ExcelUtils {
|
|||
|
||||
List<String> headerList = new ArrayList<>();
|
||||
|
||||
for (Map.Entry<String, Object> en : headerMap.entrySet()) {
|
||||
Iterator<Map.Entry<String, Object>> iter = headerMap.entrySet().iterator();
|
||||
while (iter.hasNext()) {
|
||||
Map.Entry<String, Object> en = iter.next();
|
||||
headerList.add(en.getKey());
|
||||
}
|
||||
|
||||
|
|
@ -122,11 +125,12 @@ public class ExcelUtils {
|
|||
}
|
||||
|
||||
//setting file output
|
||||
fos = new FileOutputStream(xlsFilePath + Constants.SINGLE_SLASH + title + Constants.EXCEL_SUFFIX_XLS);
|
||||
fos = new FileOutputStream(xlsFilePath + EmailConstants.SINGLE_SLASH + title + EmailConstants.EXCEL_SUFFIX_XLS);
|
||||
|
||||
wb.write(fos);
|
||||
|
||||
} catch (Exception e) {
|
||||
logger.error("generate excel error", e);
|
||||
throw new RuntimeException("generate excel error", e);
|
||||
} finally {
|
||||
if (wb != null) {
|
||||
|
|
@ -146,4 +150,4 @@ public class ExcelUtils {
|
|||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
* 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.email;
|
||||
|
||||
/**
|
||||
* mail plugin params json use
|
||||
*/
|
||||
public class MailParamsConstants {
|
||||
|
||||
public MailParamsConstants() {
|
||||
throw new IllegalStateException("Utility class");
|
||||
}
|
||||
|
||||
public static final String PLUGIN_DEFAULT_EMAIL_RECEIVERS = "$t('receivers')";
|
||||
public static final String NAME_PLUGIN_DEFAULT_EMAIL_RECEIVERS = "receivers";
|
||||
|
||||
public static final String PLUGIN_DEFAULT_EMAIL_RECEIVERCCS = "$t('receiverCcs')";
|
||||
public static final String NAME_PLUGIN_DEFAULT_EMAIL_RECEIVERCCS = "receiverCcs";
|
||||
|
||||
public static final String MAIL_PROTOCOL = "transport.protocol";
|
||||
public static final String NAME_MAIL_PROTOCOL = "protocol";
|
||||
|
||||
public static final String MAIL_SMTP_HOST = "smtp.host";
|
||||
public static final String NAME_MAIL_SMTP_HOST = "serverHost";
|
||||
|
||||
public static final String MAIL_SMTP_PORT = "smtp.port";
|
||||
public static final String NAME_MAIL_SMTP_PORT = "serverPort";
|
||||
|
||||
public static final String MAIL_SENDER = "sender";
|
||||
public static final String NAME_MAIL_SENDER = "sender";
|
||||
|
||||
public static final String MAIL_SMTP_AUTH = "smtp.auth";
|
||||
public static final String NAME_MAIL_SMTP_AUTH = "enableSmtpAuth";
|
||||
|
||||
public static final String MAIL_USER = "user";
|
||||
public static final String NAME_MAIL_USER = "user";
|
||||
|
||||
public static final String MAIL_PASSWD = "passwd";
|
||||
public static final String NAME_MAIL_PASSWD = "passwd";
|
||||
|
||||
public static final String MAIL_SMTP_STARTTLS_ENABLE = "smtp.starttls.enable";
|
||||
public static final String NAME_MAIL_SMTP_STARTTLS_ENABLE = "starttlsEnable";
|
||||
|
||||
public static final String MAIL_SMTP_SSL_ENABLE = "smtp.ssl.enable";
|
||||
public static final String NAME_MAIL_SMTP_SSL_ENABLE = "sslEnable";
|
||||
|
||||
public static final String MAIL_SMTP_SSL_TRUST = "smtp.ssl.trust";
|
||||
public static final String NAME_MAIL_SMTP_SSL_TRUST = "smtpSslTrust";
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,429 @@
|
|||
/*
|
||||
* 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.email;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
import org.apache.dolphinscheduler.plugin.alert.email.template.AlertTemplate;
|
||||
import org.apache.dolphinscheduler.plugin.alert.email.template.DefaultHTMLTemplate;
|
||||
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.StringUtils;
|
||||
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.apache.commons.mail.EmailException;
|
||||
import org.apache.commons.mail.HtmlEmail;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
import javax.mail.Authenticator;
|
||||
import javax.mail.Message;
|
||||
import javax.mail.MessagingException;
|
||||
import javax.mail.PasswordAuthentication;
|
||||
import javax.mail.Session;
|
||||
import javax.mail.Transport;
|
||||
import javax.mail.internet.InternetAddress;
|
||||
import javax.mail.internet.MimeBodyPart;
|
||||
import javax.mail.internet.MimeMessage;
|
||||
import javax.mail.internet.MimeMultipart;
|
||||
import javax.mail.internet.MimeUtility;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.sun.mail.smtp.SMTPProvider;
|
||||
|
||||
/**
|
||||
* mail utils
|
||||
*/
|
||||
public class MailSender {
|
||||
|
||||
public static final Logger logger = LoggerFactory.getLogger(MailSender.class);
|
||||
|
||||
private List<String> receivers;
|
||||
private List<String> receiverCcs;
|
||||
private String mailProtocol = "SMTP";
|
||||
private String mailSmtpHost;
|
||||
private String mailSmtpPort;
|
||||
private String mailSender;
|
||||
private String enableSmtpAuth;
|
||||
private String mailUser;
|
||||
private String mailPasswd;
|
||||
private String mailUseStartTLS;
|
||||
private String mailUseSSL;
|
||||
private String xlsFilePath;
|
||||
private String sslTrust;
|
||||
private String showType;
|
||||
private AlertTemplate alertTemplate;
|
||||
|
||||
public MailSender(Map<String, String> config) {
|
||||
|
||||
String receiversConfig = config.get(MailParamsConstants.NAME_PLUGIN_DEFAULT_EMAIL_RECEIVERS);
|
||||
if (receiversConfig == null || "".equals(receiversConfig)) {
|
||||
throw new RuntimeException(MailParamsConstants.PLUGIN_DEFAULT_EMAIL_RECEIVERS + "must not be null");
|
||||
}
|
||||
|
||||
receivers = Arrays.asList(receiversConfig.split(","));
|
||||
|
||||
String receiverCcsConfig = config.get(MailParamsConstants.NAME_PLUGIN_DEFAULT_EMAIL_RECEIVERCCS);
|
||||
|
||||
receiverCcs = new ArrayList<>();
|
||||
if (receiverCcsConfig != null && !"".equals(receiverCcsConfig)) {
|
||||
receiverCcs = Arrays.asList(receiverCcsConfig.split(","));
|
||||
}
|
||||
|
||||
mailSmtpHost = config.get(MailParamsConstants.NAME_MAIL_SMTP_HOST);
|
||||
requireNonNull(mailSmtpHost, MailParamsConstants.MAIL_SMTP_HOST + " must not null");
|
||||
|
||||
mailSmtpPort = config.get(MailParamsConstants.NAME_MAIL_SMTP_PORT);
|
||||
requireNonNull(mailSmtpPort, MailParamsConstants.MAIL_SMTP_PORT + " must not null");
|
||||
|
||||
mailSender = config.get(MailParamsConstants.NAME_MAIL_SENDER);
|
||||
requireNonNull(mailSender, MailParamsConstants.MAIL_SENDER + " must not null");
|
||||
|
||||
enableSmtpAuth = config.get(MailParamsConstants.NAME_MAIL_SMTP_AUTH);
|
||||
|
||||
mailUser = config.get(MailParamsConstants.NAME_MAIL_USER);
|
||||
requireNonNull(mailUser, MailParamsConstants.MAIL_USER + " must not null");
|
||||
|
||||
mailPasswd = config.get(MailParamsConstants.NAME_MAIL_PASSWD);
|
||||
requireNonNull(mailPasswd, MailParamsConstants.MAIL_PASSWD + " must not null");
|
||||
|
||||
mailUseStartTLS = config.get(MailParamsConstants.NAME_MAIL_SMTP_STARTTLS_ENABLE);
|
||||
requireNonNull(mailUseStartTLS, MailParamsConstants.MAIL_SMTP_STARTTLS_ENABLE + " must not null");
|
||||
|
||||
mailUseSSL = config.get(MailParamsConstants.NAME_MAIL_SMTP_SSL_ENABLE);
|
||||
requireNonNull(mailUseSSL, MailParamsConstants.MAIL_SMTP_SSL_ENABLE + " must not null");
|
||||
|
||||
sslTrust = config.get(MailParamsConstants.NAME_MAIL_SMTP_SSL_TRUST);
|
||||
requireNonNull(sslTrust, MailParamsConstants.MAIL_SMTP_SSL_TRUST + " must not null");
|
||||
|
||||
showType = config.get(AlertConstants.SHOW_TYPE);
|
||||
requireNonNull(showType, AlertConstants.SHOW_TYPE + " must not null");
|
||||
|
||||
xlsFilePath = config.get(EmailConstants.XLS_FILE_PATH);
|
||||
if (StringUtils.isBlank(xlsFilePath)) {
|
||||
xlsFilePath = "/tmp/xls";
|
||||
}
|
||||
|
||||
alertTemplate = new DefaultHTMLTemplate();
|
||||
}
|
||||
|
||||
/**
|
||||
* send mail to receivers
|
||||
*
|
||||
* @param title title
|
||||
* @param content content
|
||||
* @return
|
||||
*/
|
||||
public AlertResult sendMails(String title, String content) {
|
||||
return sendMails(this.receivers, this.receiverCcs, title, content);
|
||||
}
|
||||
|
||||
/**
|
||||
* send mail to receivers
|
||||
*
|
||||
* @param title email title
|
||||
* @param content email content
|
||||
* @return
|
||||
*/
|
||||
public AlertResult sendMailsToReceiverOnly(String title, String content) {
|
||||
return sendMails(this.receivers, null, title, content);
|
||||
}
|
||||
|
||||
/**
|
||||
* send mail
|
||||
*
|
||||
* @param receivers receivers
|
||||
* @param receiverCcs receiverCcs
|
||||
* @param title title
|
||||
* @param content content
|
||||
* @return
|
||||
*/
|
||||
public AlertResult sendMails(List<String> receivers, List<String> receiverCcs, String title, String content) {
|
||||
AlertResult alertResult = new AlertResult();
|
||||
alertResult.setStatus("false");
|
||||
|
||||
// if there is no receivers && no receiversCc, no need to process
|
||||
if (CollectionUtils.isEmpty(receivers) && CollectionUtils.isEmpty(receiverCcs)) {
|
||||
return alertResult;
|
||||
}
|
||||
|
||||
receivers.removeIf(StringUtils::isEmpty);
|
||||
|
||||
if (showType.equals(ShowType.TABLE.getDescp()) || showType.equals(ShowType.TEXT.getDescp())) {
|
||||
// send email
|
||||
HtmlEmail email = new HtmlEmail();
|
||||
|
||||
try {
|
||||
Session session = getSession();
|
||||
email.setMailSession(session);
|
||||
email.setFrom(mailSender);
|
||||
email.setCharset(EmailConstants.UTF_8);
|
||||
if (CollectionUtils.isNotEmpty(receivers)) {
|
||||
// receivers mail
|
||||
for (String receiver : receivers) {
|
||||
email.addTo(receiver);
|
||||
}
|
||||
}
|
||||
|
||||
if (CollectionUtils.isNotEmpty(receiverCcs)) {
|
||||
//cc
|
||||
for (String receiverCc : receiverCcs) {
|
||||
email.addCc(receiverCc);
|
||||
}
|
||||
}
|
||||
// sender mail
|
||||
return getStringObjectMap(title, content, alertResult, email);
|
||||
} catch (Exception e) {
|
||||
handleException(alertResult, e);
|
||||
}
|
||||
} else if (showType.equals(ShowType.ATTACHMENT.getDescp()) || showType.equals(ShowType.TABLEATTACHMENT.getDescp())) {
|
||||
try {
|
||||
|
||||
String partContent = (showType.equals(ShowType.ATTACHMENT.getDescp()) ? "Please see the attachment " + title + EmailConstants.EXCEL_SUFFIX_XLS : htmlTable(content, false));
|
||||
|
||||
attachment(title, content, partContent);
|
||||
|
||||
alertResult.setStatus("true");
|
||||
return alertResult;
|
||||
} catch (Exception e) {
|
||||
handleException(alertResult, e);
|
||||
return alertResult;
|
||||
}
|
||||
}
|
||||
return alertResult;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* html table content
|
||||
*
|
||||
* @param content the content
|
||||
* @param showAll if show the whole content
|
||||
* @return the html table form
|
||||
*/
|
||||
private String htmlTable(String content, boolean showAll) {
|
||||
return alertTemplate.getMessageFromTemplate(content, ShowType.TABLE, showAll);
|
||||
}
|
||||
|
||||
/**
|
||||
* html table content
|
||||
*
|
||||
* @param content the content
|
||||
* @return the html table form
|
||||
*/
|
||||
private String htmlTable(String content) {
|
||||
return htmlTable(content, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* html text content
|
||||
*
|
||||
* @param content the content
|
||||
* @return text in html form
|
||||
*/
|
||||
private String htmlText(String content) {
|
||||
return alertTemplate.getMessageFromTemplate(content, ShowType.TEXT);
|
||||
}
|
||||
|
||||
/**
|
||||
* send mail as Excel attachment
|
||||
*
|
||||
* @param title
|
||||
* @param content
|
||||
* @param partContent
|
||||
* @throws Exception
|
||||
*/
|
||||
private void attachment(String title, String content, String partContent) throws Exception {
|
||||
MimeMessage msg = getMimeMessage();
|
||||
|
||||
attachContent(title, content, partContent, msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* get MimeMessage
|
||||
*
|
||||
* @return
|
||||
* @throws MessagingException
|
||||
*/
|
||||
private MimeMessage getMimeMessage() throws MessagingException {
|
||||
|
||||
// 1. The first step in creating mail: creating session
|
||||
Session session = getSession();
|
||||
// Setting debug mode, can be turned off
|
||||
session.setDebug(false);
|
||||
|
||||
// 2. creating mail: Creating a MimeMessage
|
||||
MimeMessage msg = new MimeMessage(session);
|
||||
// 3. set sender
|
||||
msg.setFrom(new InternetAddress(mailSender));
|
||||
// 4. set receivers
|
||||
for (String receiver : receivers) {
|
||||
msg.addRecipients(Message.RecipientType.TO, InternetAddress.parse(receiver));
|
||||
}
|
||||
return msg;
|
||||
}
|
||||
|
||||
/**
|
||||
* get session
|
||||
*
|
||||
* @return the new Session
|
||||
*/
|
||||
private Session getSession() {
|
||||
Properties props = new Properties();
|
||||
props.setProperty(MailParamsConstants.MAIL_SMTP_HOST, mailSmtpHost);
|
||||
props.setProperty(MailParamsConstants.MAIL_SMTP_PORT, mailSmtpPort);
|
||||
props.setProperty(MailParamsConstants.MAIL_SMTP_AUTH, enableSmtpAuth);
|
||||
props.setProperty(EmailConstants.MAIL_TRANSPORT_PROTOCOL, mailProtocol);
|
||||
props.setProperty(MailParamsConstants.MAIL_SMTP_STARTTLS_ENABLE, mailUseStartTLS);
|
||||
props.setProperty(MailParamsConstants.MAIL_SMTP_SSL_ENABLE, mailUseSSL);
|
||||
props.setProperty(MailParamsConstants.MAIL_SMTP_SSL_TRUST, sslTrust);
|
||||
|
||||
Authenticator auth = new Authenticator() {
|
||||
@Override
|
||||
protected PasswordAuthentication getPasswordAuthentication() {
|
||||
// mail username and password
|
||||
return new PasswordAuthentication(mailUser, mailPasswd);
|
||||
}
|
||||
};
|
||||
|
||||
Session session = Session.getInstance(props, auth);
|
||||
session.addProvider(new SMTPProvider());
|
||||
return session;
|
||||
}
|
||||
|
||||
/**
|
||||
* attach content
|
||||
*
|
||||
* @param title
|
||||
* @param content
|
||||
* @param partContent
|
||||
* @param msg
|
||||
* @throws MessagingException
|
||||
* @throws IOException
|
||||
*/
|
||||
private void attachContent(String title, String content, String partContent, MimeMessage msg) throws MessagingException, IOException {
|
||||
/**
|
||||
* set receiverCc
|
||||
*/
|
||||
if (CollectionUtils.isNotEmpty(receiverCcs)) {
|
||||
for (String receiverCc : receiverCcs) {
|
||||
msg.addRecipients(Message.RecipientType.CC, InternetAddress.parse(receiverCc));
|
||||
}
|
||||
}
|
||||
|
||||
// set subject
|
||||
msg.setSubject(title);
|
||||
MimeMultipart partList = new MimeMultipart();
|
||||
// set signature
|
||||
MimeBodyPart part1 = new MimeBodyPart();
|
||||
part1.setContent(partContent, EmailConstants.TEXT_HTML_CHARSET_UTF_8);
|
||||
// set attach file
|
||||
MimeBodyPart part2 = new MimeBodyPart();
|
||||
File file = new File(xlsFilePath + EmailConstants.SINGLE_SLASH + title + EmailConstants.EXCEL_SUFFIX_XLS);
|
||||
if (!file.getParentFile().exists()) {
|
||||
file.getParentFile().mkdirs();
|
||||
}
|
||||
// make excel file
|
||||
|
||||
ExcelUtils.genExcelFile(content, title, xlsFilePath);
|
||||
|
||||
part2.attachFile(file);
|
||||
part2.setFileName(MimeUtility.encodeText(title + EmailConstants.EXCEL_SUFFIX_XLS, EmailConstants.UTF_8, "B"));
|
||||
// add components to collection
|
||||
partList.addBodyPart(part1);
|
||||
partList.addBodyPart(part2);
|
||||
msg.setContent(partList);
|
||||
// 5. send Transport
|
||||
Transport.send(msg);
|
||||
// 6. delete saved file
|
||||
deleteFile(file);
|
||||
}
|
||||
|
||||
/**
|
||||
* the string object map
|
||||
*
|
||||
* @param title
|
||||
* @param content
|
||||
* @param alertResult
|
||||
* @param email
|
||||
* @return
|
||||
* @throws EmailException
|
||||
*/
|
||||
private AlertResult getStringObjectMap(String title, String content, AlertResult alertResult, HtmlEmail email) throws EmailException {
|
||||
|
||||
/**
|
||||
* the subject of the message to be sent
|
||||
*/
|
||||
email.setSubject(title);
|
||||
/**
|
||||
* to send information, you can use HTML tags in mail content because of the use of HtmlEmail
|
||||
*/
|
||||
if (showType.equals(ShowType.TABLE.getDescp())) {
|
||||
email.setMsg(htmlTable(content));
|
||||
} else if (showType.equals(ShowType.TEXT.getDescp())) {
|
||||
email.setMsg(htmlText(content));
|
||||
}
|
||||
|
||||
// send
|
||||
email.setDebug(true);
|
||||
Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
|
||||
email.send();
|
||||
|
||||
alertResult.setStatus("true");
|
||||
|
||||
return alertResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* file delete
|
||||
*
|
||||
* @param file the file to delete
|
||||
*/
|
||||
public void deleteFile(File file) {
|
||||
if (file.exists()) {
|
||||
if (file.delete()) {
|
||||
logger.info("delete success: {}", file.getAbsolutePath() + file.getName());
|
||||
} else {
|
||||
logger.info("delete fail: {}", file.getAbsolutePath() + file.getName());
|
||||
}
|
||||
} else {
|
||||
logger.info("file not exists: {}", file.getAbsolutePath() + file.getName());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* handle exception
|
||||
*
|
||||
* @param alertResult
|
||||
* @param e
|
||||
*/
|
||||
private void handleException(AlertResult alertResult, Exception e) {
|
||||
logger.error("Send email to {} failed", receivers, e);
|
||||
alertResult.setMessage("Send email to {" + String.join(",", receivers) + "} failed," + e.toString());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -14,9 +14,10 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.dolphinscheduler.alert.template;
|
||||
|
||||
import org.apache.dolphinscheduler.common.enums.ShowType;
|
||||
package org.apache.dolphinscheduler.plugin.alert.email.template;
|
||||
|
||||
import org.apache.dolphinscheduler.spi.alert.ShowType;
|
||||
|
||||
/**
|
||||
* alert message template
|
||||
|
|
@ -25,20 +26,22 @@ public interface AlertTemplate {
|
|||
|
||||
/**
|
||||
* get a message from a specified alert template
|
||||
* @param content alert message content
|
||||
* @param showType show type
|
||||
* @param showAll whether to show all
|
||||
*
|
||||
* @param content alert message content
|
||||
* @param showType show type
|
||||
* @param showAll whether to show all
|
||||
* @return a message from a specified alert template
|
||||
*/
|
||||
String getMessageFromTemplate(String content, ShowType showType,boolean showAll);
|
||||
String getMessageFromTemplate(String content, ShowType showType, boolean showAll);
|
||||
|
||||
/**
|
||||
* default showAll is true
|
||||
* @param content alert message content
|
||||
*
|
||||
* @param content alert message content
|
||||
* @param showType show type
|
||||
* @return a message from a specified alert template
|
||||
*/
|
||||
default String getMessageFromTemplate(String content,ShowType showType){
|
||||
return getMessageFromTemplate(content,showType,true);
|
||||
default String getMessageFromTemplate(String content, ShowType showType) {
|
||||
return getMessageFromTemplate(content, showType, true);
|
||||
}
|
||||
}
|
||||
|
|
@ -15,21 +15,19 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.apache.dolphinscheduler.alert.template.impl;
|
||||
package org.apache.dolphinscheduler.plugin.alert.email.template;
|
||||
|
||||
import static org.apache.dolphinscheduler.common.utils.Preconditions.checkNotNull;
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
import org.apache.dolphinscheduler.alert.template.AlertTemplate;
|
||||
import org.apache.dolphinscheduler.alert.utils.Constants;
|
||||
import org.apache.dolphinscheduler.common.enums.ShowType;
|
||||
import org.apache.dolphinscheduler.common.utils.JSONUtils;
|
||||
import org.apache.dolphinscheduler.common.utils.StringUtils;
|
||||
import org.apache.dolphinscheduler.plugin.alert.email.EmailConstants;
|
||||
import org.apache.dolphinscheduler.spi.alert.ShowType;
|
||||
import org.apache.dolphinscheduler.spi.utils.JSONUtils;
|
||||
import org.apache.dolphinscheduler.spi.utils.StringUtils;
|
||||
|
||||
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;
|
||||
|
|
@ -52,7 +50,7 @@ public class DefaultHTMLTemplate implements AlertTemplate {
|
|||
case TABLE:
|
||||
return getTableTypeMessage(content, showAll);
|
||||
case TEXT:
|
||||
return getTextTypeMessage(content);
|
||||
return getTextTypeMessage(content, showAll);
|
||||
default:
|
||||
throw new IllegalArgumentException(String.format("not support showType: %s in DefaultHTMLTemplate", showType));
|
||||
}
|
||||
|
|
@ -70,8 +68,8 @@ public class DefaultHTMLTemplate implements AlertTemplate {
|
|||
if (StringUtils.isNotEmpty(content)) {
|
||||
List<LinkedHashMap> mapItemsList = JSONUtils.toList(content, LinkedHashMap.class);
|
||||
|
||||
if (!showAll && mapItemsList.size() > Constants.NUMBER_1000) {
|
||||
mapItemsList = mapItemsList.subList(0, Constants.NUMBER_1000);
|
||||
if (!showAll && mapItemsList.size() > EmailConstants.NUMBER_1000) {
|
||||
mapItemsList = mapItemsList.subList(0, EmailConstants.NUMBER_1000);
|
||||
}
|
||||
|
||||
StringBuilder contents = new StringBuilder(200);
|
||||
|
|
@ -81,21 +79,21 @@ public class DefaultHTMLTemplate implements AlertTemplate {
|
|||
String title = "";
|
||||
for (LinkedHashMap mapItems : mapItemsList) {
|
||||
|
||||
Set<Entry<String, Object>> entries = mapItems.entrySet();
|
||||
Set<Map.Entry<String, Object>> entries = mapItems.entrySet();
|
||||
|
||||
Iterator<Entry<String, Object>> iterator = entries.iterator();
|
||||
Iterator<Map.Entry<String, Object>> iterator = entries.iterator();
|
||||
|
||||
StringBuilder t = new StringBuilder(Constants.TR);
|
||||
StringBuilder cs = new StringBuilder(Constants.TR);
|
||||
StringBuilder t = new StringBuilder(EmailConstants.TR);
|
||||
StringBuilder cs = new StringBuilder(EmailConstants.TR);
|
||||
while (iterator.hasNext()) {
|
||||
|
||||
Map.Entry<String, Object> entry = iterator.next();
|
||||
t.append(Constants.TH).append(entry.getKey()).append(Constants.TH_END);
|
||||
cs.append(Constants.TD).append(String.valueOf(entry.getValue())).append(Constants.TD_END);
|
||||
t.append(EmailConstants.TH).append(entry.getKey()).append(EmailConstants.TH_END);
|
||||
cs.append(EmailConstants.TD).append(String.valueOf(entry.getValue())).append(EmailConstants.TD_END);
|
||||
|
||||
}
|
||||
t.append(Constants.TR_END);
|
||||
cs.append(Constants.TR_END);
|
||||
t.append(EmailConstants.TR_END);
|
||||
cs.append(EmailConstants.TR_END);
|
||||
if (flag) {
|
||||
title = t.toString();
|
||||
}
|
||||
|
|
@ -113,17 +111,18 @@ public class DefaultHTMLTemplate implements AlertTemplate {
|
|||
* get alert message which type is TEXT
|
||||
*
|
||||
* @param content message content
|
||||
* @param showAll weather to show all
|
||||
* @return alert message
|
||||
*/
|
||||
private String getTextTypeMessage(String content) {
|
||||
private String getTextTypeMessage(String content, boolean showAll) {
|
||||
|
||||
if (StringUtils.isNotEmpty(content)) {
|
||||
ArrayNode list = JSONUtils.parseArray(content);
|
||||
StringBuilder contents = new StringBuilder(100);
|
||||
for (JsonNode jsonNode : list) {
|
||||
contents.append(Constants.TR);
|
||||
contents.append(Constants.TD).append(jsonNode.toString()).append(Constants.TD_END);
|
||||
contents.append(Constants.TR_END);
|
||||
contents.append(EmailConstants.TR);
|
||||
contents.append(EmailConstants.TD).append(jsonNode.toString()).append(EmailConstants.TD_END);
|
||||
contents.append(EmailConstants.TR_END);
|
||||
}
|
||||
|
||||
return getMessageFromHtmlTemplate(null, contents.toString());
|
||||
|
|
@ -136,16 +135,16 @@ public class DefaultHTMLTemplate implements AlertTemplate {
|
|||
/**
|
||||
* get alert message from a html template
|
||||
*
|
||||
* @param title message title
|
||||
* @param title message title
|
||||
* @param content message content
|
||||
* @return alert message which use html template
|
||||
*/
|
||||
private String getMessageFromHtmlTemplate(String title, String content) {
|
||||
|
||||
checkNotNull(content);
|
||||
String htmlTableThead = StringUtils.isEmpty(title) ? "" : String.format("<thead>%s</thead>%n", title);
|
||||
requireNonNull(content, "content must not null");
|
||||
String htmlTableThead = StringUtils.isEmpty(title) ? "" : String.format("<thead>%s</thead>\n", title);
|
||||
|
||||
return Constants.HTML_HEADER_PREFIX + htmlTableThead + content + Constants.TABLE_BODY_HTML_TAIL;
|
||||
return EmailConstants.HTML_HEADER_PREFIX + htmlTableThead + content + EmailConstants.TABLE_BODY_HTML_TAIL;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,75 @@
|
|||
/*
|
||||
* 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.email;
|
||||
|
||||
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.After;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* EmailAlertChannelFactory Tester.
|
||||
*
|
||||
* @version 1.0
|
||||
* @since <pre>Aug 20, 2020</pre>
|
||||
*/
|
||||
public class EmailAlertChannelFactoryTest {
|
||||
|
||||
@Before
|
||||
public void before() throws Exception {
|
||||
}
|
||||
|
||||
@After
|
||||
public void after() throws Exception {
|
||||
}
|
||||
|
||||
/**
|
||||
* Method: getName()
|
||||
*/
|
||||
@Test
|
||||
public void testGetName() throws Exception {
|
||||
}
|
||||
|
||||
/**
|
||||
* Method: getParams()
|
||||
*/
|
||||
@Test
|
||||
public void testGetParams() throws Exception {
|
||||
EmailAlertChannelFactory emailAlertChannelFactory = new EmailAlertChannelFactory();
|
||||
List<PluginParams> params = emailAlertChannelFactory.getParams();
|
||||
System.out.println(JSONUtils.toJsonString(params));
|
||||
Assert.assertEquals(12, params.size());
|
||||
}
|
||||
|
||||
/**
|
||||
* Method: create()
|
||||
*/
|
||||
@Test
|
||||
public void testCreate() throws Exception {
|
||||
EmailAlertChannelFactory emailAlertChannelFactory = new EmailAlertChannelFactory();
|
||||
AlertChannel alertChannel = emailAlertChannelFactory.create();
|
||||
Assert.assertNotNull(alertChannel);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,161 @@
|
|||
/*
|
||||
* 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.email;
|
||||
|
||||
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.AlertResult;
|
||||
import org.apache.dolphinscheduler.spi.alert.ShowType;
|
||||
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.DataType;
|
||||
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 org.apache.dolphinscheduler.spi.utils.JSONUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* EmailAlertChannel Tester.
|
||||
*/
|
||||
public class EmailAlertChannelTest {
|
||||
|
||||
/**
|
||||
* Method: process(AlertInfo info)
|
||||
*/
|
||||
@Test
|
||||
public void testProcess() {
|
||||
EmailAlertChannel emailAlertChannel = new EmailAlertChannel();
|
||||
AlertData alertData = new AlertData();
|
||||
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");
|
||||
List<LinkedHashMap<String, Object>> maps = new ArrayList<>();
|
||||
maps.add(0, map1);
|
||||
String mapjson = JSONUtils.toJsonString(maps);
|
||||
|
||||
alertData.setId(10)
|
||||
.setContent(mapjson)
|
||||
.setLog("10")
|
||||
.setTitle("test");
|
||||
AlertInfo alertInfo = new AlertInfo();
|
||||
alertInfo.setAlertData(alertData);
|
||||
alertInfo.setAlertParams(getEmailAlertParams());
|
||||
AlertResult alertResult = emailAlertChannel.process(alertInfo);
|
||||
Assert.assertNotNull(alertResult);
|
||||
Assert.assertEquals("false", alertResult.getStatus());
|
||||
}
|
||||
|
||||
public String getEmailAlertParams() {
|
||||
List<PluginParams> paramsList = new ArrayList<>();
|
||||
InputParam receivesParam = InputParam.newBuilder("receivers", "receivers")
|
||||
.setValue("540957506@qq.com")
|
||||
.addValidate(Validate.newBuilder().setRequired(true).build())
|
||||
.build();
|
||||
|
||||
InputParam mailSmtpHost = InputParam.newBuilder("serverHost", "smtp.host")
|
||||
.addValidate(Validate.newBuilder().setRequired(true).build())
|
||||
.setValue("smtp.126.com")
|
||||
.build();
|
||||
|
||||
InputParam mailSmtpPort = InputParam.newBuilder("serverPort", "smtp.port")
|
||||
.addValidate(Validate.newBuilder()
|
||||
.setRequired(true)
|
||||
.setType(DataType.NUMBER.getDataType())
|
||||
.build())
|
||||
.setValue(25)
|
||||
.build();
|
||||
|
||||
InputParam mailSender = InputParam.newBuilder("sender", "sender")
|
||||
.addValidate(Validate.newBuilder().setRequired(true).build())
|
||||
.setValue("dolphinscheduler@126.com")
|
||||
.build();
|
||||
|
||||
RadioParam enableSmtpAuth = RadioParam.newBuilder("enableSmtpAuth", "smtp.auth")
|
||||
.addParamsOptions(new ParamsOptions("YES", true, false))
|
||||
.addParamsOptions(new ParamsOptions("NO", false, false))
|
||||
.addValidate(Validate.newBuilder().setRequired(true).build())
|
||||
.setValue(false)
|
||||
.build();
|
||||
|
||||
InputParam mailUser = InputParam.newBuilder("user", "user")
|
||||
.setPlaceholder("if enable use authentication, you need input user")
|
||||
.setValue("dolphinscheduler@126.com")
|
||||
.build();
|
||||
|
||||
PasswordParam mailPassword = PasswordParam.newBuilder("passwd", "passwd")
|
||||
.setPlaceholder("if enable use authentication, you need input password")
|
||||
.setValue("escheduler123")
|
||||
.build();
|
||||
|
||||
RadioParam enableTls = RadioParam.newBuilder("starttlsEnable", "starttls.enable")
|
||||
.addParamsOptions(new ParamsOptions("YES", true, false))
|
||||
.addParamsOptions(new ParamsOptions("NO", false, false))
|
||||
.addValidate(Validate.newBuilder().setRequired(true).build())
|
||||
.setValue(true)
|
||||
.build();
|
||||
|
||||
RadioParam enableSsl = RadioParam.newBuilder("sslEnable", "smtp.ssl.enable")
|
||||
.addParamsOptions(new ParamsOptions("YES", true, false))
|
||||
.addParamsOptions(new ParamsOptions("NO", false, false))
|
||||
.addValidate(Validate.newBuilder().setRequired(true).build())
|
||||
.setValue(true)
|
||||
.build();
|
||||
|
||||
InputParam sslTrust = InputParam.newBuilder("smtpSslTrust", "smtp.ssl.trust")
|
||||
.addValidate(Validate.newBuilder().setRequired(true).build())
|
||||
.setValue("smtp.126.com")
|
||||
.build();
|
||||
|
||||
List<ParamsOptions> emailShowTypeList = new ArrayList<>();
|
||||
emailShowTypeList.add(new ParamsOptions(ShowType.TABLE.getDescp(), ShowType.TABLE.getDescp(), false));
|
||||
emailShowTypeList.add(new ParamsOptions(ShowType.TEXT.getDescp(), ShowType.TEXT.getDescp(), false));
|
||||
emailShowTypeList.add(new ParamsOptions(ShowType.ATTACHMENT.getDescp(), ShowType.ATTACHMENT.getDescp(), false));
|
||||
emailShowTypeList.add(new ParamsOptions(ShowType.TABLEATTACHMENT.getDescp(), ShowType.TABLEATTACHMENT.getDescp(), false));
|
||||
RadioParam showType = RadioParam.newBuilder(AlertConstants.SHOW_TYPE, "showType")
|
||||
.setParamsOptionsList(emailShowTypeList)
|
||||
.setValue(ShowType.TABLE.getDescp())
|
||||
.addValidate(Validate.newBuilder().setRequired(true).build())
|
||||
.build();
|
||||
|
||||
paramsList.add(receivesParam);
|
||||
paramsList.add(mailSmtpHost);
|
||||
paramsList.add(mailSmtpPort);
|
||||
paramsList.add(mailSender);
|
||||
paramsList.add(enableSmtpAuth);
|
||||
paramsList.add(mailUser);
|
||||
paramsList.add(mailPassword);
|
||||
paramsList.add(enableTls);
|
||||
paramsList.add(enableSsl);
|
||||
paramsList.add(sslTrust);
|
||||
paramsList.add(showType);
|
||||
|
||||
return JSONUtils.toJsonString(paramsList);
|
||||
}
|
||||
}
|
||||
|
|
@ -15,7 +15,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.apache.dolphinscheduler.alert.utils;
|
||||
package org.apache.dolphinscheduler.plugin.alert.email;
|
||||
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
|
|
@ -63,7 +63,7 @@ public class ExcelUtilsTest {
|
|||
|
||||
//Define dest file path
|
||||
String xlsFilePath = rootPath + System.getProperty("file.separator");
|
||||
logger.info("XLS_FILE_PATH: " + xlsFilePath);
|
||||
logger.info("xlsFilePath: " + xlsFilePath);
|
||||
|
||||
//Define correctContent
|
||||
String correctContent = "[{\"name\":\"ds name\",\"value\":\"ds value\"}]";
|
||||
|
|
@ -78,7 +78,7 @@ public class ExcelUtilsTest {
|
|||
ExcelUtils.genExcelFile(correctContent, title, xlsFilePath);
|
||||
|
||||
//Test file exists
|
||||
File xlsFile = new File(xlsFilePath + Constants.SINGLE_SLASH + title + Constants.EXCEL_SUFFIX_XLS);
|
||||
File xlsFile = new File(xlsFilePath + EmailConstants.SINGLE_SLASH + title + EmailConstants.EXCEL_SUFFIX_XLS);
|
||||
assertTrue(xlsFile.exists());
|
||||
|
||||
//Expected RuntimeException
|
||||
|
|
@ -98,7 +98,7 @@ public class ExcelUtilsTest {
|
|||
@Test
|
||||
public void testGenExcelFileByCheckDir() {
|
||||
ExcelUtils.genExcelFile("[{\"a\": \"a\"},{\"a\": \"a\"}]", "t", "/tmp/xls");
|
||||
File file = new File("/tmp/xls" + Constants.SINGLE_SLASH + "t" + Constants.EXCEL_SUFFIX_XLS);
|
||||
File file = new File("/tmp/xls" + EmailConstants.SINGLE_SLASH + "t" + EmailConstants.EXCEL_SUFFIX_XLS);
|
||||
file.delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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.plugin.alert.email;
|
||||
|
||||
import org.apache.dolphinscheduler.plugin.alert.email.template.AlertTemplate;
|
||||
import org.apache.dolphinscheduler.plugin.alert.email.template.DefaultHTMLTemplate;
|
||||
import org.apache.dolphinscheduler.spi.alert.AlertConstants;
|
||||
import org.apache.dolphinscheduler.spi.alert.ShowType;
|
||||
import org.apache.dolphinscheduler.spi.utils.JSONUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
*/
|
||||
public class MailUtilsTest {
|
||||
private static final Logger logger = LoggerFactory.getLogger(MailUtilsTest.class);
|
||||
|
||||
private static Map<String, String> emailConfig = new HashMap<>();
|
||||
|
||||
private static AlertTemplate alertTemplate;
|
||||
|
||||
static MailSender mailSender;
|
||||
|
||||
@BeforeClass
|
||||
public static void initEmailConfig() {
|
||||
emailConfig.put(MailParamsConstants.NAME_MAIL_PROTOCOL, "smtp");
|
||||
emailConfig.put(MailParamsConstants.NAME_MAIL_SMTP_HOST, "xxx.xxx.com");
|
||||
emailConfig.put(MailParamsConstants.NAME_MAIL_SMTP_PORT, "25");
|
||||
emailConfig.put(MailParamsConstants.NAME_MAIL_SENDER, "xxx1.xxx.com");
|
||||
emailConfig.put(MailParamsConstants.NAME_MAIL_USER, "xxx2.xxx.com");
|
||||
emailConfig.put(MailParamsConstants.NAME_MAIL_PASSWD, "111111");
|
||||
emailConfig.put(MailParamsConstants.NAME_MAIL_SMTP_STARTTLS_ENABLE, "true");
|
||||
emailConfig.put(MailParamsConstants.NAME_MAIL_SMTP_SSL_ENABLE, "false");
|
||||
emailConfig.put(MailParamsConstants.NAME_MAIL_SMTP_SSL_TRUST, "false");
|
||||
emailConfig.put(MailParamsConstants.NAME_PLUGIN_DEFAULT_EMAIL_RECEIVERS, "347801120@qq.com");
|
||||
emailConfig.put(MailParamsConstants.NAME_PLUGIN_DEFAULT_EMAIL_RECEIVERCCS, "347801120@qq.com");
|
||||
emailConfig.put(AlertConstants.SHOW_TYPE, ShowType.TEXT.getDescp());
|
||||
alertTemplate = new DefaultHTMLTemplate();
|
||||
mailSender = new MailSender(emailConfig);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSendMails() {
|
||||
|
||||
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\"]";
|
||||
|
||||
mailSender.sendMails(
|
||||
"Mysql Exception",
|
||||
content);
|
||||
}
|
||||
|
||||
public 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);
|
||||
logger.info(mapjson);
|
||||
|
||||
return mapjson;
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSendTableMail() {
|
||||
String title = "Mysql Exception";
|
||||
String content = list2String();
|
||||
emailConfig.put(AlertConstants.SHOW_TYPE, ShowType.TABLE.getDescp());
|
||||
mailSender = new MailSender(emailConfig);
|
||||
mailSender.sendMails(title, content);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAttachmentFile() throws Exception {
|
||||
String content = list2String();
|
||||
emailConfig.put(AlertConstants.SHOW_TYPE, ShowType.ATTACHMENT.getDescp());
|
||||
mailSender = new MailSender(emailConfig);
|
||||
mailSender.sendMails("gaojing", content);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTableAttachmentFile() throws Exception {
|
||||
String content = list2String();
|
||||
emailConfig.put(AlertConstants.SHOW_TYPE, ShowType.TABLEATTACHMENT.getDescp());
|
||||
mailSender = new MailSender(emailConfig);
|
||||
mailSender.sendMails("gaojing", content);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,105 @@
|
|||
/*
|
||||
* 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.email.template;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import org.apache.dolphinscheduler.plugin.alert.email.EmailConstants;
|
||||
import org.apache.dolphinscheduler.spi.alert.ShowType;
|
||||
import org.apache.dolphinscheduler.spi.utils.JSONUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* test class for DefaultHTMLTemplate
|
||||
*/
|
||||
public class DefaultHTMLTemplateTest {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(DefaultHTMLTemplateTest.class);
|
||||
|
||||
/**
|
||||
* only need test method GetMessageFromTemplate
|
||||
*/
|
||||
@Test
|
||||
public void testGetMessageFromTemplate() {
|
||||
|
||||
DefaultHTMLTemplate template = new DefaultHTMLTemplate();
|
||||
|
||||
String tableTypeMessage = template.getMessageFromTemplate(list2String(), ShowType.TABLE, true);
|
||||
|
||||
assertEquals(tableTypeMessage, generateMockTableTypeResultByHand());
|
||||
|
||||
String textTypeMessage = template.getMessageFromTemplate(list2String(), ShowType.TEXT, true);
|
||||
|
||||
assertEquals(textTypeMessage, generateMockTextTypeResultByHand());
|
||||
}
|
||||
|
||||
/**
|
||||
* generate some simulation data
|
||||
*/
|
||||
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("database client connections", "190");
|
||||
map1.put("port", "3306");
|
||||
map1.put("no index of number", "80");
|
||||
|
||||
LinkedHashMap<String, Object> map2 = new LinkedHashMap<>();
|
||||
map2.put("mysql service name", "mysql210");
|
||||
map2.put("mysql address", "192.168.xx.xx");
|
||||
map2.put("database client connections", "90");
|
||||
map2.put("port", "3306");
|
||||
map2.put("no index of number", "10");
|
||||
|
||||
List<LinkedHashMap<String, Object>> maps = new ArrayList<>();
|
||||
maps.add(0, map1);
|
||||
maps.add(1, map2);
|
||||
String mapjson = JSONUtils.toJsonString(maps);
|
||||
logger.info(mapjson);
|
||||
|
||||
return mapjson;
|
||||
}
|
||||
|
||||
private String generateMockTableTypeResultByHand() {
|
||||
|
||||
return EmailConstants.HTML_HEADER_PREFIX
|
||||
+ "<thead>"
|
||||
+ "<tr><th>mysql service name</th><th>mysql address</th><th>database client connections</th><th>port</th><th>no index of number</th></tr>"
|
||||
+ "</thead>\n"
|
||||
+ "<tr><td>mysql200</td><td>192.168.xx.xx</td><td>190</td><td>3306</td><td>80</td></tr>"
|
||||
+ "<tr><td>mysql210</td><td>192.168.xx.xx</td><td>90</td><td>3306</td><td>10</td></tr>"
|
||||
+ EmailConstants.TABLE_BODY_HTML_TAIL;
|
||||
|
||||
}
|
||||
|
||||
private String generateMockTextTypeResultByHand() {
|
||||
|
||||
return EmailConstants.HTML_HEADER_PREFIX
|
||||
+ "<tr><td>{\"mysql service name\":\"mysql200\",\"mysql address\":\"192.168.xx.xx\",\"database client connections\":\"190\",\"port\":\"3306\",\"no index of number\":\"80\"}</td></tr>"
|
||||
+ "<tr><td>{\"mysql service name\":\"mysql210\",\"mysql address\":\"192.168.xx.xx\",\"database client connections\":\"90\",\"port\":\"3306\",\"no index of number\":\"10\"}</td></tr>"
|
||||
+ EmailConstants.TABLE_BODY_HTML_TAIL;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,76 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
~ 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.
|
||||
-->
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>dolphinscheduler-alert-plugin</artifactId>
|
||||
<groupId>org.apache.dolphinscheduler</groupId>
|
||||
<version>1.3.4-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>dolphinscheduler-alert-http</artifactId>
|
||||
<packaging>dolphinscheduler-plugin</packaging>
|
||||
<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>
|
||||
|
||||
<build>
|
||||
<finalName>dolphinscheduler-alert-http-${project.version}</finalName>
|
||||
</build>
|
||||
|
||||
</project>
|
||||
|
|
@ -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.http;
|
||||
|
||||
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;
|
||||
|
||||
/**
|
||||
* http alert channel,use sms message to seed the alertInfo
|
||||
*/
|
||||
public class HttpAlertChannel 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 HttpSender(paramsMap).send(alertData.getContent());
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,78 @@
|
|||
/*
|
||||
* 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.http;
|
||||
|
||||
import org.apache.dolphinscheduler.spi.alert.AlertChannel;
|
||||
import org.apache.dolphinscheduler.spi.alert.AlertChannelFactory;
|
||||
import org.apache.dolphinscheduler.spi.params.InputParam;
|
||||
import org.apache.dolphinscheduler.spi.params.base.PluginParams;
|
||||
import org.apache.dolphinscheduler.spi.params.base.Validate;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* http alert factory
|
||||
*/
|
||||
public class HttpAlertChannelFactory implements AlertChannelFactory {
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Http";
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<PluginParams> getParams() {
|
||||
|
||||
InputParam url = InputParam.newBuilder(HttpAlertConstants.URL, HttpAlertConstants.URL)
|
||||
.addValidate(Validate.newBuilder()
|
||||
.setRequired(true)
|
||||
.build())
|
||||
.build();
|
||||
|
||||
InputParam headerParams = InputParam.newBuilder(HttpAlertConstants.HEADER_PARAMS, HttpAlertConstants.HEADER_PARAMS)
|
||||
.addValidate(Validate.newBuilder()
|
||||
.setRequired(true)
|
||||
.build())
|
||||
.build();
|
||||
|
||||
InputParam bodyParams = InputParam.newBuilder(HttpAlertConstants.BODY_PARAMS, HttpAlertConstants.BODY_PARAMS)
|
||||
.addValidate(Validate.newBuilder()
|
||||
.setRequired(true)
|
||||
.build())
|
||||
.build();
|
||||
|
||||
InputParam contentField = InputParam.newBuilder(HttpAlertConstants.CONTENT_FIELD, HttpAlertConstants.CONTENT_FIELD)
|
||||
.addValidate(Validate.newBuilder()
|
||||
.setRequired(true)
|
||||
.build())
|
||||
.build();
|
||||
|
||||
InputParam requestType = InputParam.newBuilder(HttpAlertConstants.REQUEST_TYPE, HttpAlertConstants.REQUEST_TYPE)
|
||||
.addValidate(Validate.newBuilder()
|
||||
.setRequired(true)
|
||||
.build())
|
||||
.build();
|
||||
|
||||
return Arrays.asList(url, requestType, headerParams, bodyParams, contentField);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AlertChannel create() {
|
||||
return new HttpAlertChannel();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* 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.http;
|
||||
|
||||
public class HttpAlertConstants {
|
||||
|
||||
private HttpAlertConstants() {
|
||||
}
|
||||
|
||||
public static final String URL = "url";
|
||||
|
||||
public static final String HEADER_PARAMS = "headerParams";
|
||||
|
||||
public static final String BODY_PARAMS = "bodyParams";
|
||||
|
||||
public static final String CONTENT_FIELD = "contentField";
|
||||
|
||||
public static final String REQUEST_TYPE = "requestType";
|
||||
|
||||
}
|
||||
|
|
@ -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.http;
|
||||
|
||||
import org.apache.dolphinscheduler.spi.DolphinSchedulerPlugin;
|
||||
import org.apache.dolphinscheduler.spi.alert.AlertChannelFactory;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
/**
|
||||
* http alertPlugins
|
||||
*/
|
||||
public class HttpAlertPlugin implements DolphinSchedulerPlugin {
|
||||
|
||||
@Override
|
||||
public Iterable<AlertChannelFactory> getAlertChannelFactorys() {
|
||||
return ImmutableList.of(new HttpAlertChannelFactory());
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,166 @@
|
|||
/*
|
||||
* 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.http;
|
||||
|
||||
import org.apache.dolphinscheduler.spi.alert.AlertResult;
|
||||
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.client.methods.HttpRequestBase;
|
||||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
import org.apache.http.impl.client.HttpClientBuilder;
|
||||
import org.apache.http.util.EntityUtils;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||
|
||||
/**
|
||||
* http send message
|
||||
*/
|
||||
public class HttpSender {
|
||||
|
||||
public static final Logger logger = LoggerFactory.getLogger(HttpSender.class);
|
||||
|
||||
private String url;
|
||||
|
||||
private final String headerParams;
|
||||
|
||||
private final String bodyParams;
|
||||
|
||||
private final String contentField;
|
||||
|
||||
private final String requestType;
|
||||
|
||||
private HttpRequestBase httpRequest;
|
||||
|
||||
|
||||
private static final String URL_SPLICE_CHAR = "?";
|
||||
|
||||
/**
|
||||
* request type post
|
||||
*/
|
||||
private static final String REQUEST_TYPE_POST = "POST";
|
||||
|
||||
/**
|
||||
* request type get
|
||||
*/
|
||||
private static final String REQUEST_TYPE_GET = "GET";
|
||||
|
||||
private static final String DEFAULT_CHARSET = "utf-8";
|
||||
|
||||
public HttpSender(Map<String, String> paramsMap) {
|
||||
|
||||
url = paramsMap.get(HttpAlertConstants.URL);
|
||||
headerParams = paramsMap.get(HttpAlertConstants.HEADER_PARAMS);
|
||||
bodyParams = paramsMap.get(HttpAlertConstants.BODY_PARAMS);
|
||||
contentField = paramsMap.get(HttpAlertConstants.CONTENT_FIELD);
|
||||
requestType = paramsMap.get(HttpAlertConstants.REQUEST_TYPE);
|
||||
}
|
||||
|
||||
public AlertResult send(String msg) {
|
||||
|
||||
AlertResult alertResult = new AlertResult();
|
||||
|
||||
createHttpRequest(msg);
|
||||
|
||||
if (httpRequest == null) {
|
||||
alertResult.setStatus("false");
|
||||
alertResult.setMessage("Request types are not supported");
|
||||
return alertResult;
|
||||
}
|
||||
|
||||
try {
|
||||
CloseableHttpClient httpClient = HttpClientBuilder.create().build();
|
||||
CloseableHttpResponse response = httpClient.execute(httpRequest);
|
||||
HttpEntity entity = response.getEntity();
|
||||
String resp = EntityUtils.toString(entity, DEFAULT_CHARSET);
|
||||
alertResult.setStatus("true");
|
||||
alertResult.setMessage(resp);
|
||||
} catch (Exception e) {
|
||||
logger.error("send http alert msg exception : {}", e.getMessage());
|
||||
alertResult.setStatus("false");
|
||||
alertResult.setMessage("send http request alert fail.");
|
||||
}
|
||||
|
||||
return alertResult;
|
||||
}
|
||||
|
||||
private void createHttpRequest(String msg) {
|
||||
|
||||
if (REQUEST_TYPE_POST.equals(requestType)) {
|
||||
httpRequest = new HttpPost(url);
|
||||
//POST request add param in request body
|
||||
setMsgInRequestBody(msg);
|
||||
} else if (REQUEST_TYPE_GET.equals(requestType)) {
|
||||
//GET request add param in url
|
||||
setMsgInUrl(msg);
|
||||
httpRequest = new HttpGet(url);
|
||||
}
|
||||
setHeader();
|
||||
}
|
||||
|
||||
/**
|
||||
* add msg param in url
|
||||
*/
|
||||
private void setMsgInUrl(String msg) {
|
||||
|
||||
if (StringUtils.isNotBlank(contentField)) {
|
||||
String type = "&";
|
||||
//check splice char is & or ?
|
||||
if (!url.contains(URL_SPLICE_CHAR)) {
|
||||
type = URL_SPLICE_CHAR;
|
||||
}
|
||||
url = String.format("%s%s%s=%s", url, type, contentField, msg);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* set header params
|
||||
*/
|
||||
private void setHeader() {
|
||||
|
||||
if (httpRequest == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
HashMap<String, Object> map = JSONUtils.parseObject(headerParams, HashMap.class);
|
||||
for (Map.Entry<String, Object> entry : map.entrySet()) {
|
||||
httpRequest.setHeader(entry.getKey(), String.valueOf(entry.getValue()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* set body params
|
||||
*/
|
||||
private String setMsgInRequestBody(String msg) {
|
||||
ObjectNode objectNode = JSONUtils.parseObject(bodyParams);
|
||||
//set msg content field
|
||||
objectNode.put(contentField, msg);
|
||||
return objectNode.toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -14,41 +14,41 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.dolphinscheduler.plugin.model;
|
||||
|
||||
package org.apache.dolphinscheduler.plugin.alert.http;
|
||||
|
||||
import org.apache.dolphinscheduler.spi.alert.AlertChannel;
|
||||
import org.apache.dolphinscheduler.spi.params.base.PluginParams;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
/**
|
||||
* HttpAlertChannelFactory UT
|
||||
*/
|
||||
public class HttpAlertChannelFactoryTest {
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
public class AlertInfoTest {
|
||||
|
||||
private AlertInfo alertInfo;
|
||||
private HttpAlertChannelFactory httpAlertChannelFactory;
|
||||
|
||||
@Before
|
||||
public void before() {
|
||||
alertInfo = new AlertInfo();
|
||||
public void init() {
|
||||
httpAlertChannelFactory = new HttpAlertChannelFactory();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAlertProps() {
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
alertInfo.setAlertProps(map);
|
||||
assertNotNull(alertInfo.getAlertProps());
|
||||
public void getParamsTest() {
|
||||
|
||||
List<PluginParams> pluginParamsList = httpAlertChannelFactory.getParams();
|
||||
Assert.assertEquals(5, pluginParamsList.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getProp() {
|
||||
alertInfo.addProp("k", "v");
|
||||
assertEquals("v", alertInfo.getProp("k"));
|
||||
public void createTest() {
|
||||
AlertChannel alertChannel = httpAlertChannelFactory.create();
|
||||
Assert.assertNotNull(alertChannel);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAlertData() {
|
||||
alertInfo.setAlertData(new AlertData());
|
||||
assertNotNull(alertInfo.getAlertData());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,104 @@
|
|||
/*
|
||||
* 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.http;
|
||||
|
||||
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.InputParam;
|
||||
import org.apache.dolphinscheduler.spi.params.base.PluginParams;
|
||||
import org.apache.dolphinscheduler.spi.params.base.Validate;
|
||||
import org.apache.dolphinscheduler.spi.utils.JSONUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* HttpAlertChannel UT
|
||||
*/
|
||||
public class HttpAlertChannelTest {
|
||||
|
||||
@Test
|
||||
public void processTest() {
|
||||
|
||||
HttpAlertChannel alertChannel = new HttpAlertChannel();
|
||||
AlertInfo alertInfo = new AlertInfo();
|
||||
AlertData alertData = new AlertData();
|
||||
alertData.setContent("Fault tolerance warning");
|
||||
alertInfo.setAlertData(alertData);
|
||||
AlertResult alertResult = alertChannel.process(alertInfo);
|
||||
Assert.assertEquals("Request types are not supported", alertResult.getMessage());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void processTest2() {
|
||||
|
||||
HttpAlertChannel alertChannel = new HttpAlertChannel();
|
||||
AlertInfo alertInfo = new AlertInfo();
|
||||
AlertData alertData = new AlertData();
|
||||
alertData.setContent("Fault tolerance warning");
|
||||
alertInfo.setAlertData(alertData);
|
||||
alertInfo.setAlertParams(getParams());
|
||||
AlertResult alertResult = alertChannel.process(alertInfo);
|
||||
Assert.assertEquals("true", alertResult.getStatus());
|
||||
}
|
||||
|
||||
/**
|
||||
* create params
|
||||
*/
|
||||
private String getParams() {
|
||||
|
||||
List<PluginParams> paramsList = new ArrayList<>();
|
||||
InputParam urlParam = InputParam.newBuilder("url", "url")
|
||||
.setValue("http://www.baidu.com")
|
||||
.addValidate(Validate.newBuilder().setRequired(true).build())
|
||||
.build();
|
||||
|
||||
InputParam headerParams = InputParam.newBuilder("headerParams", "headerParams")
|
||||
.addValidate(Validate.newBuilder().setRequired(true).build())
|
||||
.setValue("{\"Content-Type\":\"application/json\"}")
|
||||
.build();
|
||||
|
||||
InputParam bodyParams = InputParam.newBuilder("bodyParams", "bodyParams")
|
||||
.addValidate(Validate.newBuilder().setRequired(true).build())
|
||||
.setValue("{\"number\":\"13457654323\"}")
|
||||
.build();
|
||||
|
||||
InputParam content = InputParam.newBuilder("contentField", "contentField")
|
||||
.setValue("content")
|
||||
.addValidate(Validate.newBuilder().setRequired(true).build())
|
||||
.build();
|
||||
|
||||
InputParam requestType = InputParam.newBuilder("requestType", "requestType")
|
||||
.setValue("POST")
|
||||
.addValidate(Validate.newBuilder().setRequired(true).build())
|
||||
.build();
|
||||
|
||||
paramsList.add(urlParam);
|
||||
paramsList.add(headerParams);
|
||||
paramsList.add(bodyParams);
|
||||
paramsList.add(content);
|
||||
paramsList.add(requestType);
|
||||
|
||||
return JSONUtils.toJsonString(paramsList);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* 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.http;
|
||||
|
||||
import org.apache.dolphinscheduler.spi.alert.AlertChannelFactory;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* HttpAlertPlugin UT
|
||||
*/
|
||||
public class HttpAlertPluginTest {
|
||||
|
||||
@Test
|
||||
public void getAlertChannelFactorysTest() {
|
||||
|
||||
HttpAlertPlugin httpAlertPlugin = new HttpAlertPlugin();
|
||||
Iterable<AlertChannelFactory> alertChannelFactorys = httpAlertPlugin.getAlertChannelFactorys();
|
||||
Assert.assertNotNull(alertChannelFactorys);
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* 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.http;
|
||||
|
||||
import org.apache.dolphinscheduler.spi.alert.AlertResult;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* HttpSender UT
|
||||
*/
|
||||
public class HttpSenderTest {
|
||||
|
||||
@Test
|
||||
public void sendTest() {
|
||||
|
||||
Map<String, String> paramsMap = new HashMap<>();
|
||||
paramsMap.put(HttpAlertConstants.URL, "http://www.baidu.com");
|
||||
paramsMap.put(HttpAlertConstants.REQUEST_TYPE, "POST");
|
||||
paramsMap.put(HttpAlertConstants.HEADER_PARAMS, "{\"Content-Type\":\"application/json\"}");
|
||||
paramsMap.put(HttpAlertConstants.BODY_PARAMS, "{\"number\":\"13457654323\"}");
|
||||
paramsMap.put(HttpAlertConstants.CONTENT_FIELD, "content");
|
||||
HttpSender httpSender = new HttpSender(paramsMap);
|
||||
AlertResult alertResult = httpSender.send("Fault tolerance warning");
|
||||
Assert.assertEquals("true", alertResult.getStatus());
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,79 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
~ 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.
|
||||
-->
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>dolphinscheduler-alert-plugin</artifactId>
|
||||
<groupId>org.apache.dolphinscheduler</groupId>
|
||||
<version>1.3.4-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>org.apache.dolphinscheduler</groupId>
|
||||
<artifactId>dolphinscheduler-alert-script</artifactId>
|
||||
<packaging>dolphinscheduler-plugin</packaging>
|
||||
|
||||
<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.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>
|
||||
|
||||
<build>
|
||||
<finalName>dolphinscheduler-alert-script-${project.version}</finalName>
|
||||
</build>
|
||||
|
||||
</project>
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* 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.script;
|
||||
|
||||
/**
|
||||
* OSUtils
|
||||
*/
|
||||
public class OSUtils {
|
||||
|
||||
public OSUtils() {
|
||||
throw new UnsupportedOperationException("Construct OSUtils");
|
||||
}
|
||||
|
||||
static Boolean isWindows() {
|
||||
return System.getProperty("os.name").startsWith("Windows");
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
* 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.script;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* ProcessUtils
|
||||
*/
|
||||
public class ProcessUtils {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(ProcessUtils.class);
|
||||
|
||||
private ProcessUtils() {
|
||||
throw new IllegalStateException("Utility class");
|
||||
}
|
||||
|
||||
/**
|
||||
* executeScript
|
||||
*
|
||||
* @param cmd cmd params
|
||||
* @return exit code
|
||||
*/
|
||||
static Integer executeScript(String... cmd) {
|
||||
|
||||
int exitCode = -1;
|
||||
|
||||
ProcessBuilder processBuilder = new ProcessBuilder(cmd);
|
||||
try {
|
||||
Process process = processBuilder.start();
|
||||
StreamGobbler inputStreamGobbler = new StreamGobbler(process.getInputStream());
|
||||
StreamGobbler errorStreamGobbler = new StreamGobbler(process.getErrorStream());
|
||||
|
||||
inputStreamGobbler.start();
|
||||
errorStreamGobbler.start();
|
||||
return process.waitFor();
|
||||
} catch (IOException | InterruptedException e) {
|
||||
logger.error("execute alert script error {}", e.getMessage());
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
|
||||
return exitCode;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* 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.script;
|
||||
|
||||
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;
|
||||
|
||||
/**
|
||||
* ScriptAlertChannel
|
||||
*/
|
||||
public class ScriptAlertChannel 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 ScriptSender(paramsMap).sendScriptAlert(alertData.getTitle());
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
* 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.script;
|
||||
|
||||
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.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;
|
||||
|
||||
/**
|
||||
* ScriptAlertChannelFactory
|
||||
*/
|
||||
public class ScriptAlertChannelFactory implements AlertChannelFactory {
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Script";
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<PluginParams> getParams() {
|
||||
|
||||
InputParam scriptUserParam = InputParam.newBuilder(ScriptParamsConstants.NAME_SCRIPT_USER_PARAMS, ScriptParamsConstants.SCRIPT_USER_PARAMS)
|
||||
.addValidate(Validate.newBuilder()
|
||||
.setRequired(false)
|
||||
.build())
|
||||
.setPlaceholder("please enter your custom parameters, which will be passed to you when calling your script")
|
||||
.build();
|
||||
// need check file type and file exist
|
||||
InputParam scriptPathParam = InputParam.newBuilder(ScriptParamsConstants.NAME_SCRIPT_PATH, ScriptParamsConstants.SCRIPT_PATH)
|
||||
.addValidate(Validate.newBuilder()
|
||||
.setRequired(true)
|
||||
.build())
|
||||
.setPlaceholder("please upload the file to the disk directory of the alert server, and ensure that the path is absolute and has the corresponding access rights")
|
||||
.build();
|
||||
|
||||
RadioParam scriptTypeParams = RadioParam.newBuilder(ScriptParamsConstants.NAME_SCRIPT_TYPE, ScriptParamsConstants.SCRIPT_TYPE)
|
||||
.addParamsOptions(new ParamsOptions(ScriptType.SHELL.getDescp(), ScriptType.SHELL.getCode(), false))
|
||||
.setValue(ScriptType.SHELL.getCode())
|
||||
.addValidate(Validate.newBuilder().setRequired(true).build())
|
||||
.build();
|
||||
|
||||
return Arrays.asList(scriptUserParam, scriptPathParam, scriptTypeParams);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AlertChannel create() {
|
||||
return new ScriptAlertChannel();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* 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.script;
|
||||
|
||||
import org.apache.dolphinscheduler.spi.DolphinSchedulerPlugin;
|
||||
import org.apache.dolphinscheduler.spi.alert.AlertChannelFactory;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
/**
|
||||
* ScriptAlertPlugin
|
||||
*/
|
||||
public class ScriptAlertPlugin implements DolphinSchedulerPlugin {
|
||||
|
||||
@Override
|
||||
public Iterable<AlertChannelFactory> getAlertChannelFactorys() {
|
||||
return ImmutableList.of(new ScriptAlertChannelFactory());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* 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.script;
|
||||
|
||||
/**
|
||||
* ScriptParamsConstants
|
||||
*/
|
||||
public class ScriptParamsConstants {
|
||||
|
||||
public ScriptParamsConstants() {
|
||||
throw new IllegalStateException("Utility class");
|
||||
}
|
||||
|
||||
static final String SCRIPT_TYPE = "type";
|
||||
|
||||
static final String NAME_SCRIPT_TYPE = "type";
|
||||
|
||||
static final String SCRIPT_PATH = "path";
|
||||
|
||||
static final String NAME_SCRIPT_PATH = "path";
|
||||
|
||||
static final String SCRIPT_USER_PARAMS = "user.params";
|
||||
|
||||
static final String NAME_SCRIPT_USER_PARAMS = "userParams";
|
||||
}
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* 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.script;
|
||||
|
||||
import org.apache.dolphinscheduler.spi.alert.AlertResult;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* ScriptSender
|
||||
*/
|
||||
public class ScriptSender {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(ScriptSender.class);
|
||||
|
||||
private String scriptPath;
|
||||
|
||||
private Integer scriptType;
|
||||
|
||||
private String userParams;
|
||||
|
||||
ScriptSender(Map<String, String> config) {
|
||||
scriptPath = config.get(ScriptParamsConstants.NAME_SCRIPT_PATH);
|
||||
scriptType = Integer.parseInt(config.get(ScriptParamsConstants.NAME_SCRIPT_TYPE));
|
||||
userParams = config.get(ScriptParamsConstants.NAME_SCRIPT_USER_PARAMS);
|
||||
}
|
||||
|
||||
AlertResult sendScriptAlert(String msg) {
|
||||
AlertResult alertResult = new AlertResult();
|
||||
if (ScriptType.of(scriptType).equals(ScriptType.SHELL)) {
|
||||
return executeShellScript(msg);
|
||||
}
|
||||
return alertResult;
|
||||
}
|
||||
|
||||
private AlertResult executeShellScript(String msg) {
|
||||
AlertResult alertResult = new AlertResult();
|
||||
alertResult.setStatus("false");
|
||||
if (Boolean.TRUE.equals(OSUtils.isWindows())) {
|
||||
alertResult.setMessage("shell script not support windows os");
|
||||
return alertResult;
|
||||
}
|
||||
String[] cmd = {"/bin/sh", "-c", scriptPath + " " + msg + " " + userParams};
|
||||
int exitCode = ProcessUtils.executeScript(cmd);
|
||||
|
||||
if (exitCode == 0) {
|
||||
alertResult.setStatus("true");
|
||||
alertResult.setMessage("send script alert msg success");
|
||||
return alertResult;
|
||||
}
|
||||
alertResult.setMessage("send script alert msg error,exitCode is " + exitCode);
|
||||
logger.info("send script alert msg error,exitCode is {}", exitCode);
|
||||
return alertResult;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -14,48 +14,49 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.dolphinscheduler.plugin.model;
|
||||
|
||||
package org.apache.dolphinscheduler.plugin.alert.script;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* AlertInfo
|
||||
* ScriptType
|
||||
*/
|
||||
public class AlertInfo {
|
||||
public enum ScriptType {
|
||||
|
||||
private Map<String, Object> alertProps;
|
||||
|
||||
private AlertData alertData;
|
||||
SHELL(0, "SHELL"),
|
||||
;
|
||||
|
||||
public AlertInfo() {
|
||||
this.alertProps = new HashMap<>();
|
||||
ScriptType(int code, String descp) {
|
||||
this.code = code;
|
||||
this.descp = descp;
|
||||
}
|
||||
|
||||
public Map<String, Object> getAlertProps() {
|
||||
return alertProps;
|
||||
private final int code;
|
||||
private final String descp;
|
||||
|
||||
public int getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public AlertInfo setAlertProps(Map<String, Object> alertProps) {
|
||||
this.alertProps = alertProps;
|
||||
return this;
|
||||
public String getDescp() {
|
||||
return descp;
|
||||
}
|
||||
|
||||
public AlertInfo addProp(String key, Object value) {
|
||||
this.alertProps.put(key, value);
|
||||
return this;
|
||||
private static final Map<Integer, ScriptType> SCRIPT_TYPE_MAP = new HashMap<>();
|
||||
|
||||
static {
|
||||
for (ScriptType scriptType : ScriptType.values()) {
|
||||
SCRIPT_TYPE_MAP.put(scriptType.code, scriptType);
|
||||
}
|
||||
}
|
||||
|
||||
public Object getProp(String key) {
|
||||
return this.alertProps.get(key);
|
||||
}
|
||||
|
||||
public AlertData getAlertData() {
|
||||
return alertData;
|
||||
}
|
||||
|
||||
public AlertInfo setAlertData(AlertData alertData) {
|
||||
this.alertData = alertData;
|
||||
return this;
|
||||
public static ScriptType of(Integer code) {
|
||||
if (SCRIPT_TYPE_MAP.containsKey(code)) {
|
||||
return SCRIPT_TYPE_MAP.get(code);
|
||||
}
|
||||
throw new IllegalArgumentException("invalid code : " + code);
|
||||
}
|
||||
}
|
||||
|
|
@ -15,40 +15,47 @@
|
|||
* 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;
|
||||
package org.apache.dolphinscheduler.plugin.alert.script;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Ding Talk Manager
|
||||
* StreamGobbler
|
||||
*/
|
||||
public class DingTalkManager {
|
||||
private static final Logger logger = LoggerFactory.getLogger(DingTalkManager.class);
|
||||
public class StreamGobbler extends Thread {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(StreamGobbler.class);
|
||||
|
||||
private InputStream inputStream;
|
||||
|
||||
StreamGobbler(InputStream inputStream) {
|
||||
this.inputStream = inputStream;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
|
||||
BufferedReader inputBufferReader = new BufferedReader(inputStreamReader);
|
||||
|
||||
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);
|
||||
String line;
|
||||
StringBuilder output = new StringBuilder();
|
||||
while ((line = inputBufferReader.readLine()) != null) {
|
||||
output.append(line);
|
||||
output.append(System.getProperty("line.separator"));
|
||||
}
|
||||
if (output.length() > 0) {
|
||||
logger.info("out put msg is{}",output.toString());
|
||||
}
|
||||
} catch (IOException e) {
|
||||
logger.error(e.getMessage(), e);
|
||||
logger.error("I/O error occurs {}", e.getMessage());
|
||||
}
|
||||
retMap.put(Constants.STATUS, true);
|
||||
return retMap;
|
||||
}
|
||||
|
||||
private String buildMessage(AlertInfo alert) {
|
||||
return alert.getAlertData().getContent();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* 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.script;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* ProcessUtilsTest
|
||||
*/
|
||||
public class ProcessUtilsTest {
|
||||
|
||||
private static final String rootPath = System.getProperty("user.dir");
|
||||
|
||||
private static final String shellFilPath = rootPath + "/dolphinscheduler-alert-plugin/dolphinscheduler-alert-script/src/test/script/shell/example.sh";
|
||||
|
||||
private String[] cmd = {"/bin/sh", "-c", shellFilPath + " " + "testMsg" + " " + "userParams"};
|
||||
|
||||
@Test
|
||||
public void testExecuteScript() {
|
||||
ProcessUtils.executeScript(cmd);
|
||||
}
|
||||
}
|
||||
|
|
@ -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.script;
|
||||
|
||||
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;
|
||||
|
||||
/**
|
||||
* ScriptAlertChannelFactoryTest
|
||||
*/
|
||||
public class ScriptAlertChannelFactoryTest {
|
||||
|
||||
@Test
|
||||
public void testGetParams() {
|
||||
ScriptAlertChannelFactory scriptAlertChannelFactory = new ScriptAlertChannelFactory();
|
||||
List<PluginParams> params = scriptAlertChannelFactory.getParams();
|
||||
JSONUtils.toJsonString(params);
|
||||
Assert.assertEquals(3, params.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreate() {
|
||||
ScriptAlertChannelFactory scriptAlertChannelFactory = new ScriptAlertChannelFactory();
|
||||
AlertChannel alertChannel = scriptAlertChannelFactory.create();
|
||||
Assert.assertNotNull(alertChannel);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* 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.script;
|
||||
|
||||
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;
|
||||
|
||||
/**
|
||||
* ScriptSenderTest
|
||||
*/
|
||||
public class ScriptSenderTest {
|
||||
|
||||
private static Map<String, String> scriptConfig = new HashMap<>();
|
||||
|
||||
private static final String rootPath = System.getProperty("user.dir");
|
||||
|
||||
private static final String shellFilPath = rootPath + "/src/test/script/shell/scriptTest.sh";
|
||||
|
||||
@Before
|
||||
public void initScriptConfig() {
|
||||
|
||||
scriptConfig.put(ScriptParamsConstants.NAME_SCRIPT_TYPE, String.valueOf(ScriptType.SHELL.getCode()));
|
||||
scriptConfig.put(ScriptParamsConstants.NAME_SCRIPT_USER_PARAMS, "userParams");
|
||||
scriptConfig.put(ScriptParamsConstants.NAME_SCRIPT_PATH, shellFilPath);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testScriptSenderTest() {
|
||||
ScriptSender scriptSender = new ScriptSender(scriptConfig);
|
||||
AlertResult alertResult;
|
||||
alertResult = scriptSender.sendScriptAlert("success");
|
||||
Assert.assertEquals("true", alertResult.getStatus());
|
||||
alertResult = scriptSender.sendScriptAlert("errorMsg");
|
||||
Assert.assertEquals("false", alertResult.getStatus());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
|
||||
msg=$1
|
||||
content=$2
|
||||
|
||||
# Write your specific logic here
|
||||
|
||||
# Set the exit code according to your execution result, and alert needs to use it to judge the status of this alarm result
|
||||
exit 0
|
||||
|
|
@ -15,8 +15,11 @@
|
|||
# limitations under the License.
|
||||
#
|
||||
|
||||
test.string=teststring
|
||||
test.false=false
|
||||
test.true=true
|
||||
cba=3.1
|
||||
test.long=100
|
||||
msg=$1
|
||||
content=$2
|
||||
|
||||
if [ $msg = errorMsg ]
|
||||
then
|
||||
exit 12
|
||||
fi
|
||||
exit 0
|
||||
|
|
@ -0,0 +1,78 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
~ 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.
|
||||
-->
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>dolphinscheduler-alert-plugin</artifactId>
|
||||
<groupId>org.apache.dolphinscheduler</groupId>
|
||||
<version>1.3.4-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>org.apache.dolphinscheduler</groupId>
|
||||
<artifactId>dolphinscheduler-alert-wechat</artifactId>
|
||||
<packaging>dolphinscheduler-plugin</packaging>
|
||||
<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>
|
||||
|
||||
<build>
|
||||
<finalName>dolphinscheduler-alert-wechat-${project.version}</finalName>
|
||||
</build>
|
||||
</project>
|
||||
|
|
@ -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());
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -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 "WeChat";
|
||||
}
|
||||
|
||||
@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();
|
||||
}
|
||||
}
|
||||
|
|
@ -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}";
|
||||
}
|
||||
|
|
@ -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 = "corp.id";
|
||||
|
||||
static final String NAME_ENTERPRISE_WE_CHAT_CORP_ID = "corpId";
|
||||
|
||||
|
||||
static final String ENTERPRISE_WE_CHAT_SECRET = "secret";
|
||||
|
||||
static final String NAME_ENTERPRISE_WE_CHAT_SECRET = "secret";
|
||||
|
||||
static final String ENTERPRISE_WE_CHAT_TEAM_SEND_MSG = "team.send.msg";
|
||||
|
||||
static final String NAME_ENTERPRISE_WE_CHAT_TEAM_SEND_MSG = "teamSendMsg";
|
||||
|
||||
|
||||
static final String ENTERPRISE_WE_CHAT_USER_SEND_MSG = "user.send.msg";
|
||||
|
||||
static final String NAME_ENTERPRISE_WE_CHAT_USER_SEND_MSG = "userSendMsg";
|
||||
|
||||
|
||||
static final String ENTERPRISE_WE_CHAT_AGENT_ID = "agent.id";
|
||||
|
||||
static final String NAME_ENTERPRISE_WE_CHAT_AGENT_ID = "agentId";
|
||||
|
||||
|
||||
static final String ENTERPRISE_WE_CHAT_USERS = "users";
|
||||
|
||||
|
||||
static final String NAME_ENTERPRISE_WE_CHAT_USERS = "users";
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,335 @@
|
|||
/*
|
||||
* 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) {
|
||||
AlertResult alertResult;
|
||||
List<String> userList = Arrays.asList(weChatUsers.split(","));
|
||||
String data = markdownByAlert(title, content);
|
||||
String msg = makeUserSendMsg(userList, weChatAgentId, data);
|
||||
if (null == weChatToken) {
|
||||
alertResult = new AlertResult();
|
||||
alertResult.setMessage("send we chat alert fail,get weChat token error");
|
||||
alertResult.setStatus("false");
|
||||
return alertResult;
|
||||
}
|
||||
String enterpriseWeChatPushUrlReplace = WeChatAlertConstants.WE_CHAT_PUSH_URL.replace(tokenRegex, weChatToken);
|
||||
|
||||
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 && null != map.get("access_token")) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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, "100000");
|
||||
weChatConfig.put(WeChatAlertParamsConstants.NAME_ENTERPRISE_WE_CHAT_CORP_ID, "NAME_ENTERPRISE_WE_CHAT_CORP_ID");
|
||||
weChatConfig.put(WeChatAlertParamsConstants.NAME_ENTERPRISE_WE_CHAT_SECRET, "NAME_ENTERPRISE_WE_CHAT_SECRET");
|
||||
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("false", 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("false", alertResult.getStatus());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
~ 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.
|
||||
-->
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>dolphinscheduler</artifactId>
|
||||
<groupId>org.apache.dolphinscheduler</groupId>
|
||||
<version>1.3.4-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>org.apache.dolphinscheduler</groupId>
|
||||
<artifactId>dolphinscheduler-alert-plugin</artifactId>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<modules>
|
||||
<module>dolphinscheduler-alert-email</module>
|
||||
<module>dolphinscheduler-alert-wechat</module>
|
||||
<module>dolphinscheduler-alert-dingtalk</module>
|
||||
<module>dolphinscheduler-alert-script</module>
|
||||
<module>dolphinscheduler-alert-http</module>
|
||||
</modules>
|
||||
|
||||
|
||||
</project>
|
||||
|
|
@ -31,40 +31,23 @@
|
|||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.apache.dolphinscheduler</groupId>
|
||||
<artifactId>dolphinscheduler-spi</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.dolphinscheduler</groupId>
|
||||
<artifactId>dolphinscheduler-remote</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.dolphinscheduler</groupId>
|
||||
<artifactId>dolphinscheduler-common</artifactId>
|
||||
</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>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.powermock</groupId>
|
||||
<artifactId>powermock-module-junit4</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.powermock</groupId>
|
||||
<artifactId>powermock-api-mockito2</artifactId>
|
||||
<scope>test</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-core</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-email</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
|
|
@ -108,6 +91,52 @@
|
|||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.sonatype.aether</groupId>
|
||||
<artifactId>aether-api</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.airlift.resolver</groupId>
|
||||
<artifactId>resolver</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.ow2.asm</groupId>
|
||||
<artifactId>asm</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.powermock</groupId>
|
||||
<artifactId>powermock-module-junit4</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-core</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>mysql</groupId>
|
||||
<artifactId>mysql-connector-java</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.powermock</groupId>
|
||||
<artifactId>powermock-api-mockito2</artifactId>
|
||||
<scope>test</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-core</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
|
|
|
|||
|
|
@ -17,21 +17,32 @@
|
|||
|
||||
package org.apache.dolphinscheduler.alert;
|
||||
|
||||
import org.apache.dolphinscheduler.alert.plugin.EmailAlertPlugin;
|
||||
import static org.apache.dolphinscheduler.common.Constants.ALERT_RPC_PORT;
|
||||
|
||||
import org.apache.dolphinscheduler.alert.plugin.AlertPluginManager;
|
||||
import org.apache.dolphinscheduler.alert.plugin.DolphinPluginLoader;
|
||||
import org.apache.dolphinscheduler.alert.plugin.DolphinPluginManagerConfig;
|
||||
import org.apache.dolphinscheduler.alert.processor.AlertRequestProcessor;
|
||||
import org.apache.dolphinscheduler.alert.runner.AlertSender;
|
||||
import org.apache.dolphinscheduler.alert.utils.Constants;
|
||||
import org.apache.dolphinscheduler.alert.utils.PropertyUtils;
|
||||
import org.apache.dolphinscheduler.common.plugin.FilePluginManager;
|
||||
import org.apache.dolphinscheduler.common.thread.Stopper;
|
||||
import org.apache.dolphinscheduler.dao.AlertDao;
|
||||
import org.apache.dolphinscheduler.dao.DaoFactory;
|
||||
import org.apache.dolphinscheduler.dao.PluginDao;
|
||||
import org.apache.dolphinscheduler.dao.entity.Alert;
|
||||
import org.apache.dolphinscheduler.remote.NettyRemotingServer;
|
||||
import org.apache.dolphinscheduler.remote.command.CommandType;
|
||||
import org.apache.dolphinscheduler.remote.config.NettyServerConfig;
|
||||
import org.apache.dolphinscheduler.spi.utils.StringUtils;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
/**
|
||||
* alert of start
|
||||
*/
|
||||
|
|
@ -42,34 +53,75 @@ public class AlertServer {
|
|||
*/
|
||||
private AlertDao alertDao = DaoFactory.getDaoInstance(AlertDao.class);
|
||||
|
||||
private PluginDao pluginDao = DaoFactory.getDaoInstance(PluginDao.class);
|
||||
|
||||
private AlertSender alertSender;
|
||||
|
||||
private static AlertServer instance;
|
||||
|
||||
private FilePluginManager alertPluginManager;
|
||||
private AlertPluginManager alertPluginManager;
|
||||
|
||||
private static final String[] whitePrefixes = new String[]{"org.apache.dolphinscheduler.plugin.utils."};
|
||||
private DolphinPluginManagerConfig alertPluginManagerConfig;
|
||||
|
||||
private static final String[] excludePrefixes = new String[]{
|
||||
"org.apache.dolphinscheduler.plugin.",
|
||||
"ch.qos.logback.",
|
||||
"org.slf4j."
|
||||
};
|
||||
public static final String ALERT_PLUGIN_BINDING = "alert.plugin.binding";
|
||||
|
||||
public AlertServer() {
|
||||
alertPluginManager =
|
||||
new FilePluginManager(PropertyUtils.getString(Constants.PLUGIN_DIR), whitePrefixes, excludePrefixes);
|
||||
// add default alert plugins
|
||||
alertPluginManager.addPlugin(new EmailAlertPlugin());
|
||||
public static final String ALERT_PLUGIN_DIR = "alert.plugin.dir";
|
||||
|
||||
public static final String MAVEN_LOCAL_REPOSITORY = "maven.local.repository";
|
||||
|
||||
/**
|
||||
* netty server
|
||||
*/
|
||||
private NettyRemotingServer server;
|
||||
|
||||
private static class AlertServerHolder {
|
||||
private static final AlertServer INSTANCE = new AlertServer();
|
||||
}
|
||||
|
||||
public static synchronized AlertServer getInstance() {
|
||||
if (null == instance) {
|
||||
instance = new AlertServer();
|
||||
public static final AlertServer getInstance() {
|
||||
return AlertServerHolder.INSTANCE;
|
||||
|
||||
}
|
||||
|
||||
private AlertServer() {
|
||||
|
||||
}
|
||||
|
||||
private void initPlugin() {
|
||||
alertPluginManager = new AlertPluginManager();
|
||||
alertPluginManagerConfig = new DolphinPluginManagerConfig();
|
||||
alertPluginManagerConfig.setPlugins(PropertyUtils.getString(ALERT_PLUGIN_BINDING));
|
||||
if (StringUtils.isNotBlank(PropertyUtils.getString(ALERT_PLUGIN_DIR))) {
|
||||
alertPluginManagerConfig.setInstalledPluginsDir(PropertyUtils.getString(ALERT_PLUGIN_DIR, Constants.ALERT_PLUGIN_PATH).trim());
|
||||
}
|
||||
|
||||
if (StringUtils.isNotBlank(PropertyUtils.getString(MAVEN_LOCAL_REPOSITORY))) {
|
||||
alertPluginManagerConfig.setMavenLocalRepository(PropertyUtils.getString(MAVEN_LOCAL_REPOSITORY).trim());
|
||||
}
|
||||
|
||||
DolphinPluginLoader alertPluginLoader = new DolphinPluginLoader(alertPluginManagerConfig, ImmutableList.of(alertPluginManager));
|
||||
try {
|
||||
alertPluginLoader.loadPlugins();
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("load Alert Plugin Failed !", e);
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
public void start() {
|
||||
logger.info("alert server ready start ");
|
||||
/**
|
||||
* init netty remoting server
|
||||
*/
|
||||
private void initRemoteServer() {
|
||||
NettyServerConfig serverConfig = new NettyServerConfig();
|
||||
serverConfig.setListenPort(ALERT_RPC_PORT);
|
||||
this.server = new NettyRemotingServer(serverConfig);
|
||||
this.server.registerProcessor(CommandType.ALERT_SEND_REQUEST, new AlertRequestProcessor(alertDao, alertPluginManager, pluginDao));
|
||||
this.server.start();
|
||||
}
|
||||
|
||||
/**
|
||||
* Cyclic alert info sending alert
|
||||
*/
|
||||
private void runSender() {
|
||||
while (Stopper.isRunning()) {
|
||||
try {
|
||||
Thread.sleep(Constants.ALERT_SCAN_INTERVAL);
|
||||
|
|
@ -77,15 +129,43 @@ public class AlertServer {
|
|||
logger.error(e.getMessage(), e);
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
List<Alert> alerts = alertDao.listWaitExecutionAlert();
|
||||
AlertSender alertSender = new AlertSender(alerts, alertDao, alertPluginManager);
|
||||
alertSender.run();
|
||||
if (alertPluginManager == null || alertPluginManager.getAlertChannelMap().size() == 0) {
|
||||
logger.warn("No Alert Plugin . Can not send alert info. ");
|
||||
} else {
|
||||
List<Alert> alerts = alertDao.listWaitExecutionAlert();
|
||||
alertSender = new AlertSender(alerts, alertDao, alertPluginManager, pluginDao);
|
||||
alertSender.run();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* start
|
||||
*/
|
||||
public void start() {
|
||||
initPlugin();
|
||||
initRemoteServer();
|
||||
logger.info("alert server ready start ");
|
||||
runSender();
|
||||
}
|
||||
|
||||
/**
|
||||
* stop
|
||||
*/
|
||||
public void stop() {
|
||||
this.server.close();
|
||||
logger.info("alert server shut down");
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
AlertServer alertServer = AlertServer.getInstance();
|
||||
alertServer.start();
|
||||
Runtime.getRuntime().addShutdownHook(new Thread() {
|
||||
@Override
|
||||
public void run() {
|
||||
alertServer.stop();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,55 +1,55 @@
|
|||
/*
|
||||
* 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.MailUtils;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* email send manager
|
||||
*/
|
||||
public class EmailManager {
|
||||
/**
|
||||
* email send
|
||||
* @param receiversList the receiver list
|
||||
* @param receiversCcList the cc List
|
||||
* @param title the title
|
||||
* @param content the content
|
||||
* @param showType the showType
|
||||
* @return the send result
|
||||
*/
|
||||
public Map<String,Object> send(List<String> receiversList,List<String> receiversCcList,String title,String content,String showType){
|
||||
|
||||
return MailUtils.sendMails(receiversList, receiversCcList, title, content, showType);
|
||||
}
|
||||
|
||||
/**
|
||||
* msg send
|
||||
* @param receiversList the receiver list
|
||||
* @param title the title
|
||||
* @param content the content
|
||||
* @param showType the showType
|
||||
* @return the send result
|
||||
*/
|
||||
public Map<String,Object> send(List<String> receiversList,String title,String content,String showType){
|
||||
|
||||
return MailUtils.sendMails(receiversList,title, content, showType);
|
||||
}
|
||||
|
||||
}
|
||||
///*
|
||||
// * 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.MailUtils;
|
||||
//
|
||||
//import java.util.List;
|
||||
//import java.util.Map;
|
||||
//
|
||||
///**
|
||||
// * email send manager
|
||||
// */
|
||||
//public class EmailManager {
|
||||
// /**
|
||||
// * email send
|
||||
// * @param receiversList the receiver list
|
||||
// * @param receiversCcList the cc List
|
||||
// * @param title the title
|
||||
// * @param content the content
|
||||
// * @param showType the showType
|
||||
// * @return the send result
|
||||
// */
|
||||
// public Map<String,Object> send(List<String> receiversList,List<String> receiversCcList,String title,String content,String showType){
|
||||
//
|
||||
// return MailUtils.sendMails(receiversList, receiversCcList, title, content, showType);
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * msg send
|
||||
// * @param receiversList the receiver list
|
||||
// * @param title the title
|
||||
// * @param content the content
|
||||
// * @param showType the showType
|
||||
// * @return the send result
|
||||
// */
|
||||
// public Map<String,Object> send(List<String> receiversList,String title,String content,String showType){
|
||||
//
|
||||
// return MailUtils.sendMails(receiversList,title, content, showType);
|
||||
// }
|
||||
//
|
||||
//}
|
||||
|
|
|
|||
|
|
@ -1,59 +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.plugin.model.AlertInfo;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 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.getAlertData()));
|
||||
try {
|
||||
EnterpriseWeChatUtils.sendEnterpriseWeChat(Constants.UTF_8, msg, token);
|
||||
} catch (IOException e) {
|
||||
logger.error(e.getMessage(),e);
|
||||
}
|
||||
retMap.put(Constants.STATUS, true);
|
||||
return retMap;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -14,23 +14,27 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.apache.dolphinscheduler.alert.manager;
|
||||
|
||||
import org.apache.dolphinscheduler.dao.entity.Alert;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* SMS send manager
|
||||
*/
|
||||
public class MsgManager {
|
||||
public class MsgManager {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(MsgManager.class);
|
||||
|
||||
/**
|
||||
* SMS send
|
||||
*
|
||||
* @param alert the alert
|
||||
*/
|
||||
public void send(Alert alert){
|
||||
logger.info("send message {}",alert);
|
||||
public void send(Alert alert) {
|
||||
logger.info("send message {}", alert);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* 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.plugin;
|
||||
|
||||
import org.apache.dolphinscheduler.dao.DaoFactory;
|
||||
import org.apache.dolphinscheduler.dao.PluginDao;
|
||||
import org.apache.dolphinscheduler.spi.DolphinSchedulerPlugin;
|
||||
|
||||
public abstract class AbstractDolphinPluginManager {
|
||||
|
||||
protected PluginDao pluginDao = DaoFactory.getDaoInstance(PluginDao.class);
|
||||
|
||||
public abstract void installPlugin(DolphinSchedulerPlugin dolphinSchedulerPlugin);
|
||||
}
|
||||
|
|
@ -0,0 +1,99 @@
|
|||
/*
|
||||
* 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.plugin;
|
||||
|
||||
import static java.lang.String.format;
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkState;
|
||||
|
||||
import org.apache.dolphinscheduler.common.enums.PluginType;
|
||||
import org.apache.dolphinscheduler.dao.entity.PluginDefine;
|
||||
import org.apache.dolphinscheduler.spi.DolphinSchedulerPlugin;
|
||||
import org.apache.dolphinscheduler.spi.alert.AlertChannel;
|
||||
import org.apache.dolphinscheduler.spi.alert.AlertChannelFactory;
|
||||
import org.apache.dolphinscheduler.spi.classloader.ThreadContextClassLoader;
|
||||
import org.apache.dolphinscheduler.spi.params.PluginParamsTransfer;
|
||||
import org.apache.dolphinscheduler.spi.params.base.PluginParams;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* load the configured alert plugin and manager them
|
||||
*/
|
||||
public class AlertPluginManager extends AbstractDolphinPluginManager {
|
||||
private static final Logger logger = LoggerFactory.getLogger(AlertPluginManager.class);
|
||||
|
||||
private final Map<String, AlertChannelFactory> alertChannelFactoryMap = new ConcurrentHashMap<>();
|
||||
private final Map<String, AlertChannel> alertChannelMap = new ConcurrentHashMap<>();
|
||||
|
||||
public void addAlertChannelFactory(AlertChannelFactory alertChannelFactory) {
|
||||
requireNonNull(alertChannelFactory, "alertChannelFactory is null");
|
||||
|
||||
if (alertChannelFactoryMap.putIfAbsent(alertChannelFactory.getName(), alertChannelFactory) != null) {
|
||||
throw new IllegalArgumentException(format("Alert Plugin '{}' is already registered", alertChannelFactory.getName()));
|
||||
}
|
||||
|
||||
try {
|
||||
loadAlertChannel(alertChannelFactory.getName());
|
||||
} catch (Exception e) {
|
||||
throw new IllegalArgumentException(format("Alert Plugin '{}' is can not load .", alertChannelFactory.getName()));
|
||||
}
|
||||
}
|
||||
|
||||
protected void loadAlertChannel(String name) {
|
||||
requireNonNull(name, "name is null");
|
||||
|
||||
AlertChannelFactory alertChannelFactory = alertChannelFactoryMap.get(name);
|
||||
checkState(alertChannelFactory != null, "Alert Plugin {} is not registered", name);
|
||||
|
||||
try (ThreadContextClassLoader ignored = new ThreadContextClassLoader(alertChannelFactory.getClass().getClassLoader())) {
|
||||
AlertChannel alertChannel = alertChannelFactory.create();
|
||||
this.alertChannelMap.put(name, alertChannel);
|
||||
}
|
||||
|
||||
logger.info("-- Loaded Alert Plugin {} --", name);
|
||||
}
|
||||
|
||||
public Map<String, AlertChannelFactory> getAlertChannelFactoryMap() {
|
||||
return alertChannelFactoryMap;
|
||||
}
|
||||
|
||||
public Map<String, AlertChannel> getAlertChannelMap() {
|
||||
return alertChannelMap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void installPlugin(DolphinSchedulerPlugin dolphinSchedulerPlugin) {
|
||||
for (AlertChannelFactory alertChannelFactory : dolphinSchedulerPlugin.getAlertChannelFactorys()) {
|
||||
logger.info("Registering Alert Plugin '{}'", alertChannelFactory.getName());
|
||||
this.addAlertChannelFactory(alertChannelFactory);
|
||||
List<PluginParams> params = alertChannelFactory.getParams();
|
||||
String nameEn = alertChannelFactory.getName();
|
||||
String paramsJson = PluginParamsTransfer.transferParamsToJson(params);
|
||||
|
||||
PluginDefine pluginDefine = new PluginDefine(nameEn, PluginType.ALERT.getDesc(), paramsJson);
|
||||
pluginDao.addOrUpdatePluginDefine(pluginDefine);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,139 @@
|
|||
/*
|
||||
* 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.plugin;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.util.Enumeration;
|
||||
import java.util.List;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.Iterables;
|
||||
|
||||
class DolphinPluginClassLoader
|
||||
extends URLClassLoader {
|
||||
private static final ClassLoader PLATFORM_CLASS_LOADER = findPlatformClassLoader();
|
||||
|
||||
private final ClassLoader spiClassLoader;
|
||||
private final List<String> spiPackages;
|
||||
private final List<String> spiResources;
|
||||
|
||||
public DolphinPluginClassLoader(
|
||||
List<URL> urls,
|
||||
ClassLoader spiClassLoader,
|
||||
Iterable<String> spiPackages) {
|
||||
this(urls,
|
||||
spiClassLoader,
|
||||
spiPackages,
|
||||
Iterables.transform(spiPackages, DolphinPluginClassLoader::classNameToResource));
|
||||
}
|
||||
|
||||
private DolphinPluginClassLoader(
|
||||
List<URL> urls,
|
||||
ClassLoader spiClassLoader,
|
||||
Iterable<String> spiPackages,
|
||||
Iterable<String> spiResources) {
|
||||
// plugins should not have access to the system (application) class loader
|
||||
super(urls.toArray(new URL[urls.size()]), PLATFORM_CLASS_LOADER);
|
||||
this.spiClassLoader = requireNonNull(spiClassLoader, "spiClassLoader is null");
|
||||
this.spiPackages = ImmutableList.copyOf(spiPackages);
|
||||
this.spiResources = ImmutableList.copyOf(spiResources);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<?> loadClass(String name, boolean resolve)
|
||||
throws ClassNotFoundException {
|
||||
// grab the magic lock
|
||||
synchronized (getClassLoadingLock(name)) {
|
||||
// Check if class is in the loaded classes cache
|
||||
Class<?> cachedClass = findLoadedClass(name);
|
||||
if (cachedClass != null) {
|
||||
return resolveClass(cachedClass, resolve);
|
||||
}
|
||||
|
||||
// If this is an SPI class, only check SPI class loader
|
||||
if (isSpiClass(name)) {
|
||||
return resolveClass(spiClassLoader.loadClass(name), resolve);
|
||||
}
|
||||
|
||||
// Look for class locally
|
||||
return super.loadClass(name, resolve);
|
||||
}
|
||||
}
|
||||
|
||||
private Class<?> resolveClass(Class<?> clazz, boolean resolve) {
|
||||
if (resolve) {
|
||||
resolveClass(clazz);
|
||||
}
|
||||
return clazz;
|
||||
}
|
||||
|
||||
@Override
|
||||
public URL getResource(String name) {
|
||||
// If this is an SPI resource, only check SPI class loader
|
||||
if (isSpiResource(name)) {
|
||||
return spiClassLoader.getResource(name);
|
||||
}
|
||||
|
||||
// Look for resource locally
|
||||
return super.getResource(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enumeration<URL> getResources(String name)
|
||||
throws IOException {
|
||||
// If this is an SPI resource, use SPI resources
|
||||
if (isSpiClass(name)) {
|
||||
return spiClassLoader.getResources(name);
|
||||
}
|
||||
|
||||
// Use local resources
|
||||
return super.getResources(name);
|
||||
}
|
||||
|
||||
private boolean isSpiClass(String name) {
|
||||
return spiPackages.stream().anyMatch(name::startsWith);
|
||||
}
|
||||
|
||||
private boolean isSpiResource(String name) {
|
||||
return spiResources.stream().anyMatch(name::startsWith);
|
||||
}
|
||||
|
||||
private static String classNameToResource(String className) {
|
||||
return className.replace('.', '/');
|
||||
}
|
||||
|
||||
@SuppressWarnings("JavaReflectionMemberAccess")
|
||||
private static ClassLoader findPlatformClassLoader() {
|
||||
try {
|
||||
// use platform class loader on Java 9
|
||||
Method method = ClassLoader.class.getMethod("getPlatformClassLoader");
|
||||
return (ClassLoader) method.invoke(null);
|
||||
} catch (NoSuchMethodException ignored) {
|
||||
// use null class loader on Java 8
|
||||
return null;
|
||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,139 @@
|
|||
/*
|
||||
* 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.plugin;
|
||||
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
import static java.nio.file.Files.createDirectories;
|
||||
import static java.nio.file.Files.walkFileTree;
|
||||
|
||||
import static com.google.common.io.ByteStreams.toByteArray;
|
||||
|
||||
import org.apache.dolphinscheduler.spi.DolphinSchedulerPlugin;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.io.Writer;
|
||||
import java.nio.file.FileVisitResult;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.SimpleFileVisitor;
|
||||
import java.nio.file.attribute.BasicFileAttributes;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.objectweb.asm.ClassReader;
|
||||
import org.sonatype.aether.artifact.Artifact;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
|
||||
/**
|
||||
* The role of this class is to load the plugin class during development
|
||||
*/
|
||||
final class DolphinPluginDiscovery {
|
||||
private static final String JAVA_CLASS_FILE_SUFFIX = ".class";
|
||||
private static final String PLUGIN_SERVICES_FILE = "META-INF/services/" + DolphinSchedulerPlugin.class.getName();
|
||||
|
||||
private DolphinPluginDiscovery() {
|
||||
}
|
||||
|
||||
public static Set<String> discoverPluginsFromArtifact(Artifact artifact, ClassLoader classLoader)
|
||||
throws IOException {
|
||||
if (!artifact.getExtension().equals("dolphinscheduler-plugin")) {
|
||||
throw new RuntimeException("Unexpected extension for main artifact: " + artifact);
|
||||
}
|
||||
|
||||
File file = artifact.getFile();
|
||||
if (!file.getPath().endsWith("/target/classes")) {
|
||||
throw new RuntimeException("Unexpected file for main artifact: " + file);
|
||||
}
|
||||
if (!file.isDirectory()) {
|
||||
throw new RuntimeException("Main artifact file is not a directory: " + file);
|
||||
}
|
||||
|
||||
if (new File(file, PLUGIN_SERVICES_FILE).exists()) {
|
||||
return ImmutableSet.of();
|
||||
}
|
||||
|
||||
return listClasses(file.toPath()).stream()
|
||||
.filter(name -> classInterfaces(name, classLoader).contains(DolphinSchedulerPlugin.class.getName()))
|
||||
.collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
public static void writePluginServices(Iterable<String> plugins, File root)
|
||||
throws IOException {
|
||||
Path path = root.toPath().resolve(PLUGIN_SERVICES_FILE);
|
||||
createDirectories(path.getParent());
|
||||
try (Writer out = new OutputStreamWriter(new FileOutputStream(path.toFile()), UTF_8)) {
|
||||
for (String plugin : plugins) {
|
||||
out.write(plugin + "\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static List<String> listClasses(Path base)
|
||||
throws IOException {
|
||||
ImmutableList.Builder<String> list = ImmutableList.builder();
|
||||
walkFileTree(base, new SimpleFileVisitor<Path>() {
|
||||
@Override
|
||||
public FileVisitResult visitFile(Path file, BasicFileAttributes attributes) {
|
||||
if (file.getFileName().toString().endsWith(JAVA_CLASS_FILE_SUFFIX)) {
|
||||
String name = file.subpath(base.getNameCount(), file.getNameCount()).toString();
|
||||
list.add(javaName(name.substring(0, name.length() - JAVA_CLASS_FILE_SUFFIX.length())));
|
||||
}
|
||||
return FileVisitResult.CONTINUE;
|
||||
}
|
||||
});
|
||||
return list.build();
|
||||
}
|
||||
|
||||
private static List<String> classInterfaces(String name, ClassLoader classLoader) {
|
||||
ImmutableList.Builder<String> list = ImmutableList.builder();
|
||||
ClassReader reader = readClass(name, classLoader);
|
||||
for (String binaryName : reader.getInterfaces()) {
|
||||
list.add(javaName(binaryName));
|
||||
}
|
||||
if (reader.getSuperName() != null) {
|
||||
list.addAll(classInterfaces(javaName(reader.getSuperName()), classLoader));
|
||||
}
|
||||
return list.build();
|
||||
}
|
||||
|
||||
private static ClassReader readClass(String name, ClassLoader classLoader) {
|
||||
try (InputStream in = classLoader.getResourceAsStream(binaryName(name) + JAVA_CLASS_FILE_SUFFIX)) {
|
||||
if (in == null) {
|
||||
throw new RuntimeException("Failed to read class: " + name);
|
||||
}
|
||||
return new ClassReader(toByteArray(in));
|
||||
} catch (IOException e) {
|
||||
throw new UncheckedIOException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private static String binaryName(String javaName) {
|
||||
return javaName.replace('.', '/');
|
||||
}
|
||||
|
||||
private static String javaName(String binaryName) {
|
||||
return binaryName.replace('/', '.');
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,194 @@
|
|||
/*
|
||||
* 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.plugin;
|
||||
|
||||
import static java.lang.String.format;
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkState;
|
||||
|
||||
import org.apache.dolphinscheduler.spi.DolphinSchedulerPlugin;
|
||||
import org.apache.dolphinscheduler.spi.classloader.ThreadContextClassLoader;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.ServiceLoader;
|
||||
import java.util.Set;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.sonatype.aether.artifact.Artifact;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.Ordering;
|
||||
|
||||
import io.airlift.resolver.ArtifactResolver;
|
||||
|
||||
/**
|
||||
* Plugin Loader
|
||||
* Load Plugin from pom when development and run server in IDE
|
||||
* Load Plugin from the plugin directory when running on the server
|
||||
*/
|
||||
public class DolphinPluginLoader {
|
||||
private static final Logger logger = LoggerFactory.getLogger(DolphinPluginLoader.class);
|
||||
|
||||
/**
|
||||
* All third-party jar packages used in the classes which in spi package need to be add
|
||||
*/
|
||||
private static final ImmutableList<String> DOLPHIN_SPI_PACKAGES = ImmutableList.<String>builder()
|
||||
.add("org.apache.dolphinscheduler.spi.")
|
||||
.add("com.fasterxml.jackson.")
|
||||
.build();
|
||||
|
||||
private final File installedPluginsDir;
|
||||
private final List<String> configPlugins;
|
||||
private ArtifactResolver resolver = null;
|
||||
private final List<AbstractDolphinPluginManager> dolphinPluginManagerList;
|
||||
|
||||
public DolphinPluginLoader(DolphinPluginManagerConfig config, List<AbstractDolphinPluginManager> dolphinPluginManagerList) {
|
||||
installedPluginsDir = config.getInstalledPluginsDir();
|
||||
if (config.getPlugins() == null) {
|
||||
this.configPlugins = ImmutableList.of();
|
||||
} else {
|
||||
this.configPlugins = ImmutableList.copyOf(config.getPlugins());
|
||||
}
|
||||
|
||||
this.dolphinPluginManagerList = requireNonNull(dolphinPluginManagerList, "dolphinPluginManagerList is null");
|
||||
if (configPlugins != null && configPlugins.size() > 0) {
|
||||
this.resolver = new ArtifactResolver(config.getMavenLocalRepository(), config.getMavenRemoteRepository());
|
||||
}
|
||||
}
|
||||
|
||||
public void loadPlugins()
|
||||
throws Exception {
|
||||
for (File file : listPluginDirs(installedPluginsDir)) {
|
||||
if (file.isDirectory()) {
|
||||
loadPlugin(file.getAbsolutePath());
|
||||
}
|
||||
}
|
||||
|
||||
for (String plugin : configPlugins) {
|
||||
loadPlugin(plugin);
|
||||
}
|
||||
}
|
||||
|
||||
private void loadPlugin(String plugin)
|
||||
throws Exception {
|
||||
logger.info("-- Loading Alert plugin {} --", plugin);
|
||||
URLClassLoader pluginClassLoader = buildPluginClassLoader(plugin);
|
||||
try (ThreadContextClassLoader ignored = new ThreadContextClassLoader(pluginClassLoader)) {
|
||||
loadPlugin(pluginClassLoader);
|
||||
}
|
||||
logger.info("-- Finished loading Alert plugin {} --", plugin);
|
||||
}
|
||||
|
||||
private void loadPlugin(URLClassLoader pluginClassLoader) {
|
||||
ServiceLoader<DolphinSchedulerPlugin> serviceLoader = ServiceLoader.load(DolphinSchedulerPlugin.class, pluginClassLoader);
|
||||
List<DolphinSchedulerPlugin> plugins = ImmutableList.copyOf(serviceLoader);
|
||||
checkState(!plugins.isEmpty(), "No service providers the plugin {}", DolphinSchedulerPlugin.class.getName());
|
||||
for (DolphinSchedulerPlugin plugin : plugins) {
|
||||
logger.info("Installing {}", plugin.getClass().getName());
|
||||
for (AbstractDolphinPluginManager dolphinPluginManager : dolphinPluginManagerList) {
|
||||
dolphinPluginManager.installPlugin(plugin);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private URLClassLoader buildPluginClassLoader(String plugin)
|
||||
throws Exception {
|
||||
File file = new File(plugin);
|
||||
|
||||
if (!file.isDirectory() && (file.getName().equals("pom.xml") || file.getName().endsWith(".pom"))) {
|
||||
return buildPluginClassLoaderFromPom(file);
|
||||
}
|
||||
if (file.isDirectory()) {
|
||||
return buildPluginClassLoaderFromDirectory(file);
|
||||
} else {
|
||||
throw new IllegalArgumentException(format("plugin must be a pom file or directory {} .", plugin));
|
||||
}
|
||||
}
|
||||
|
||||
private URLClassLoader buildPluginClassLoaderFromPom(File pomFile)
|
||||
throws Exception {
|
||||
List<Artifact> artifacts = resolver.resolvePom(pomFile);
|
||||
URLClassLoader classLoader = createClassLoader(artifacts, pomFile.getPath());
|
||||
|
||||
Artifact artifact = artifacts.get(0);
|
||||
Set<String> plugins = DolphinPluginDiscovery.discoverPluginsFromArtifact(artifact, classLoader);
|
||||
if (!plugins.isEmpty()) {
|
||||
DolphinPluginDiscovery.writePluginServices(plugins, artifact.getFile());
|
||||
}
|
||||
|
||||
return classLoader;
|
||||
}
|
||||
|
||||
private URLClassLoader buildPluginClassLoaderFromDirectory(File dir)
|
||||
throws Exception {
|
||||
logger.info("Classpath for {}:", dir.getName());
|
||||
List<URL> urls = new ArrayList<>();
|
||||
for (File file : listPluginDirs(dir)) {
|
||||
logger.info(" {}", file);
|
||||
urls.add(file.toURI().toURL());
|
||||
}
|
||||
return createClassLoader(urls);
|
||||
}
|
||||
|
||||
private URLClassLoader createClassLoader(List<Artifact> artifacts, String name)
|
||||
throws IOException {
|
||||
logger.info("Classpath for {}:", name);
|
||||
List<URL> urls = new ArrayList<>();
|
||||
for (Artifact artifact : sortArtifacts(artifacts)) {
|
||||
if (artifact.getFile() == null) {
|
||||
throw new RuntimeException("Could not resolve artifact: " + artifact);
|
||||
}
|
||||
File file = artifact.getFile().getCanonicalFile();
|
||||
logger.info(" {}", file);
|
||||
urls.add(file.toURI().toURL());
|
||||
}
|
||||
return createClassLoader(urls);
|
||||
}
|
||||
|
||||
private URLClassLoader createClassLoader(List<URL> urls) {
|
||||
ClassLoader parent = getClass().getClassLoader();
|
||||
return new DolphinPluginClassLoader(urls, parent, DOLPHIN_SPI_PACKAGES);
|
||||
}
|
||||
|
||||
private static List<File> listPluginDirs(File installedPluginsDir) {
|
||||
if (installedPluginsDir != null && installedPluginsDir.isDirectory()) {
|
||||
File[] files = installedPluginsDir.listFiles();
|
||||
if (files != null) {
|
||||
Arrays.sort(files);
|
||||
return ImmutableList.copyOf(files);
|
||||
}
|
||||
}
|
||||
return ImmutableList.of();
|
||||
}
|
||||
|
||||
private static List<Artifact> sortArtifacts(List<Artifact> artifacts) {
|
||||
List<Artifact> list = new ArrayList<>(artifacts);
|
||||
Collections.sort(list, Ordering.natural().nullsLast().onResultOf(Artifact::getFile));
|
||||
return list;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,121 @@
|
|||
/*
|
||||
* 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.plugin;
|
||||
|
||||
import static java.lang.String.format;
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
|
||||
import com.google.common.base.Splitter;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
/**
|
||||
* Dolphin Scheduler Plugin Manager Config
|
||||
*/
|
||||
public class DolphinPluginManagerConfig {
|
||||
|
||||
/**
|
||||
* The dir of the Alert Plugin in.
|
||||
* When AlertServer is running on the server, it will load the Alert Plugin from this directory.
|
||||
*/
|
||||
private File installedPluginsDir;
|
||||
|
||||
/**
|
||||
* The plugin should be load.
|
||||
* The installedPluginsDir is empty when we development and run server in IDEA. Then we can config which plugin should be load by param name alert.plugin.binding in the alert.properties file
|
||||
*/
|
||||
private List<String> plugins;
|
||||
|
||||
/**
|
||||
* Development, When AlertServer is running on IDE, AlertPluginLoad can load Alert Plugin from local Repository.
|
||||
*/
|
||||
private String mavenLocalRepository = System.getProperty("user.home") + "/.m2/repository";
|
||||
private List<String> mavenRemoteRepository = ImmutableList.of("http://repo1.maven.org/maven2/");
|
||||
|
||||
public File getInstalledPluginsDir() {
|
||||
return installedPluginsDir;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param pluginDir
|
||||
*/
|
||||
public DolphinPluginManagerConfig setInstalledPluginsDir(String pluginDir) {
|
||||
requireNonNull(pluginDir, "pluginDir can not be null");
|
||||
File pluginDirFile = new File(pluginDir);
|
||||
if (!pluginDirFile.exists()) {
|
||||
throw new IllegalArgumentException(format("plugin dir not exists ! {}", pluginDirFile.getPath()));
|
||||
}
|
||||
this.installedPluginsDir = pluginDirFile;
|
||||
return this;
|
||||
}
|
||||
|
||||
public List<String> getPlugins() {
|
||||
return plugins;
|
||||
}
|
||||
|
||||
public DolphinPluginManagerConfig setPlugins(List<String> plugins) {
|
||||
this.plugins = plugins;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* When development and run server in IDE, this method can set plugins in alert.properties .
|
||||
* Then when you start AlertServer in IDE, the plugin can be load.
|
||||
* eg:
|
||||
* file: alert.properties
|
||||
* alert.plugin=\
|
||||
* ../dolphinscheduler-alert-plugin/dolphinscheduler-alert-email/pom.xml, \
|
||||
* ../dolphinscheduler-alert-plugin/dolphinscheduler-alert-wechat/pom.xml
|
||||
*
|
||||
* @param plugins
|
||||
* @return
|
||||
*/
|
||||
public DolphinPluginManagerConfig setPlugins(String plugins) {
|
||||
if (plugins == null) {
|
||||
this.plugins = null;
|
||||
} else {
|
||||
this.plugins = ImmutableList.copyOf(Splitter.on(',').omitEmptyStrings().trimResults().split(plugins));
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getMavenLocalRepository() {
|
||||
return mavenLocalRepository;
|
||||
}
|
||||
|
||||
public DolphinPluginManagerConfig setMavenLocalRepository(String mavenLocalRepository) {
|
||||
this.mavenLocalRepository = mavenLocalRepository;
|
||||
return this;
|
||||
}
|
||||
|
||||
public List<String> getMavenRemoteRepository() {
|
||||
return mavenRemoteRepository;
|
||||
}
|
||||
|
||||
public DolphinPluginManagerConfig setMavenRemoteRepository(List<String> mavenRemoteRepository) {
|
||||
this.mavenRemoteRepository = mavenRemoteRepository;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DolphinPluginManagerConfig setMavenRemoteRepository(String mavenRemoteRepository) {
|
||||
this.mavenRemoteRepository = ImmutableList.copyOf(Splitter.on(',').omitEmptyStrings().trimResults().split(mavenRemoteRepository));
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,147 +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.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;
|
||||
import org.apache.dolphinscheduler.plugin.api.AlertPlugin;
|
||||
import org.apache.dolphinscheduler.plugin.model.AlertData;
|
||||
import org.apache.dolphinscheduler.plugin.model.AlertInfo;
|
||||
import org.apache.dolphinscheduler.plugin.model.PluginName;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* EmailAlertPlugin
|
||||
* <p>
|
||||
* This plugin is a default plugin, and mix up email and enterprise wechat, because adapt with former alert behavior
|
||||
*/
|
||||
public class EmailAlertPlugin implements AlertPlugin {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(EmailAlertPlugin.class);
|
||||
|
||||
private PluginName pluginName;
|
||||
|
||||
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();
|
||||
this.pluginName.setEnglish(Constants.PLUGIN_DEFAULT_EMAIL_EN);
|
||||
this.pluginName.setChinese(Constants.PLUGIN_DEFAULT_EMAIL_CH);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return Constants.PLUGIN_DEFAULT_EMAIL_ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PluginName getName() {
|
||||
return pluginName;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Map<String, Object> process(AlertInfo info) {
|
||||
Map<String, Object> retMaps = new HashMap<>();
|
||||
|
||||
AlertData alert = info.getAlertData();
|
||||
|
||||
List<String> receiversList = (List<String>) info.getProp(Constants.PLUGIN_DEFAULT_EMAIL_RECEIVERS);
|
||||
|
||||
// receiving group list
|
||||
// custom receiver
|
||||
String receivers = alert.getReceivers();
|
||||
if (StringUtils.isNotEmpty(receivers)) {
|
||||
String[] splits = receivers.split(",");
|
||||
receiversList.addAll(Arrays.asList(splits));
|
||||
}
|
||||
|
||||
List<String> receiversCcList = new ArrayList<>();
|
||||
// Custom Copier
|
||||
String receiversCc = alert.getReceiversCc();
|
||||
if (StringUtils.isNotEmpty(receiversCc)) {
|
||||
String[] splits = receiversCc.split(",");
|
||||
receiversCcList.addAll(Arrays.asList(splits));
|
||||
}
|
||||
|
||||
if (CollectionUtils.isEmpty(receiversList) && CollectionUtils.isEmpty(receiversCcList)) {
|
||||
logger.warn("alert send error : At least one receiver address required");
|
||||
retMaps.put(Constants.STATUS, "false");
|
||||
retMaps.put(Constants.MESSAGE, "execution failure,At least one receiver address required.");
|
||||
return retMaps;
|
||||
}
|
||||
|
||||
retMaps = emailManager.send(receiversList, receiversCcList, alert.getTitle(), alert.getContent(),
|
||||
alert.getShowType());
|
||||
|
||||
//send flag
|
||||
boolean flag = false;
|
||||
|
||||
if (retMaps == null) {
|
||||
retMaps = new HashMap<>();
|
||||
retMaps.put(Constants.MESSAGE, "alert send error.");
|
||||
retMaps.put(Constants.STATUS, "false");
|
||||
logger.info("alert send error : {}", retMaps.get(Constants.MESSAGE));
|
||||
return retMaps;
|
||||
}
|
||||
|
||||
flag = Boolean.parseBoolean(String.valueOf(retMaps.get(Constants.STATUS)));
|
||||
|
||||
if (flag) {
|
||||
logger.info("alert send success");
|
||||
retMaps.put(Constants.MESSAGE, "email send success.");
|
||||
if (EnterpriseWeChatUtils.isEnable()) {
|
||||
logger.info("Enterprise WeChat is enable!");
|
||||
try {
|
||||
String token = EnterpriseWeChatUtils.getToken();
|
||||
weChatManager.send(info, token);
|
||||
} catch (Exception e) {
|
||||
logger.error(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
if (DingTalkUtils.IS_ENABLE_DING_TALK) {
|
||||
logger.info("Ding Talk is enable.");
|
||||
dingTalkManager.send(info);
|
||||
}
|
||||
|
||||
} else {
|
||||
retMaps.put(Constants.MESSAGE, "alert send error.");
|
||||
logger.info("alert send error : {}", retMaps.get(Constants.MESSAGE));
|
||||
}
|
||||
|
||||
return retMaps;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* 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.processor;
|
||||
|
||||
import org.apache.dolphinscheduler.alert.plugin.AlertPluginManager;
|
||||
import org.apache.dolphinscheduler.alert.runner.AlertSender;
|
||||
import org.apache.dolphinscheduler.common.utils.Preconditions;
|
||||
import org.apache.dolphinscheduler.dao.AlertDao;
|
||||
import org.apache.dolphinscheduler.dao.PluginDao;
|
||||
import org.apache.dolphinscheduler.remote.command.Command;
|
||||
import org.apache.dolphinscheduler.remote.command.CommandType;
|
||||
import org.apache.dolphinscheduler.remote.command.alert.AlertSendRequestCommand;
|
||||
import org.apache.dolphinscheduler.remote.command.alert.AlertSendResponseCommand;
|
||||
import org.apache.dolphinscheduler.remote.processor.NettyRequestProcessor;
|
||||
import org.apache.dolphinscheduler.remote.utils.JsonSerializer;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import io.netty.channel.Channel;
|
||||
|
||||
/**
|
||||
* alert request processor
|
||||
*/
|
||||
public class AlertRequestProcessor implements NettyRequestProcessor {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(AlertRequestProcessor.class);
|
||||
private AlertDao alertDao;
|
||||
private PluginDao pluginDao;
|
||||
private AlertPluginManager alertPluginManager;
|
||||
|
||||
public AlertRequestProcessor(AlertDao alertDao, AlertPluginManager alertPluginManager, PluginDao pluginDao) {
|
||||
this.alertDao = alertDao;
|
||||
this.pluginDao = pluginDao;
|
||||
this.alertPluginManager = alertPluginManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void process(Channel channel, Command command) {
|
||||
Preconditions.checkArgument(CommandType.ALERT_SEND_REQUEST == command.getType(),
|
||||
String.format("invalid command type : %s", command.getType()));
|
||||
|
||||
AlertSendRequestCommand alertSendRequestCommand = JsonSerializer.deserialize(
|
||||
command.getBody(), AlertSendRequestCommand.class);
|
||||
logger.info("received command : {}", alertSendRequestCommand);
|
||||
|
||||
AlertSender alertSender = new AlertSender(alertDao, alertPluginManager, pluginDao);
|
||||
AlertSendResponseCommand alertSendResponseCommand = alertSender.syncHandler(alertSendRequestCommand.getGroupId(), alertSendRequestCommand.getTitle(), alertSendRequestCommand.getContent());
|
||||
channel.writeAndFlush(alertSendResponseCommand.convert2Command(command.getOpaque()));
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -14,23 +14,28 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.apache.dolphinscheduler.alert.runner;
|
||||
|
||||
import org.apache.dolphinscheduler.alert.utils.Constants;
|
||||
import org.apache.dolphinscheduler.alert.plugin.AlertPluginManager;
|
||||
import org.apache.dolphinscheduler.common.enums.AlertStatus;
|
||||
import org.apache.dolphinscheduler.common.plugin.PluginManager;
|
||||
import org.apache.dolphinscheduler.common.utils.CollectionUtils;
|
||||
import org.apache.dolphinscheduler.dao.AlertDao;
|
||||
import org.apache.dolphinscheduler.dao.PluginDao;
|
||||
import org.apache.dolphinscheduler.dao.entity.Alert;
|
||||
import org.apache.dolphinscheduler.dao.entity.User;
|
||||
import org.apache.dolphinscheduler.plugin.api.AlertPlugin;
|
||||
import org.apache.dolphinscheduler.plugin.model.AlertData;
|
||||
import org.apache.dolphinscheduler.plugin.model.AlertInfo;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.apache.dolphinscheduler.dao.entity.AlertPluginInstance;
|
||||
import org.apache.dolphinscheduler.remote.command.alert.AlertSendResponseCommand;
|
||||
import org.apache.dolphinscheduler.remote.command.alert.AlertSendResponseResult;
|
||||
import org.apache.dolphinscheduler.spi.alert.AlertChannel;
|
||||
import org.apache.dolphinscheduler.spi.alert.AlertData;
|
||||
import org.apache.dolphinscheduler.spi.alert.AlertInfo;
|
||||
import org.apache.dolphinscheduler.spi.alert.AlertResult;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* alert sender
|
||||
|
|
@ -41,60 +46,135 @@ public class AlertSender {
|
|||
|
||||
private List<Alert> alertList;
|
||||
private AlertDao alertDao;
|
||||
private PluginManager pluginManager;
|
||||
private PluginDao pluginDao;
|
||||
private AlertPluginManager alertPluginManager;
|
||||
|
||||
public AlertSender() {
|
||||
public AlertSender(AlertPluginManager alertPluginManager) {
|
||||
this.alertPluginManager = alertPluginManager;
|
||||
}
|
||||
|
||||
public AlertSender(List<Alert> alertList, AlertDao alertDao, PluginManager pluginManager) {
|
||||
public AlertSender(AlertDao alertDao, AlertPluginManager alertPluginManager, PluginDao pluginDao) {
|
||||
super();
|
||||
this.alertDao = alertDao;
|
||||
this.pluginDao = pluginDao;
|
||||
this.alertPluginManager = alertPluginManager;
|
||||
}
|
||||
|
||||
public AlertSender(List<Alert> alertList, AlertDao alertDao, AlertPluginManager alertPluginManager, PluginDao pluginDao) {
|
||||
super();
|
||||
this.alertList = alertList;
|
||||
this.alertDao = alertDao;
|
||||
this.pluginManager = pluginManager;
|
||||
this.pluginDao = pluginDao;
|
||||
this.alertPluginManager = alertPluginManager;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
List<User> users;
|
||||
Map<String, Object> retMaps = null;
|
||||
for (Alert alert : alertList) {
|
||||
users = alertDao.listUserByAlertgroupId(alert.getAlertGroupId());
|
||||
|
||||
// receiving group list
|
||||
List<String> receiversList = new ArrayList<>();
|
||||
for (User user : users) {
|
||||
receiversList.add(user.getEmail());
|
||||
//get alert group from alert
|
||||
int alertGroupId = alert.getAlertGroupId();
|
||||
List<AlertPluginInstance> alertInstanceList = alertDao.listInstanceByAlertGroupId(alertGroupId);
|
||||
if (CollectionUtils.isEmpty(alertInstanceList)) {
|
||||
logger.error("send alert msg fail,no bind plugin instance.");
|
||||
return;
|
||||
}
|
||||
|
||||
AlertData alertData = new AlertData();
|
||||
alertData.setId(alert.getId())
|
||||
.setAlertGroupId(alert.getAlertGroupId())
|
||||
.setContent(alert.getContent())
|
||||
.setLog(alert.getLog())
|
||||
.setReceivers(alert.getReceivers())
|
||||
.setReceiversCc(alert.getReceiversCc())
|
||||
.setShowType(alert.getShowType().getDescp())
|
||||
.setTitle(alert.getTitle());
|
||||
.setContent(alert.getContent())
|
||||
.setLog(alert.getLog())
|
||||
.setTitle(alert.getTitle());
|
||||
|
||||
AlertInfo alertInfo = new AlertInfo();
|
||||
alertInfo.setAlertData(alertData);
|
||||
for (AlertPluginInstance instance : alertInstanceList) {
|
||||
|
||||
alertInfo.addProp("receivers", receiversList);
|
||||
AlertResult alertResult = this.alertResultHandler(instance, alertData);
|
||||
AlertStatus alertStatus = Boolean.parseBoolean(String.valueOf(alertResult.getStatus())) ? AlertStatus.EXECUTION_SUCCESS : AlertStatus.EXECUTION_FAILURE;
|
||||
alertDao.updateAlert(alertStatus, alertResult.getMessage(), alert.getId());
|
||||
|
||||
AlertPlugin emailPlugin = pluginManager.findOne(Constants.PLUGIN_DEFAULT_EMAIL_ID);
|
||||
retMaps = emailPlugin.process(alertInfo);
|
||||
|
||||
if (retMaps == null) {
|
||||
alertDao.updateAlert(AlertStatus.EXECUTION_FAILURE, "alert send error", alert.getId());
|
||||
logger.error("alert send error : return value is null");
|
||||
} else if (!Boolean.parseBoolean(String.valueOf(retMaps.get(Constants.STATUS)))) {
|
||||
alertDao.updateAlert(AlertStatus.EXECUTION_FAILURE, String.valueOf(retMaps.get(Constants.MESSAGE)), alert.getId());
|
||||
logger.error("alert send error : {}", retMaps.get(Constants.MESSAGE));
|
||||
} else {
|
||||
alertDao.updateAlert(AlertStatus.EXECUTION_SUCCESS, (String) retMaps.get(Constants.MESSAGE), alert.getId());
|
||||
logger.info("alert send success");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* sync send alert handler
|
||||
*
|
||||
* @param alertGroupId alertGroupId
|
||||
* @param title title
|
||||
* @param content content
|
||||
* @return AlertSendResponseCommand
|
||||
*/
|
||||
public AlertSendResponseCommand syncHandler(int alertGroupId, String title, String content) {
|
||||
|
||||
List<AlertPluginInstance> alertInstanceList = alertDao.listInstanceByAlertGroupId(alertGroupId);
|
||||
AlertData alertData = new AlertData();
|
||||
alertData.setContent(title)
|
||||
.setTitle(content);
|
||||
|
||||
boolean sendResponseStatus = true;
|
||||
List<AlertSendResponseResult> sendResponseResults = new ArrayList<>();
|
||||
|
||||
if (CollectionUtils.isEmpty(alertInstanceList)) {
|
||||
sendResponseStatus = false;
|
||||
AlertSendResponseResult alertSendResponseResult = new AlertSendResponseResult();
|
||||
String message = String.format("Alert GroupId %s send error : not found alert instance", alertGroupId);
|
||||
alertSendResponseResult.setStatus(sendResponseStatus);
|
||||
alertSendResponseResult.setMessage(message);
|
||||
sendResponseResults.add(alertSendResponseResult);
|
||||
logger.error("Alert GroupId {} send error : not found alert instance", alertGroupId);
|
||||
return new AlertSendResponseCommand(sendResponseStatus, sendResponseResults);
|
||||
}
|
||||
|
||||
for (AlertPluginInstance instance : alertInstanceList) {
|
||||
AlertResult alertResult = this.alertResultHandler(instance, alertData);
|
||||
AlertSendResponseResult alertSendResponseResult = new AlertSendResponseResult(
|
||||
Boolean.parseBoolean(String.valueOf(alertResult.getStatus())), alertResult.getMessage());
|
||||
sendResponseStatus = sendResponseStatus && alertSendResponseResult.getStatus();
|
||||
sendResponseResults.add(alertSendResponseResult);
|
||||
}
|
||||
|
||||
return new AlertSendResponseCommand(sendResponseStatus, sendResponseResults);
|
||||
}
|
||||
|
||||
/**
|
||||
* alert result handler
|
||||
*
|
||||
* @param instance instance
|
||||
* @param alertData alertData
|
||||
* @return AlertResult
|
||||
*/
|
||||
private AlertResult alertResultHandler(AlertPluginInstance instance, AlertData alertData) {
|
||||
String pluginName = pluginDao.getPluginDefineById(instance.getPluginDefineId()).getPluginName();
|
||||
AlertChannel alertChannel = alertPluginManager.getAlertChannelMap().get(pluginName);
|
||||
AlertResult alertResultExtend = new AlertResult();
|
||||
String pluginInstanceName = instance.getInstanceName();
|
||||
if (alertChannel == null) {
|
||||
String message = String.format("Alert Plugin %s send error : return value is null", pluginInstanceName);
|
||||
alertResultExtend.setStatus(String.valueOf(false));
|
||||
alertResultExtend.setMessage(message);
|
||||
logger.error("Alert Plugin {} send error : not found plugin {}", pluginInstanceName, pluginName);
|
||||
return alertResultExtend;
|
||||
}
|
||||
|
||||
AlertInfo alertInfo = new AlertInfo();
|
||||
alertInfo.setAlertData(alertData);
|
||||
alertInfo.setAlertParams(instance.getPluginInstanceParams());
|
||||
AlertResult alertResult = alertChannel.process(alertInfo);
|
||||
|
||||
if (alertResult == null) {
|
||||
String message = String.format("Alert Plugin %s send error : return alertResult value is null", pluginInstanceName);
|
||||
alertResultExtend.setStatus(String.valueOf(false));
|
||||
alertResultExtend.setMessage(message);
|
||||
logger.info("Alert Plugin {} send error : return alertResult value is null", pluginInstanceName);
|
||||
} else if (!Boolean.parseBoolean(String.valueOf(alertResult.getStatus()))) {
|
||||
alertResultExtend.setStatus(String.valueOf(false));
|
||||
alertResultExtend.setMessage(alertResult.getMessage());
|
||||
logger.info("Alert Plugin {} send error : {}", pluginInstanceName, alertResult.getMessage());
|
||||
} else {
|
||||
String message = String.format("Alert Plugin %s send success", pluginInstanceName);
|
||||
alertResultExtend.setStatus(String.valueOf(true));
|
||||
alertResultExtend.setMessage(message);
|
||||
logger.info("Alert Plugin {} send success", pluginInstanceName);
|
||||
}
|
||||
return alertResultExtend;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,177 +30,9 @@ public class Constants {
|
|||
*/
|
||||
public static final String ALERT_PROPERTIES_PATH = "/alert.properties";
|
||||
|
||||
public static final String DATA_SOURCE_PROPERTIES_PATH = "/dao/data_source.properties";
|
||||
|
||||
public static final String SINGLE_SLASH = "/";
|
||||
|
||||
/**
|
||||
* UTF-8
|
||||
*/
|
||||
public static final String UTF_8 = "UTF-8";
|
||||
|
||||
public static final String STATUS = "status";
|
||||
|
||||
public static final String MESSAGE = "message";
|
||||
|
||||
public static final String MAIL_PROTOCOL = "mail.protocol";
|
||||
|
||||
public static final String MAIL_SERVER_HOST = "mail.server.host";
|
||||
|
||||
public static final String MAIL_SERVER_PORT = "mail.server.port";
|
||||
|
||||
public static final String MAIL_SENDER = "mail.sender";
|
||||
|
||||
public static final String MAIL_USER = "mail.user";
|
||||
|
||||
public static final String MAIL_PASSWD = "mail.passwd";
|
||||
|
||||
public static final String XLS_FILE_PATH = "xls.file.path";
|
||||
|
||||
public static final String MAIL_HOST = "mail.smtp.host";
|
||||
|
||||
public static final String MAIL_PORT = "mail.smtp.port";
|
||||
|
||||
public static final String MAIL_SMTP_AUTH = "mail.smtp.auth";
|
||||
|
||||
public static final String MAIL_TRANSPORT_PROTOCOL = "mail.transport.protocol";
|
||||
|
||||
public static final String MAIL_SMTP_STARTTLS_ENABLE = "mail.smtp.starttls.enable";
|
||||
|
||||
public static final String MAIL_SMTP_SSL_ENABLE = "mail.smtp.ssl.enable";
|
||||
|
||||
public static final String MAIL_SMTP_SSL_TRUST = "mail.smtp.ssl.trust";
|
||||
|
||||
public static final String TEXT_HTML_CHARSET_UTF_8 = "text/html;charset=utf-8";
|
||||
|
||||
public static final String STRING_TRUE = "true";
|
||||
|
||||
public static final String EXCEL_SUFFIX_XLS = ".xls";
|
||||
|
||||
public static final int NUMBER_1000 = 1000;
|
||||
|
||||
public static final String SPRING_DATASOURCE_DRIVER_CLASS_NAME = "spring.datasource.driver-class-name";
|
||||
|
||||
public static final String SPRING_DATASOURCE_URL = "spring.datasource.url";
|
||||
|
||||
public static final String SPRING_DATASOURCE_USERNAME = "spring.datasource.username";
|
||||
|
||||
public static final String SPRING_DATASOURCE_PASSWORD = "spring.datasource.password";
|
||||
|
||||
public static final String SPRING_DATASOURCE_VALIDATION_QUERY_TIMEOUT = "spring.datasource.validationQueryTimeout";
|
||||
|
||||
public static final String SPRING_DATASOURCE_INITIAL_SIZE = "spring.datasource.initialSize";
|
||||
|
||||
public static final String SPRING_DATASOURCE_MIN_IDLE = "spring.datasource.minIdle";
|
||||
|
||||
public static final String SPRING_DATASOURCE_MAX_ACTIVE = "spring.datasource.maxActive";
|
||||
|
||||
public static final String SPRING_DATASOURCE_MAX_WAIT = "spring.datasource.maxWait";
|
||||
|
||||
public static final String SPRING_DATASOURCE_TIME_BETWEEN_EVICTION_RUNS_MILLIS = "spring.datasource.timeBetweenEvictionRunsMillis";
|
||||
|
||||
public static final String SPRING_DATASOURCE_MIN_EVICTABLE_IDLE_TIME_MILLIS = "spring.datasource.minEvictableIdleTimeMillis";
|
||||
|
||||
public static final String SPRING_DATASOURCE_VALIDATION_QUERY = "spring.datasource.validationQuery";
|
||||
|
||||
public static final String SPRING_DATASOURCE_TEST_WHILE_IDLE = "spring.datasource.testWhileIdle";
|
||||
|
||||
public static final String SPRING_DATASOURCE_TEST_ON_BORROW = "spring.datasource.testOnBorrow";
|
||||
|
||||
public static final String SPRING_DATASOURCE_TEST_ON_RETURN = "spring.datasource.testOnReturn";
|
||||
|
||||
public static final String SPRING_DATASOURCE_POOL_PREPARED_STATEMENTS = "spring.datasource.poolPreparedStatements";
|
||||
|
||||
public static final String SPRING_DATASOURCE_DEFAULT_AUTO_COMMIT = "spring.datasource.defaultAutoCommit";
|
||||
|
||||
public static final String SPRING_DATASOURCE_KEEP_ALIVE = "spring.datasource.keepAlive";
|
||||
|
||||
public static final String SPRING_DATASOURCE_MAX_POOL_PREPARED_STATEMENT_PER_CONNECTION_SIZE = "spring.datasource.maxPoolPreparedStatementPerConnectionSize";
|
||||
|
||||
public static final String DEVELOPMENT = "development";
|
||||
|
||||
public static final String TR = "<tr>";
|
||||
|
||||
public static final String TD = "<td>";
|
||||
|
||||
public static final String TD_END = "</td>";
|
||||
|
||||
public static final String TR_END = "</tr>";
|
||||
|
||||
public static final String TITLE = "title";
|
||||
|
||||
public static final String CONTENT = "content";
|
||||
|
||||
public static final String TH = "<th>";
|
||||
|
||||
public static final String TH_END = "</th>";
|
||||
/** default alert plugin dir **/
|
||||
public static final String ALERT_PLUGIN_PATH = "./lib/plugin/alert";
|
||||
|
||||
public static final int ALERT_SCAN_INTERVAL = 5000;
|
||||
|
||||
public static final String MARKDOWN_QUOTE = ">";
|
||||
|
||||
public static final String MARKDOWN_ENTER = "\n";
|
||||
|
||||
public static final String ENTERPRISE_WECHAT_ENABLE = "enterprise.wechat.enable";
|
||||
|
||||
public static final String ENTERPRISE_WECHAT_CORP_ID = "enterprise.wechat.corp.id";
|
||||
|
||||
public static final String ENTERPRISE_WECHAT_SECRET = "enterprise.wechat.secret";
|
||||
|
||||
public static final String ENTERPRISE_WECHAT_TOKEN_URL = "enterprise.wechat.token.url";
|
||||
|
||||
public static final String ENTERPRISE_WECHAT_PUSH_URL = "enterprise.wechat.push.url";
|
||||
|
||||
public static final String ENTERPRISE_WECHAT_TEAM_SEND_MSG = "enterprise.wechat.team.send.msg";
|
||||
|
||||
public static final String ENTERPRISE_WECHAT_USER_SEND_MSG = "enterprise.wechat.user.send.msg";
|
||||
|
||||
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";
|
||||
|
||||
public static final String HTML_HEADER_PREFIX = "<!DOCTYPE HTML PUBLIC '-//W3C//DTD HTML 4.01 Transitional//EN' 'http://www.w3.org/TR/html4/loose.dtd'>"
|
||||
+ "<html><head><title>dolphinscheduler</title><meta name='Keywords' content=''>"
|
||||
+ "<meta name='Description' content=''>"
|
||||
+ "<style type=\"text/css\">table {margin-top:0px;padding-top:0px;border:1px solid;font-size: 14px;color: #333333;border-width: 1px;border-color: #666666;border-collapse: collapse;}"
|
||||
+ "table th {border-width: 1px;padding: 8px;border-style: solid;border-color: #666666;background-color: #dedede;text-align: left;}"
|
||||
+ "table td {border-width: 1px;padding: 8px;border-style: solid;border-color: #666666;background-color: #ffffff;text-align: left;}</style>"
|
||||
+ "/head><body style=\"margin:0;padding:0\"><table border=\"1px\" cellpadding=\"5px\" cellspacing=\"-10px\"> ";
|
||||
|
||||
public static final String TABLE_BODY_HTML_TAIL = "</table></body></html>";
|
||||
|
||||
/**
|
||||
* plugin config
|
||||
*/
|
||||
public static final String PLUGIN_DIR = "plugin.dir";
|
||||
|
||||
public static final String PLUGIN_DEFAULT_EMAIL_ID = "email";
|
||||
|
||||
public static final String PLUGIN_DEFAULT_EMAIL_CH = "邮件";
|
||||
|
||||
public static final String PLUGIN_DEFAULT_EMAIL_EN = "email";
|
||||
|
||||
public static final String PLUGIN_DEFAULT_EMAIL_RECEIVERS = "receivers";
|
||||
|
||||
public static final String PLUGIN_DEFAULT_EMAIL_RECEIVERCCS = "receiverCcs";
|
||||
|
||||
public static final String RETMAP_MSG = "msg";
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,141 +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.*;
|
||||
|
||||
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 IS_ENABLE_DING_TALK = PropertyUtils.getBoolean(Constants.DINGTALK_ENABLE);
|
||||
private static final String DING_TASK_URL = PropertyUtils.getString(Constants.DINGTALK_WEBHOOK);
|
||||
private static final String KEYWORD = PropertyUtils.getString(Constants.DINGTALK_KEYWORD);
|
||||
private static final Boolean IS_ENABLE_PROXY = 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);
|
||||
|
||||
private DingTalkUtils() {
|
||||
throw new IllegalStateException(DingTalkUtils.class.getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 (Boolean.TRUE.equals(IS_ENABLE_PROXY)) {
|
||||
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);
|
||||
return resp;
|
||||
} finally {
|
||||
httpClient.close();
|
||||
}
|
||||
}
|
||||
|
||||
public static HttpPost constructHttpPost(String msg, String charset) {
|
||||
HttpPost post = new HttpPost(DING_TASK_URL);
|
||||
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));
|
||||
return HttpClients.custom().setDefaultCredentialsProvider(provider).build();
|
||||
}
|
||||
|
||||
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<>();
|
||||
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);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,286 +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.ShowType;
|
||||
import org.apache.dolphinscheduler.common.utils.JSONUtils;
|
||||
import org.apache.dolphinscheduler.common.utils.StringUtils;
|
||||
import org.apache.dolphinscheduler.plugin.model.AlertData;
|
||||
|
||||
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 AGENT_ID_REG_EXP = "\\{agentId}";
|
||||
private static final String MSG_REG_EXP = "\\{msg}";
|
||||
private static final String USER_REG_EXP = "\\{toUser}";
|
||||
|
||||
private EnterpriseWeChatUtils() {
|
||||
throw new IllegalStateException(EnterpriseWeChatUtils.class.getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
return map == null ? null : map.get("access_token");
|
||||
} 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(AGENT_ID_REG_EXP, agentId)
|
||||
.replaceAll(MSG_REG_EXP, 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(AGENT_ID_REG_EXP, agentId)
|
||||
.replaceAll(MSG_REG_EXP, 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(USER_REG_EXP, toUser)
|
||||
.replaceAll(AGENT_ID_REG_EXP, agentId)
|
||||
.replaceAll(MSG_REG_EXP, 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(USER_REG_EXP, listUser)
|
||||
.replaceAll(AGENT_ID_REG_EXP, agentId)
|
||||
.replaceAll(MSG_REG_EXP, 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(AlertData alert) {
|
||||
String result = "";
|
||||
if (alert.getShowType().equals(ShowType.TABLE.getDescp())) {
|
||||
result = markdownTable(alert.getTitle(), alert.getContent());
|
||||
} else if (alert.getShowType().equals(ShowType.TEXT.getDescp())) {
|
||||
result = markdownText(alert.getTitle(), alert.getContent());
|
||||
}
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,375 +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.alert.template.AlertTemplate;
|
||||
import org.apache.dolphinscheduler.alert.template.AlertTemplateFactory;
|
||||
import org.apache.dolphinscheduler.common.enums.ShowType;
|
||||
import org.apache.dolphinscheduler.common.utils.CollectionUtils;
|
||||
import org.apache.dolphinscheduler.common.utils.StringUtils;
|
||||
|
||||
import org.apache.commons.mail.EmailException;
|
||||
import org.apache.commons.mail.HtmlEmail;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
import javax.mail.Authenticator;
|
||||
import javax.mail.Message;
|
||||
import javax.mail.MessagingException;
|
||||
import javax.mail.PasswordAuthentication;
|
||||
import javax.mail.Session;
|
||||
import javax.mail.Transport;
|
||||
import javax.mail.internet.InternetAddress;
|
||||
import javax.mail.internet.MimeBodyPart;
|
||||
import javax.mail.internet.MimeMessage;
|
||||
import javax.mail.internet.MimeMultipart;
|
||||
import javax.mail.internet.MimeUtility;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* mail utils
|
||||
*/
|
||||
public class MailUtils {
|
||||
|
||||
public static final Logger logger = LoggerFactory.getLogger(MailUtils.class);
|
||||
|
||||
public static final String MAIL_PROTOCOL = PropertyUtils.getString(Constants.MAIL_PROTOCOL);
|
||||
|
||||
public static final String MAIL_SERVER_HOST = PropertyUtils.getString(Constants.MAIL_SERVER_HOST);
|
||||
|
||||
public static final Integer MAIL_SERVER_PORT = PropertyUtils.getInt(Constants.MAIL_SERVER_PORT);
|
||||
|
||||
public static final String MAIL_SENDER = PropertyUtils.getString(Constants.MAIL_SENDER);
|
||||
|
||||
public static final String MAIL_USER = PropertyUtils.getString(Constants.MAIL_USER);
|
||||
|
||||
public static final String MAIL_PASSWD = PropertyUtils.getString(Constants.MAIL_PASSWD);
|
||||
|
||||
public static final Boolean MAIL_USE_START_TLS = PropertyUtils.getBoolean(Constants.MAIL_SMTP_STARTTLS_ENABLE);
|
||||
|
||||
public static final Boolean MAIL_USE_SSL = PropertyUtils.getBoolean(Constants.MAIL_SMTP_SSL_ENABLE);
|
||||
|
||||
public static final String XLS_FILE_PATH = PropertyUtils.getString(Constants.XLS_FILE_PATH, "/tmp/xls");
|
||||
|
||||
public static final String STARTTLS_ENABLE = PropertyUtils.getString(Constants.MAIL_SMTP_STARTTLS_ENABLE);
|
||||
|
||||
public static final Boolean SSL_ENABLE = PropertyUtils.getBoolean(Constants.MAIL_SMTP_SSL_ENABLE);
|
||||
|
||||
public static final String SSL_TRUST = PropertyUtils.getString(Constants.MAIL_SMTP_SSL_TRUST);
|
||||
|
||||
public static final AlertTemplate alertTemplate = AlertTemplateFactory.getMessageTemplate();
|
||||
|
||||
//Solve the problem of messy Chinese name in excel attachment
|
||||
static {
|
||||
System.setProperty("mail.mime.splitlongparameters", "false");
|
||||
}
|
||||
|
||||
private MailUtils() {
|
||||
throw new IllegalStateException(MailUtils.class.getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* send mail to receivers
|
||||
*
|
||||
* @param receivers the receiver list
|
||||
* @param title the title
|
||||
* @param content the content
|
||||
* @param showType the show type
|
||||
* @return the result map
|
||||
*/
|
||||
public static Map<String, Object> sendMails(Collection<String> receivers, String title, String content, String showType) {
|
||||
return sendMails(receivers, null, title, content, showType);
|
||||
}
|
||||
|
||||
/**
|
||||
* send mail
|
||||
*
|
||||
* @param receivers the receiver list
|
||||
* @param receiversCc cc list
|
||||
* @param title the title
|
||||
* @param content the content
|
||||
* @param showType the show type
|
||||
* @return the send result
|
||||
*/
|
||||
public static Map<String, Object> sendMails(Collection<String> receivers, Collection<String> receiversCc, String title, String content, String showType) {
|
||||
Map<String, Object> retMap = new HashMap<>();
|
||||
retMap.put(Constants.STATUS, false);
|
||||
|
||||
// if there is no receivers && no receiversCc, no need to process
|
||||
if (CollectionUtils.isEmpty(receivers) && CollectionUtils.isEmpty(receiversCc)) {
|
||||
return retMap;
|
||||
}
|
||||
|
||||
receivers.removeIf(StringUtils::isEmpty);
|
||||
|
||||
if (showType.equals(ShowType.TABLE.getDescp()) || showType.equals(ShowType.TEXT.getDescp())) {
|
||||
// send email
|
||||
HtmlEmail email = new HtmlEmail();
|
||||
|
||||
try {
|
||||
Session session = getSession();
|
||||
email.setMailSession(session);
|
||||
email.setFrom(MAIL_SENDER);
|
||||
email.setCharset(Constants.UTF_8);
|
||||
if (CollectionUtils.isNotEmpty(receivers)) {
|
||||
// receivers mail
|
||||
for (String receiver : receivers) {
|
||||
email.addTo(receiver);
|
||||
}
|
||||
}
|
||||
|
||||
if (CollectionUtils.isNotEmpty(receiversCc)) {
|
||||
//cc
|
||||
for (String receiverCc : receiversCc) {
|
||||
email.addCc(receiverCc);
|
||||
}
|
||||
}
|
||||
// sender mail
|
||||
return getStringObjectMap(title, content, showType, retMap, email);
|
||||
} catch (Exception e) {
|
||||
handleException(receivers, retMap, e);
|
||||
}
|
||||
} else if (showType.equals(ShowType.ATTACHMENT.getDescp()) || showType.equals(ShowType.TABLEATTACHMENT.getDescp())) {
|
||||
try {
|
||||
|
||||
String partContent = (showType.equals(ShowType.ATTACHMENT.getDescp()) ? "Please see the attachment " + title + Constants.EXCEL_SUFFIX_XLS : htmlTable(content, false));
|
||||
|
||||
attachment(receivers, receiversCc, title, content, partContent);
|
||||
|
||||
retMap.put(Constants.STATUS, true);
|
||||
return retMap;
|
||||
} catch (Exception e) {
|
||||
handleException(receivers, retMap, e);
|
||||
return retMap;
|
||||
}
|
||||
}
|
||||
return retMap;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* html table content
|
||||
*
|
||||
* @param content the content
|
||||
* @param showAll if show the whole content
|
||||
* @return the html table form
|
||||
*/
|
||||
private static String htmlTable(String content, boolean showAll) {
|
||||
return alertTemplate.getMessageFromTemplate(content, ShowType.TABLE, showAll);
|
||||
}
|
||||
|
||||
/**
|
||||
* html table content
|
||||
*
|
||||
* @param content the content
|
||||
* @return the html table form
|
||||
*/
|
||||
private static String htmlTable(String content) {
|
||||
return htmlTable(content, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* html text content
|
||||
*
|
||||
* @param content the content
|
||||
* @return text in html form
|
||||
*/
|
||||
private static String htmlText(String content) {
|
||||
return alertTemplate.getMessageFromTemplate(content, ShowType.TEXT);
|
||||
}
|
||||
|
||||
/**
|
||||
* send mail as Excel attachment
|
||||
*
|
||||
* @param receivers the receiver list
|
||||
* @param title the title
|
||||
*/
|
||||
private static void attachment(Collection<String> receivers, Collection<String> receiversCc, String title, String content, String partContent) throws Exception {
|
||||
MimeMessage msg = getMimeMessage(receivers);
|
||||
|
||||
attachContent(receiversCc, title, content, partContent, msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* get MimeMessage
|
||||
*
|
||||
* @param receivers receivers
|
||||
* @return the MimeMessage
|
||||
*/
|
||||
private static MimeMessage getMimeMessage(Collection<String> receivers) throws MessagingException {
|
||||
|
||||
// 1. The first step in creating mail: creating session
|
||||
Session session = getSession();
|
||||
// Setting debug mode, can be turned off
|
||||
session.setDebug(false);
|
||||
|
||||
// 2. creating mail: Creating a MimeMessage
|
||||
MimeMessage msg = new MimeMessage(session);
|
||||
// 3. set sender
|
||||
msg.setFrom(new InternetAddress(MAIL_SENDER));
|
||||
// 4. set receivers
|
||||
for (String receiver : receivers) {
|
||||
msg.addRecipients(Message.RecipientType.TO, InternetAddress.parse(receiver));
|
||||
}
|
||||
return msg;
|
||||
}
|
||||
|
||||
/**
|
||||
* get session
|
||||
*
|
||||
* @return the new Session
|
||||
*/
|
||||
private static Session getSession() {
|
||||
Properties props = new Properties();
|
||||
props.setProperty(Constants.MAIL_HOST, MAIL_SERVER_HOST);
|
||||
props.setProperty(Constants.MAIL_PORT, String.valueOf(MAIL_SERVER_PORT));
|
||||
props.setProperty(Constants.MAIL_SMTP_AUTH, Constants.STRING_TRUE);
|
||||
props.setProperty(Constants.MAIL_TRANSPORT_PROTOCOL, MAIL_PROTOCOL);
|
||||
props.setProperty(Constants.MAIL_SMTP_STARTTLS_ENABLE, STARTTLS_ENABLE);
|
||||
if (Boolean.TRUE.equals(SSL_ENABLE)) {
|
||||
props.setProperty(Constants.MAIL_SMTP_SSL_ENABLE, "true");
|
||||
props.setProperty(Constants.MAIL_SMTP_SSL_TRUST, SSL_TRUST);
|
||||
}
|
||||
|
||||
Authenticator auth = new Authenticator() {
|
||||
@Override
|
||||
protected PasswordAuthentication getPasswordAuthentication() {
|
||||
// mail username and password
|
||||
return new PasswordAuthentication(MAIL_USER, MAIL_PASSWD);
|
||||
}
|
||||
};
|
||||
|
||||
return Session.getInstance(props, auth);
|
||||
}
|
||||
|
||||
/**
|
||||
* attach content
|
||||
*
|
||||
* @param receiversCc the cc list
|
||||
* @param title the title
|
||||
* @param content the content
|
||||
* @param partContent the partContent
|
||||
* @param msg the message
|
||||
*/
|
||||
private static void attachContent(Collection<String> receiversCc, String title, String content, String partContent, MimeMessage msg) throws MessagingException, IOException {
|
||||
/*
|
||||
* set receiverCc
|
||||
*/
|
||||
if (CollectionUtils.isNotEmpty(receiversCc)) {
|
||||
for (String receiverCc : receiversCc) {
|
||||
msg.addRecipients(Message.RecipientType.CC, InternetAddress.parse(receiverCc));
|
||||
}
|
||||
}
|
||||
|
||||
// set subject
|
||||
msg.setSubject(title);
|
||||
MimeMultipart partList = new MimeMultipart();
|
||||
// set signature
|
||||
MimeBodyPart part1 = new MimeBodyPart();
|
||||
part1.setContent(partContent, Constants.TEXT_HTML_CHARSET_UTF_8);
|
||||
// set attach file
|
||||
MimeBodyPart part2 = new MimeBodyPart();
|
||||
File file = new File(XLS_FILE_PATH + Constants.SINGLE_SLASH + title + Constants.EXCEL_SUFFIX_XLS);
|
||||
if (!file.getParentFile().exists()) {
|
||||
file.getParentFile().mkdirs();
|
||||
}
|
||||
// make excel file
|
||||
|
||||
ExcelUtils.genExcelFile(content, title, XLS_FILE_PATH);
|
||||
|
||||
part2.attachFile(file);
|
||||
part2.setFileName(MimeUtility.encodeText(title + Constants.EXCEL_SUFFIX_XLS, Constants.UTF_8, "B"));
|
||||
// add components to collection
|
||||
partList.addBodyPart(part1);
|
||||
partList.addBodyPart(part2);
|
||||
msg.setContent(partList);
|
||||
// 5. send Transport
|
||||
Transport.send(msg);
|
||||
// 6. delete saved file
|
||||
deleteFile(file);
|
||||
}
|
||||
|
||||
/**
|
||||
* the string object map
|
||||
*
|
||||
* @param title the title
|
||||
* @param content the content
|
||||
* @param showType the showType
|
||||
* @param retMap the result map
|
||||
* @param email the email
|
||||
* @return the result map
|
||||
*/
|
||||
private static Map<String, Object> getStringObjectMap(String title, String content, String showType, Map<String, Object> retMap, HtmlEmail email) throws EmailException {
|
||||
|
||||
/*
|
||||
* the subject of the message to be sent
|
||||
*/
|
||||
email.setSubject(title);
|
||||
/*
|
||||
* to send information, you can use HTML tags in mail content because of the use of HtmlEmail
|
||||
*/
|
||||
if (showType.equals(ShowType.TABLE.getDescp())) {
|
||||
email.setMsg(htmlTable(content));
|
||||
} else if (showType.equals(ShowType.TEXT.getDescp())) {
|
||||
email.setMsg(htmlText(content));
|
||||
}
|
||||
|
||||
// send
|
||||
email.send();
|
||||
|
||||
retMap.put(Constants.STATUS, true);
|
||||
|
||||
return retMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* file delete
|
||||
*
|
||||
* @param file the file to delete
|
||||
*/
|
||||
public static void deleteFile(File file) {
|
||||
if (file.exists()) {
|
||||
if (file.delete()) {
|
||||
logger.info("delete success: {}", file.getAbsolutePath() + file.getName());
|
||||
} else {
|
||||
logger.info("delete fail: {}", file.getAbsolutePath() + file.getName());
|
||||
}
|
||||
} else {
|
||||
logger.info("file not exists: {}", file.getAbsolutePath() + file.getName());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* handle exception
|
||||
*
|
||||
* @param receivers the receiver list
|
||||
* @param retMap the result map
|
||||
* @param e the exception
|
||||
*/
|
||||
private static void handleException(Collection<String> receivers, Map<String, Object> retMap, Exception e) {
|
||||
logger.error("Send email to {} failed", receivers, e);
|
||||
retMap.put(Constants.MESSAGE, "Send email to {" + String.join(",", receivers) + "} failed," + e.toString());
|
||||
}
|
||||
}
|
||||
|
|
@ -83,7 +83,7 @@ public class PropertyUtils {
|
|||
/**
|
||||
* get property value
|
||||
*
|
||||
* @param key property name
|
||||
* @param key property name
|
||||
* @param defaultVal default value
|
||||
* @return property value
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -15,46 +15,19 @@
|
|||
# limitations under the License.
|
||||
#
|
||||
|
||||
#alert type is EMAIL/SMS
|
||||
alert.type=EMAIL
|
||||
#This configuration file configures the configuration parameters related to the AlertServer.
|
||||
#These parameters are only related to the AlertServer, and it has nothing to do with the specific Alert Plugin.
|
||||
#eg : max retry num.
|
||||
#eg : Alert Server Listener port
|
||||
|
||||
# mail server configuration
|
||||
mail.protocol=SMTP
|
||||
mail.server.host=xxx.xxx.com
|
||||
mail.server.port=25
|
||||
mail.sender=xxx@xxx.com
|
||||
mail.user=xxx@xxx.com
|
||||
mail.passwd=111111
|
||||
# TLS
|
||||
mail.smtp.starttls.enable=true
|
||||
# SSL
|
||||
mail.smtp.ssl.enable=false
|
||||
mail.smtp.ssl.trust=xxx.xxx.com
|
||||
#alert.plugin.dir config the Alert Plugin dir . AlertServer while find and load the Alert Plugin Jar from this dir when deploy and start AlertServer on the server .
|
||||
#eg :
|
||||
alert.plugin.dir=/opt/soft/spi/lib/plugin/alert
|
||||
|
||||
#xls file path,need create if not exist
|
||||
#xls.file.path=/tmp/xls
|
||||
#maven.local.repository=/Users/gaojun/Documents/jianguoyun/localRepository
|
||||
|
||||
# Enterprise WeChat configuration
|
||||
enterprise.wechat.enable=false
|
||||
#alert.plugin.binding config the Alert Plugin need be load when development and run in IDE
|
||||
#alert.plugin.binding=\
|
||||
# ./dolphinscheduler-alert-plugin/dolphinscheduler-alert-email/pom.xml
|
||||
|
||||
#enterprise.wechat.corp.id=xxxxxxx
|
||||
#enterprise.wechat.secret=xxxxxxx
|
||||
#enterprise.wechat.agent.id=xxxxxxx
|
||||
#enterprise.wechat.users=xxxxxxx
|
||||
#enterprise.wechat.token.url=https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid={corpId}&corpsecret={secret}
|
||||
#enterprise.wechat.push.url=https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token={token}
|
||||
#enterprise.wechat.team.send.msg={\"toparty\":\"{toParty}\",\"agentid\":\"{agentId}\",\"msgtype\":\"text\",\"text\":{\"content\":\"{msg}\"},\"safe\":\"0\"}
|
||||
#enterprise.wechat.user.send.msg={\"touser\":\"{toUser}\",\"agentid\":\"{agentId}\",\"msgtype\":\"markdown\",\"markdown\":{\"content\":\"{msg}\"}}
|
||||
|
||||
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
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,91 @@
|
|||
/*
|
||||
* 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;
|
||||
|
||||
import org.apache.dolphinscheduler.alert.plugin.AlertPluginManager;
|
||||
import org.apache.dolphinscheduler.alert.plugin.DolphinPluginLoader;
|
||||
import org.apache.dolphinscheduler.alert.plugin.DolphinPluginManagerConfig;
|
||||
import org.apache.dolphinscheduler.alert.runner.AlertSender;
|
||||
import org.apache.dolphinscheduler.alert.utils.Constants;
|
||||
import org.apache.dolphinscheduler.dao.AlertDao;
|
||||
import org.apache.dolphinscheduler.dao.DaoFactory;
|
||||
import org.apache.dolphinscheduler.dao.PluginDao;
|
||||
import org.apache.dolphinscheduler.remote.NettyRemotingServer;
|
||||
import org.apache.dolphinscheduler.spi.alert.AlertChannel;
|
||||
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.powermock.api.mockito.PowerMockito;
|
||||
import org.powermock.core.classloader.annotations.PrepareForTest;
|
||||
import org.powermock.modules.junit4.PowerMockRunner;
|
||||
|
||||
@RunWith(PowerMockRunner.class)
|
||||
@PrepareForTest({AlertServer.class,DaoFactory.class})
|
||||
public class AlertServerTest {
|
||||
|
||||
@Before
|
||||
public void before() {
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMain() throws Exception {
|
||||
AlertDao alertDao = PowerMockito.mock(AlertDao.class);
|
||||
PowerMockito.mockStatic(DaoFactory.class);
|
||||
PowerMockito.when(DaoFactory.getDaoInstance(AlertDao.class)).thenReturn(alertDao);
|
||||
|
||||
PluginDao pluginDao = PowerMockito.mock(PluginDao.class);
|
||||
PowerMockito.when(DaoFactory.getDaoInstance(PluginDao.class)).thenReturn(pluginDao);
|
||||
|
||||
AlertChannel alertChannelMock = PowerMockito.mock(AlertChannel.class);
|
||||
|
||||
AlertPluginManager alertPluginManager = PowerMockito.mock(AlertPluginManager.class);
|
||||
PowerMockito.whenNew(AlertPluginManager.class).withNoArguments().thenReturn(alertPluginManager);
|
||||
ConcurrentHashMap alertChannelMap = new ConcurrentHashMap<>();
|
||||
alertChannelMap.put("pluginName",alertChannelMock);
|
||||
PowerMockito.when(alertPluginManager.getAlertChannelMap()).thenReturn(alertChannelMap);
|
||||
|
||||
DolphinPluginManagerConfig alertPluginManagerConfig = PowerMockito.mock(DolphinPluginManagerConfig.class);
|
||||
PowerMockito.whenNew(DolphinPluginManagerConfig.class).withNoArguments().thenReturn(alertPluginManagerConfig);
|
||||
|
||||
NettyRemotingServer nettyRemotingServer = PowerMockito.mock(NettyRemotingServer.class);
|
||||
PowerMockito.whenNew(NettyRemotingServer.class).withAnyArguments().thenReturn(nettyRemotingServer);
|
||||
AlertSender alertSender = PowerMockito.mock(AlertSender.class);
|
||||
PowerMockito.whenNew(AlertSender.class).withAnyArguments().thenReturn(alertSender);
|
||||
|
||||
DolphinPluginLoader dolphinPluginLoader = PowerMockito.mock(DolphinPluginLoader.class);
|
||||
PowerMockito.whenNew(DolphinPluginLoader.class).withAnyArguments().thenReturn(dolphinPluginLoader);
|
||||
|
||||
AlertServer alertServer = AlertServer.getInstance();
|
||||
Assert.assertNotNull(alertServer);
|
||||
|
||||
new Thread(() -> {
|
||||
alertServer.start(); })
|
||||
.start();
|
||||
|
||||
Thread.sleep(5 * Constants.ALERT_SCAN_INTERVAL);
|
||||
|
||||
alertServer.stop();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
* 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.plugin;
|
||||
|
||||
import org.apache.dolphinscheduler.alert.AlertServer;
|
||||
import org.apache.dolphinscheduler.alert.utils.Constants;
|
||||
import org.apache.dolphinscheduler.alert.utils.PropertyUtils;
|
||||
import org.apache.dolphinscheduler.spi.utils.StringUtils;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
/**
|
||||
* AlertPluginManager Tester.
|
||||
*/
|
||||
@Ignore
|
||||
public class AlertPluginManagerTest {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(AlertPluginManagerTest.class);
|
||||
|
||||
@Test
|
||||
public void testLoadPlugins() throws Exception {
|
||||
logger.info("begin test AlertPluginManagerTest");
|
||||
AlertPluginManager alertPluginManager = new AlertPluginManager();
|
||||
DolphinPluginManagerConfig alertPluginManagerConfig = new DolphinPluginManagerConfig();
|
||||
String path = DolphinPluginLoader.class.getClassLoader().getResource("").getPath();
|
||||
alertPluginManagerConfig.setPlugins(path + "../../../dolphinscheduler-alert-plugin/dolphinscheduler-alert-email/pom.xml");
|
||||
if (StringUtils.isNotBlank(PropertyUtils.getString(AlertServer.ALERT_PLUGIN_DIR))) {
|
||||
alertPluginManagerConfig.setInstalledPluginsDir(org.apache.dolphinscheduler.alert.utils.PropertyUtils.getString(AlertServer.ALERT_PLUGIN_DIR, Constants.ALERT_PLUGIN_PATH).trim());
|
||||
}
|
||||
|
||||
if (StringUtils.isNotBlank(PropertyUtils.getString(AlertServer.MAVEN_LOCAL_REPOSITORY))) {
|
||||
alertPluginManagerConfig.setMavenLocalRepository(PropertyUtils.getString(AlertServer.MAVEN_LOCAL_REPOSITORY).trim());
|
||||
}
|
||||
|
||||
DolphinPluginLoader alertPluginLoader = new DolphinPluginLoader(alertPluginManagerConfig, ImmutableList.of(alertPluginManager));
|
||||
try {
|
||||
alertPluginLoader.loadPlugins();
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("load Alert Plugin Failed !", e);
|
||||
}
|
||||
|
||||
Assert.assertNotNull(alertPluginManager.getAlertChannelFactoryMap().get("email alert"));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
* 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.plugin;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
/**
|
||||
* DolphinPluginLoader Tester.
|
||||
*/
|
||||
@Ignore
|
||||
public class DolphinPluginLoaderTest {
|
||||
|
||||
@Before
|
||||
public void before() throws Exception {
|
||||
}
|
||||
|
||||
@After
|
||||
public void after() throws Exception {
|
||||
}
|
||||
|
||||
/**
|
||||
* Method: loadPlugins()
|
||||
*/
|
||||
@Test
|
||||
public void testLoadPlugins() throws Exception {
|
||||
AlertPluginManager alertPluginManager = new AlertPluginManager();
|
||||
DolphinPluginManagerConfig alertPluginManagerConfig = new DolphinPluginManagerConfig();
|
||||
String path = DolphinPluginLoader.class.getClassLoader().getResource("").getPath();
|
||||
alertPluginManagerConfig.setPlugins(path + "../../../dolphinscheduler-alert-plugin/dolphinscheduler-alert-email/pom.xml");
|
||||
DolphinPluginLoader alertPluginLoader = new DolphinPluginLoader(alertPluginManagerConfig, ImmutableList.of(alertPluginManager));
|
||||
try {
|
||||
alertPluginLoader.loadPlugins();
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("load Alert Plugin Failed !", e);
|
||||
}
|
||||
|
||||
Assert.assertNotNull(alertPluginManager.getAlertChannelFactoryMap().get("email alert"));
|
||||
}
|
||||
}
|
||||
|
|
@ -14,67 +14,226 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.apache.dolphinscheduler.alert.plugin;
|
||||
|
||||
import org.apache.dolphinscheduler.alert.AlertServer;
|
||||
import org.apache.dolphinscheduler.alert.runner.AlertSender;
|
||||
import org.apache.dolphinscheduler.alert.utils.Constants;
|
||||
import org.apache.dolphinscheduler.common.enums.ShowType;
|
||||
import org.apache.dolphinscheduler.plugin.api.AlertPlugin;
|
||||
import org.apache.dolphinscheduler.plugin.model.AlertData;
|
||||
import org.apache.dolphinscheduler.plugin.model.AlertInfo;
|
||||
import org.apache.dolphinscheduler.plugin.model.PluginName;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.apache.dolphinscheduler.alert.utils.PropertyUtils;
|
||||
import org.apache.dolphinscheduler.common.enums.AlertStatus;
|
||||
import org.apache.dolphinscheduler.common.utils.JSONUtils;
|
||||
import org.apache.dolphinscheduler.dao.AlertDao;
|
||||
import org.apache.dolphinscheduler.dao.DaoFactory;
|
||||
import org.apache.dolphinscheduler.dao.PluginDao;
|
||||
import org.apache.dolphinscheduler.dao.entity.Alert;
|
||||
import org.apache.dolphinscheduler.dao.entity.AlertGroup;
|
||||
import org.apache.dolphinscheduler.dao.entity.AlertPluginInstance;
|
||||
import org.apache.dolphinscheduler.dao.entity.PluginDefine;
|
||||
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.PasswordParam;
|
||||
import org.apache.dolphinscheduler.spi.params.PluginParamsTransfer;
|
||||
import org.apache.dolphinscheduler.spi.params.RadioParam;
|
||||
import org.apache.dolphinscheduler.spi.params.base.DataType;
|
||||
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 org.apache.dolphinscheduler.spi.utils.StringUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
/**
|
||||
* test load and use alert plugin
|
||||
*/
|
||||
public class EmailAlertPluginTest {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(EmailAlertPluginTest.class);
|
||||
|
||||
private AlertPlugin plugin;
|
||||
|
||||
@Before
|
||||
public void before() {
|
||||
plugin = new EmailAlertPlugin();
|
||||
}
|
||||
AlertDao alertDao = DaoFactory.getDaoInstance(AlertDao.class);
|
||||
PluginDao pluginDao = DaoFactory.getDaoInstance(PluginDao.class);
|
||||
|
||||
@Test
|
||||
public void getId() {
|
||||
String id = plugin.getId();
|
||||
assertEquals(Constants.PLUGIN_DEFAULT_EMAIL_ID, id);
|
||||
@Ignore
|
||||
public void testRunSend() throws Exception {
|
||||
|
||||
//create alert group
|
||||
AlertGroup alertGroup = new AlertGroup();
|
||||
alertGroup.setDescription("test alert group 1");
|
||||
alertGroup.setGroupName("testalertg1");
|
||||
alertDao.getAlertGroupMapper().insert(alertGroup);
|
||||
|
||||
//add alert
|
||||
Alert alert1 = new Alert();
|
||||
alert1.setTitle("test alert");
|
||||
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(AlertConstants.SHOW_TYPE, ShowType.TEXT.getDescp());
|
||||
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");
|
||||
map1.put(AlertConstants.SHOW_TYPE, ShowType.TABLE.getDescp());
|
||||
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);
|
||||
alert1.setContent(mapjson);
|
||||
alert1.setLog("log log");
|
||||
alert1.setAlertGroupId(alertGroup.getId());
|
||||
alertDao.addAlert(alert1);
|
||||
|
||||
List<Alert> alertList = new ArrayList<>();
|
||||
alertList.add(alert1);
|
||||
|
||||
//load email alert plugin
|
||||
AlertPluginManager alertPluginManager = new AlertPluginManager();
|
||||
DolphinPluginManagerConfig alertPluginManagerConfig = new DolphinPluginManagerConfig();
|
||||
String path = DolphinPluginLoader.class.getClassLoader().getResource("").getPath();
|
||||
alertPluginManagerConfig.setPlugins(path + "../../../dolphinscheduler-alert-plugin/dolphinscheduler-alert-email/pom.xml");
|
||||
if (StringUtils.isNotBlank(PropertyUtils.getString(AlertServer.ALERT_PLUGIN_DIR))) {
|
||||
alertPluginManagerConfig.setInstalledPluginsDir(PropertyUtils.getString(AlertServer.ALERT_PLUGIN_DIR, Constants.ALERT_PLUGIN_PATH).trim());
|
||||
}
|
||||
|
||||
if (StringUtils.isNotBlank(PropertyUtils.getString(AlertServer.MAVEN_LOCAL_REPOSITORY))) {
|
||||
alertPluginManagerConfig.setMavenLocalRepository(PropertyUtils.getString(AlertServer.MAVEN_LOCAL_REPOSITORY).trim());
|
||||
}
|
||||
|
||||
DolphinPluginLoader alertPluginLoader = new DolphinPluginLoader(alertPluginManagerConfig, ImmutableList.of(alertPluginManager));
|
||||
try {
|
||||
alertPluginLoader.loadPlugins();
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("load Alert Plugin Failed !", e);
|
||||
}
|
||||
|
||||
//create email alert plugin instance
|
||||
AlertPluginInstance alertPluginInstance = new AlertPluginInstance();
|
||||
alertPluginInstance.setCreateTime(new Date());
|
||||
alertPluginInstance.setInstanceName("test email alert");
|
||||
|
||||
List<PluginDefine> pluginDefineList = pluginDao.getPluginDefineMapper().queryByNameAndType("email alert", "alert");
|
||||
if (pluginDefineList == null || pluginDefineList.size() == 0) {
|
||||
throw new RuntimeException("no alert plugin be load");
|
||||
}
|
||||
PluginDefine pluginDefine = pluginDefineList.get(0);
|
||||
alertPluginInstance.setPluginDefineId(pluginDefine.getId());
|
||||
alertPluginInstance.setPluginInstanceParams(getEmailAlertParams());
|
||||
alertDao.getAlertPluginInstanceMapper().insert(alertPluginInstance);
|
||||
|
||||
AlertSender alertSender = new AlertSender(alertList, alertDao, alertPluginManager, pluginDao);
|
||||
alertSender.run();
|
||||
|
||||
Alert alertResult = alertDao.getAlertMapper().selectById(alert1.getId());
|
||||
Assert.assertNotNull(alertResult);
|
||||
Assert.assertEquals(alertResult.getAlertStatus(), AlertStatus.EXECUTION_FAILURE);
|
||||
|
||||
alertDao.getAlertGroupMapper().deleteById(alertGroup.getId());
|
||||
alertDao.getAlertPluginInstanceMapper().deleteById(alertPluginInstance.getId());
|
||||
alertDao.getAlertMapper().deleteById(alert1.getId());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getName() {
|
||||
PluginName pluginName = plugin.getName();
|
||||
assertEquals(Constants.PLUGIN_DEFAULT_EMAIL_CH, pluginName.getChinese());
|
||||
assertEquals(Constants.PLUGIN_DEFAULT_EMAIL_EN, pluginName.getEnglish());
|
||||
}
|
||||
public String getEmailAlertParams() {
|
||||
|
||||
@Test
|
||||
public void process() {
|
||||
AlertInfo alertInfo = new AlertInfo();
|
||||
AlertData alertData = new AlertData();
|
||||
alertData.setId(1)
|
||||
.setAlertGroupId(1)
|
||||
.setContent("[\"alarm time:2018-02-05\", \"service name:MYSQL_ALTER\", \"alarm name:MYSQL_ALTER_DUMP\", " +
|
||||
"\"get the alarm exception.!,interface error,exception information:timed out\", \"request address:http://blog.csdn.net/dreamInTheWorld/article/details/78539286\"]")
|
||||
.setLog("test log")
|
||||
.setReceivers("xx@xx.com")
|
||||
.setReceiversCc("xx@xx.com")
|
||||
.setShowType(ShowType.TEXT.getDescp())
|
||||
.setTitle("test title");
|
||||
List<PluginParams> paramsList = new ArrayList<>();
|
||||
InputParam receivesParam = InputParam.newBuilder("receivers", "receivers")
|
||||
.setValue("540957506@qq.com")
|
||||
.addValidate(Validate.newBuilder().setRequired(true).build())
|
||||
.build();
|
||||
|
||||
alertInfo.setAlertData(alertData);
|
||||
List<String> list = new ArrayList<String>(){{ add("xx@xx.com"); }};
|
||||
alertInfo.addProp("receivers", list);
|
||||
// Map<String, Object> ret = plugin.process(alertInfo);
|
||||
// assertFalse(Boolean.parseBoolean(String.valueOf(ret.get(Constants.STATUS))));
|
||||
InputParam mailSmtpHost = InputParam.newBuilder("mailServerHost", "mail.smtp.host")
|
||||
.addValidate(Validate.newBuilder().setRequired(true).build())
|
||||
.setValue("smtp.exmail.qq.com")
|
||||
.build();
|
||||
|
||||
InputParam mailSmtpPort = InputParam.newBuilder("mailServerPort", "mail.smtp.port")
|
||||
.addValidate(Validate.newBuilder()
|
||||
.setRequired(true)
|
||||
.setType(DataType.NUMBER.getDataType())
|
||||
.build())
|
||||
.setValue(25)
|
||||
.build();
|
||||
|
||||
InputParam mailSender = InputParam.newBuilder("mailSender", "mail.sender")
|
||||
.addValidate(Validate.newBuilder().setRequired(true).build())
|
||||
.setValue("easyscheduler@analysys.com.cn")
|
||||
.build();
|
||||
|
||||
RadioParam enableSmtpAuth = RadioParam.newBuilder("enableSmtpAuth", "mail.smtp.auth")
|
||||
.addParamsOptions(new ParamsOptions("YES", true, false))
|
||||
.addParamsOptions(new ParamsOptions("NO", false, false))
|
||||
.addValidate(Validate.newBuilder().setRequired(true).build())
|
||||
.setValue(true)
|
||||
.build();
|
||||
|
||||
InputParam mailUser = InputParam.newBuilder("mailUser", "mail.user")
|
||||
.setPlaceholder("if enable use authentication, you need input user")
|
||||
.setValue("easyscheduler@analysys.com.cn")
|
||||
.build();
|
||||
|
||||
PasswordParam mailPassword = PasswordParam.newBuilder("mailPasswd", "mail.passwd")
|
||||
.setPlaceholder("if enable use authentication, you need input password")
|
||||
.setValue("xxxxxxx")
|
||||
.build();
|
||||
|
||||
RadioParam enableTls = RadioParam.newBuilder("starttlsEnable", "mail.smtp.starttls.enable")
|
||||
.addParamsOptions(new ParamsOptions("YES", true, false))
|
||||
.addParamsOptions(new ParamsOptions("NO", false, false))
|
||||
.addValidate(Validate.newBuilder().setRequired(true).build())
|
||||
.setValue(true)
|
||||
.build();
|
||||
|
||||
RadioParam enableSsl = RadioParam.newBuilder("sslEnable", "mail.smtp.ssl.enable")
|
||||
.addParamsOptions(new ParamsOptions("YES", true, false))
|
||||
.addParamsOptions(new ParamsOptions("NO", false, false))
|
||||
.addValidate(Validate.newBuilder().setRequired(true).build())
|
||||
.setValue(false)
|
||||
.build();
|
||||
|
||||
InputParam sslTrust = InputParam.newBuilder("mailSmtpSslTrust", "mail.smtp.ssl.trust")
|
||||
.addValidate(Validate.newBuilder().setRequired(true).build())
|
||||
.setValue("smtp.exmail.qq.com")
|
||||
.build();
|
||||
|
||||
List<ParamsOptions> emailShowTypeList = new ArrayList<>();
|
||||
emailShowTypeList.add(new ParamsOptions(ShowType.TABLE.getDescp(), ShowType.TABLE.getDescp(), false));
|
||||
emailShowTypeList.add(new ParamsOptions(ShowType.TEXT.getDescp(), ShowType.TEXT.getDescp(), false));
|
||||
emailShowTypeList.add(new ParamsOptions(ShowType.ATTACHMENT.getDescp(), ShowType.ATTACHMENT.getDescp(), false));
|
||||
emailShowTypeList.add(new ParamsOptions(ShowType.TABLEATTACHMENT.getDescp(), ShowType.TABLEATTACHMENT.getDescp(), false));
|
||||
RadioParam showType = RadioParam.newBuilder(AlertConstants.SHOW_TYPE, "showType")
|
||||
.setParamsOptionsList(emailShowTypeList)
|
||||
.setValue(ShowType.TABLE.getDescp())
|
||||
.addValidate(Validate.newBuilder().setRequired(true).build())
|
||||
.build();
|
||||
|
||||
paramsList.add(receivesParam);
|
||||
paramsList.add(mailSmtpHost);
|
||||
paramsList.add(mailSmtpPort);
|
||||
paramsList.add(mailSender);
|
||||
paramsList.add(enableSmtpAuth);
|
||||
paramsList.add(mailUser);
|
||||
paramsList.add(mailPassword);
|
||||
paramsList.add(enableTls);
|
||||
paramsList.add(enableSsl);
|
||||
paramsList.add(sslTrust);
|
||||
paramsList.add(showType);
|
||||
|
||||
return PluginParamsTransfer.transferParamsToJson(paramsList);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
* 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.processor;
|
||||
|
||||
import org.apache.dolphinscheduler.alert.plugin.AlertPluginManager;
|
||||
import org.apache.dolphinscheduler.dao.AlertDao;
|
||||
import org.apache.dolphinscheduler.dao.PluginDao;
|
||||
import org.apache.dolphinscheduler.remote.command.Command;
|
||||
import org.apache.dolphinscheduler.remote.command.CommandType;
|
||||
import org.apache.dolphinscheduler.remote.command.alert.AlertSendRequestCommand;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.powermock.api.mockito.PowerMockito;
|
||||
|
||||
import io.netty.channel.Channel;
|
||||
|
||||
/**
|
||||
* alert request processor test
|
||||
*/
|
||||
public class AlertRequestProcessorTest {
|
||||
|
||||
private AlertDao alertDao;
|
||||
private PluginDao pluginDao;
|
||||
private AlertPluginManager alertPluginManager;
|
||||
|
||||
private AlertRequestProcessor alertRequestProcessor;
|
||||
|
||||
@Before
|
||||
public void before() {
|
||||
alertDao = PowerMockito.mock(AlertDao.class);
|
||||
pluginDao = PowerMockito.mock(PluginDao.class);
|
||||
alertPluginManager = PowerMockito.mock(AlertPluginManager.class);
|
||||
alertRequestProcessor = new AlertRequestProcessor(alertDao,alertPluginManager,pluginDao);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProcess() {
|
||||
Channel channel = PowerMockito.mock(Channel.class);
|
||||
AlertSendRequestCommand alertSendRequestCommand = new AlertSendRequestCommand(1,"title","content");
|
||||
Command reqCommand = alertSendRequestCommand.convert2Command();
|
||||
Assert.assertEquals(CommandType.ALERT_SEND_REQUEST,reqCommand.getType());
|
||||
alertRequestProcessor.process(channel,reqCommand);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,181 @@
|
|||
/*
|
||||
* 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.runner;
|
||||
|
||||
import org.apache.dolphinscheduler.alert.plugin.AlertPluginManager;
|
||||
import org.apache.dolphinscheduler.dao.AlertDao;
|
||||
import org.apache.dolphinscheduler.dao.PluginDao;
|
||||
import org.apache.dolphinscheduler.dao.entity.Alert;
|
||||
import org.apache.dolphinscheduler.dao.entity.AlertPluginInstance;
|
||||
import org.apache.dolphinscheduler.dao.entity.PluginDefine;
|
||||
import org.apache.dolphinscheduler.remote.command.alert.AlertSendResponseCommand;
|
||||
import org.apache.dolphinscheduler.spi.alert.AlertChannel;
|
||||
import org.apache.dolphinscheduler.spi.alert.AlertResult;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.mockito.Mockito;
|
||||
import org.powermock.api.mockito.PowerMockito;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* alert sender test
|
||||
*/
|
||||
public class AlertSenderTest {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(AlertSenderTest.class);
|
||||
|
||||
private AlertDao alertDao;
|
||||
private PluginDao pluginDao;
|
||||
private AlertPluginManager alertPluginManager;
|
||||
|
||||
private AlertSender alertSender;
|
||||
|
||||
@Before
|
||||
public void before() {
|
||||
alertDao = PowerMockito.mock(AlertDao.class);
|
||||
pluginDao = PowerMockito.mock(PluginDao.class);
|
||||
alertPluginManager = PowerMockito.mock(AlertPluginManager.class);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSyncHandler() {
|
||||
|
||||
int alertGroupId = 1;
|
||||
String title = "alert mail test title";
|
||||
String content = "alert mail test content";
|
||||
alertSender = new AlertSender(alertDao,alertPluginManager,pluginDao);
|
||||
|
||||
//1.alert instance does not exist
|
||||
PowerMockito.when(alertDao.listInstanceByAlertGroupId(alertGroupId)).thenReturn(null);
|
||||
|
||||
AlertSendResponseCommand alertSendResponseCommand = alertSender.syncHandler(alertGroupId, title, content);
|
||||
Assert.assertFalse(alertSendResponseCommand.getResStatus());
|
||||
alertSendResponseCommand.getResResults().forEach(result ->
|
||||
logger.info("alert send response result, status:{}, message:{}",result.getStatus(),result.getMessage()));
|
||||
|
||||
//2.alert plugin does not exist
|
||||
int pluginDefineId = 1;
|
||||
String pluginInstanceParams = "alert-instance-mail-params";
|
||||
String pluginInstanceName = "alert-instance-mail";
|
||||
List<AlertPluginInstance> alertInstanceList = new ArrayList<>();
|
||||
AlertPluginInstance alertPluginInstance = new AlertPluginInstance(
|
||||
pluginDefineId,pluginInstanceParams,pluginInstanceName);
|
||||
alertInstanceList.add(alertPluginInstance);
|
||||
PowerMockito.when(alertDao.listInstanceByAlertGroupId(1)).thenReturn(alertInstanceList);
|
||||
|
||||
String pluginName = "alert-plugin-mail";
|
||||
PluginDefine pluginDefine = new PluginDefine(pluginName,"1",null);
|
||||
PowerMockito.when(pluginDao.getPluginDefineById(pluginDefineId)).thenReturn(pluginDefine);
|
||||
|
||||
alertSendResponseCommand = alertSender.syncHandler(alertGroupId, title, content);
|
||||
Assert.assertFalse(alertSendResponseCommand.getResStatus());
|
||||
alertSendResponseCommand.getResResults().forEach(result ->
|
||||
logger.info("alert send response result, status:{}, message:{}",result.getStatus(),result.getMessage()));
|
||||
|
||||
//3.alert result value is null
|
||||
AlertChannel alertChannelMock = PowerMockito.mock(AlertChannel.class);
|
||||
PowerMockito.when(alertChannelMock.process(Mockito.any())).thenReturn(null);
|
||||
Map<String, AlertChannel> alertChannelMap = new ConcurrentHashMap<>();
|
||||
alertChannelMap.put(pluginName,alertChannelMock);
|
||||
PowerMockito.when(alertPluginManager.getAlertChannelMap()).thenReturn(alertChannelMap);
|
||||
|
||||
alertSendResponseCommand = alertSender.syncHandler(alertGroupId, title, content);
|
||||
Assert.assertFalse(alertSendResponseCommand.getResStatus());
|
||||
alertSendResponseCommand.getResResults().forEach(result ->
|
||||
logger.info("alert send response result, status:{}, message:{}",result.getStatus(),result.getMessage()));
|
||||
|
||||
//4.abnormal information inside the alert plug-in code
|
||||
AlertResult alertResult = new AlertResult();
|
||||
alertResult.setStatus(String.valueOf(false));
|
||||
alertResult.setMessage("Abnormal information inside the alert plug-in code");
|
||||
PowerMockito.when(alertChannelMock.process(Mockito.any())).thenReturn(alertResult);
|
||||
alertChannelMap = new ConcurrentHashMap<>();
|
||||
alertChannelMap.put(pluginName,alertChannelMock);
|
||||
PowerMockito.when(alertPluginManager.getAlertChannelMap()).thenReturn(alertChannelMap);
|
||||
|
||||
alertSendResponseCommand = alertSender.syncHandler(alertGroupId, title, content);
|
||||
Assert.assertFalse(alertSendResponseCommand.getResStatus());
|
||||
alertSendResponseCommand.getResResults().forEach(result ->
|
||||
logger.info("alert send response result, status:{}, message:{}",result.getStatus(),result.getMessage()));
|
||||
|
||||
//5.alert plugin send success
|
||||
alertResult = new AlertResult();
|
||||
alertResult.setStatus(String.valueOf(true));
|
||||
alertResult.setMessage(String.format("Alert Plugin %s send success",pluginInstanceName));
|
||||
PowerMockito.when(alertChannelMock.process(Mockito.any())).thenReturn(alertResult);
|
||||
alertChannelMap = new ConcurrentHashMap<>();
|
||||
alertChannelMap.put(pluginName,alertChannelMock);
|
||||
PowerMockito.when(alertPluginManager.getAlertChannelMap()).thenReturn(alertChannelMap);
|
||||
|
||||
alertSendResponseCommand = alertSender.syncHandler(alertGroupId, title, content);
|
||||
Assert.assertTrue(alertSendResponseCommand.getResStatus());
|
||||
alertSendResponseCommand.getResResults().forEach(result ->
|
||||
logger.info("alert send response result, status:{}, message:{}",result.getStatus(),result.getMessage()));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRun() {
|
||||
int alertGroupId = 1;
|
||||
String title = "alert mail test title";
|
||||
String content = "alert mail test content";
|
||||
List<Alert> alertList = new ArrayList<>();
|
||||
Alert alert = new Alert();
|
||||
alert.setAlertGroupId(alertGroupId);
|
||||
alert.setTitle(title);
|
||||
alert.setContent(content);
|
||||
alertList.add(alert);
|
||||
|
||||
alertSender = new AlertSender(alertList,alertDao,alertPluginManager,pluginDao);
|
||||
|
||||
int pluginDefineId = 1;
|
||||
String pluginInstanceParams = "alert-instance-mail-params";
|
||||
String pluginInstanceName = "alert-instance-mail";
|
||||
List<AlertPluginInstance> alertInstanceList = new ArrayList<>();
|
||||
AlertPluginInstance alertPluginInstance = new AlertPluginInstance(
|
||||
pluginDefineId,pluginInstanceParams,pluginInstanceName);
|
||||
alertInstanceList.add(alertPluginInstance);
|
||||
PowerMockito.when(alertDao.listInstanceByAlertGroupId(alertGroupId)).thenReturn(alertInstanceList);
|
||||
|
||||
String pluginName = "alert-plugin-mail";
|
||||
PluginDefine pluginDefine = new PluginDefine(pluginName,"1",null);
|
||||
PowerMockito.when(pluginDao.getPluginDefineById(pluginDefineId)).thenReturn(pluginDefine);
|
||||
|
||||
AlertResult alertResult = new AlertResult();
|
||||
alertResult.setStatus(String.valueOf(true));
|
||||
alertResult.setMessage(String.format("Alert Plugin %s send success",pluginInstanceName));
|
||||
AlertChannel alertChannelMock = PowerMockito.mock(AlertChannel.class);
|
||||
PowerMockito.when(alertChannelMock.process(Mockito.any())).thenReturn(alertResult);
|
||||
ConcurrentHashMap alertChannelMap = new ConcurrentHashMap<>();
|
||||
alertChannelMap.put(pluginName,alertChannelMock);
|
||||
PowerMockito.when(alertPluginManager.getAlertChannelMap()).thenReturn(alertChannelMap);
|
||||
Assert.assertTrue(Boolean.parseBoolean(alertResult.getStatus()));
|
||||
alertSender.run();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,65 +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.template;
|
||||
|
||||
import org.apache.dolphinscheduler.alert.template.impl.DefaultHTMLTemplate;
|
||||
import org.apache.dolphinscheduler.alert.utils.Constants;
|
||||
import org.apache.dolphinscheduler.alert.utils.PropertyUtils;
|
||||
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;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import static org.mockito.Mockito.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* test class for AlertTemplateFactory
|
||||
*/
|
||||
@RunWith(PowerMockRunner.class)
|
||||
@PrepareForTest(PropertyUtils.class)
|
||||
public class AlertTemplateFactoryTest {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(AlertTemplateFactoryTest.class);
|
||||
|
||||
/**
|
||||
* GetMessageTemplate method test
|
||||
*/
|
||||
@Test
|
||||
public void testGetMessageTemplate(){
|
||||
|
||||
PowerMockito.mockStatic(PropertyUtils.class);
|
||||
|
||||
AlertTemplate defaultTemplate = AlertTemplateFactory.getMessageTemplate();
|
||||
|
||||
assertTrue(defaultTemplate instanceof DefaultHTMLTemplate);
|
||||
}
|
||||
|
||||
/**
|
||||
* GetMessageTemplate method throw Exception test
|
||||
*/
|
||||
@Test
|
||||
public void testGetMessageTemplateException(){
|
||||
|
||||
AlertTemplate defaultTemplate = AlertTemplateFactory.getMessageTemplate();
|
||||
assertTrue(defaultTemplate instanceof DefaultHTMLTemplate);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,96 +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.template.impl;
|
||||
|
||||
import org.apache.dolphinscheduler.common.utils.*;
|
||||
import org.apache.dolphinscheduler.alert.utils.Constants;
|
||||
import org.apache.dolphinscheduler.common.enums.ShowType;
|
||||
import org.junit.Test;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* test class for DefaultHTMLTemplate
|
||||
*/
|
||||
public class DefaultHTMLTemplateTest{
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(DefaultHTMLTemplateTest.class);
|
||||
|
||||
/**
|
||||
* only need test method GetMessageFromTemplate
|
||||
*/
|
||||
@Test
|
||||
public void testGetMessageFromTemplate(){
|
||||
|
||||
DefaultHTMLTemplate template = new DefaultHTMLTemplate();
|
||||
|
||||
String tableTypeMessage = template.getMessageFromTemplate(list2String(), ShowType.TABLE,true);
|
||||
|
||||
assertEquals(tableTypeMessage,generateMockTableTypeResultByHand());
|
||||
|
||||
String textTypeMessage = template.getMessageFromTemplate(list2String(), ShowType.TEXT,true);
|
||||
|
||||
assertEquals(textTypeMessage,generateMockTextTypeResultByHand());
|
||||
}
|
||||
|
||||
/**
|
||||
* generate some simulation data
|
||||
*/
|
||||
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("database client connections","190");
|
||||
map1.put("port","3306");
|
||||
map1.put("no index of number","80");
|
||||
|
||||
LinkedHashMap<String, Object> map2 = new LinkedHashMap<>();
|
||||
map2.put("mysql service name","mysql210");
|
||||
map2.put("mysql address","192.168.xx.xx");
|
||||
map2.put("database client connections","90");
|
||||
map2.put("port","3306");
|
||||
map2.put("no index of number","10");
|
||||
|
||||
List<LinkedHashMap<String, Object>> maps = new ArrayList<>();
|
||||
maps.add(0,map1);
|
||||
maps.add(1,map2);
|
||||
String mapjson = JSONUtils.toJsonString(maps);
|
||||
logger.info(mapjson);
|
||||
|
||||
return mapjson;
|
||||
}
|
||||
|
||||
private String generateMockTableTypeResultByHand(){
|
||||
|
||||
return Constants.HTML_HEADER_PREFIX +
|
||||
"<thead><tr><th>mysql service name</th><th>mysql address</th><th>database client connections</th><th>port</th><th>no index of number</th></tr></thead>\n" +
|
||||
"<tr><td>mysql200</td><td>192.168.xx.xx</td><td>190</td><td>3306</td><td>80</td></tr><tr><td>mysql210</td><td>192.168.xx.xx</td><td>90</td><td>3306</td><td>10</td></tr>" + Constants.TABLE_BODY_HTML_TAIL;
|
||||
|
||||
}
|
||||
|
||||
private String generateMockTextTypeResultByHand(){
|
||||
|
||||
return Constants.HTML_HEADER_PREFIX + "<tr><td>{\"mysql service name\":\"mysql200\",\"mysql address\":\"192.168.xx.xx\",\"database client connections\":\"190\",\"port\":\"3306\",\"no index of number\":\"80\"}</td></tr><tr><td>{\"mysql service name\":\"mysql210\",\"mysql address\":\"192.168.xx.xx\",\"database client connections\":\"90\",\"port\":\"3306\",\"no index of number\":\"10\"}</td></tr>" + Constants.TABLE_BODY_HTML_TAIL;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,120 +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 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;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
@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 = JSONUtils.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(80, rc.getProxy().getPort());
|
||||
Assert.assertEquals("proxy.com.cn", rc.getProxy().getHostName());
|
||||
}
|
||||
|
||||
@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.IS_ENABLE_DING_TALK);
|
||||
String expect = "{\"text\":{\"content\":\"this is test:中文\"},\"msgtype\":\"text\"}";
|
||||
Assert.assertEquals(expect, msg);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,283 +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.enums.ShowType;
|
||||
import org.apache.dolphinscheduler.common.utils.JSONUtils;
|
||||
import org.apache.dolphinscheduler.dao.entity.Alert;
|
||||
import org.apache.dolphinscheduler.plugin.model.AlertData;
|
||||
|
||||
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();
|
||||
alertData.setTitle(alertForText.getTitle())
|
||||
.setShowType(alertForText.getShowType().getDescp())
|
||||
.setContent(alertForText.getContent());
|
||||
String result = EnterpriseWeChatUtils.markdownByAlert(alertData);
|
||||
Assert.assertNotNull(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMarkdownByAlertForTable() {
|
||||
Alert alertForText = createAlertForTable();
|
||||
AlertData alertData = new AlertData();
|
||||
alertData.setTitle(alertForText.getTitle())
|
||||
.setShowType(alertForText.getShowType().getDescp())
|
||||
.setContent(alertForText.getContent());
|
||||
String result = EnterpriseWeChatUtils.markdownByAlert(alertData);
|
||||
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);
|
||||
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();
|
||||
// }
|
||||
// }
|
||||
|
||||
}
|
||||
|
|
@ -17,14 +17,14 @@
|
|||
|
||||
package org.apache.dolphinscheduler.alert.utils;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNull;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import org.junit.Test;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class FuncUtilsTest {
|
||||
|
||||
|
|
|
|||
|
|
@ -1,190 +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.enums.ShowType;
|
||||
import org.apache.dolphinscheduler.dao.AlertDao;
|
||||
import org.apache.dolphinscheduler.dao.DaoFactory;
|
||||
import org.apache.dolphinscheduler.dao.entity.Alert;
|
||||
import org.apache.dolphinscheduler.dao.entity.User;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.*;
|
||||
import org.apache.dolphinscheduler.common.utils.*;
|
||||
|
||||
|
||||
/**
|
||||
*/
|
||||
public class MailUtilsTest {
|
||||
private static final Logger logger = LoggerFactory.getLogger(MailUtilsTest.class);
|
||||
@Test
|
||||
public void testSendMails() {
|
||||
String[] receivers = new String[]{"347801120@qq.com"};
|
||||
String[] receiversCc = new String[]{"347801120@qq.com"};
|
||||
|
||||
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);
|
||||
|
||||
MailUtils.sendMails(Arrays.asList(receivers),Arrays.asList(receiversCc),alert.getTitle(),alert.getContent(), ShowType.TEXT.getDescp());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testQuery(){
|
||||
AlertDao alertDao = DaoFactory.getDaoInstance(AlertDao.class);
|
||||
List<Alert> alerts = alertDao.listWaitExecutionAlert();
|
||||
|
||||
String[] mails = new String[]{"xx@xx.com"};
|
||||
|
||||
for(Alert alert : alerts){
|
||||
MailUtils.sendMails(Arrays.asList(mails),"gaojing", alert.getContent(), ShowType.TABLE.getDescp());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public 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);
|
||||
logger.info(mapjson);
|
||||
|
||||
return mapjson;
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSendTableMail(){
|
||||
String[] mails = new String[]{"347801120@qq.com"};
|
||||
Alert alert = new Alert();
|
||||
alert.setTitle("Mysql Exception");
|
||||
alert.setShowType(ShowType.TABLE);
|
||||
String content= list2String();
|
||||
alert.setContent(content);
|
||||
alert.setAlertType(AlertType.EMAIL);
|
||||
alert.setAlertGroupId(1);
|
||||
MailUtils.sendMails(Arrays.asList(mails),"gaojing", alert.getContent(), ShowType.TABLE.getDescp());
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to test add alarm information, mail sent
|
||||
* Text
|
||||
*/
|
||||
@Test
|
||||
public void addAlertText(){
|
||||
AlertDao alertDao = DaoFactory.getDaoInstance(AlertDao.class);
|
||||
Alert alert = new Alert();
|
||||
alert.setTitle("Mysql Exception");
|
||||
alert.setShowType(ShowType.TEXT);
|
||||
alert.setContent("[\"alarm time:2018-02-05\", \"service name:MYSQL_ALTER\", \"alarm name:MYSQL_ALTER_DUMP\", " +
|
||||
"\"get the alarm exception.!,interface error,exception information:timed out\", \"request address:http://blog.csdn.net/dreamInTheWorld/article/details/78539286\"]");
|
||||
alert.setAlertType(AlertType.EMAIL);
|
||||
alert.setAlertGroupId(1);
|
||||
alertDao.addAlert(alert);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Used to test add alarm information, mail sent
|
||||
* Table
|
||||
*/
|
||||
@Test
|
||||
public void testAddAlertTable(){
|
||||
logger.info("testAddAlertTable");
|
||||
AlertDao alertDao = DaoFactory.getDaoInstance(AlertDao.class);
|
||||
Assert.assertNotNull(alertDao);
|
||||
Alert alert = new Alert();
|
||||
alert.setTitle("Mysql Exception");
|
||||
alert.setShowType(ShowType.TABLE);
|
||||
|
||||
String content = list2String();
|
||||
alert.setContent(content);
|
||||
alert.setAlertType(AlertType.EMAIL);
|
||||
alert.setAlertGroupId(1);
|
||||
alertDao.addAlert(alert);
|
||||
logger.info("" +alert);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAlertDao(){
|
||||
AlertDao alertDao = DaoFactory.getDaoInstance(AlertDao.class);
|
||||
List<User> users = alertDao.listUserByAlertgroupId(3);
|
||||
logger.info(users.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAttachmentFile()throws Exception{
|
||||
String[] mails = new String[]{"xx@xx.com"};
|
||||
Alert alert = new Alert();
|
||||
alert.setTitle("Mysql Exception");
|
||||
alert.setShowType(ShowType.ATTACHMENT);
|
||||
String content = list2String();
|
||||
alert.setContent(content);
|
||||
alert.setAlertType(AlertType.EMAIL);
|
||||
alert.setAlertGroupId(1);
|
||||
MailUtils.sendMails(Arrays.asList(mails),"gaojing",alert.getContent(),ShowType.ATTACHMENT.getDescp());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTableAttachmentFile()throws Exception{
|
||||
String[] mails = new String[]{"xx@xx.com"};
|
||||
Alert alert = new Alert();
|
||||
alert.setTitle("Mysql Exception");
|
||||
alert.setShowType(ShowType.TABLEATTACHMENT);
|
||||
String content = list2String();
|
||||
alert.setContent(content);
|
||||
alert.setAlertType(AlertType.EMAIL);
|
||||
alert.setAlertGroupId(1);
|
||||
MailUtils.sendMails(Arrays.asList(mails),"gaojing",alert.getContent(),ShowType.TABLEATTACHMENT.getDescp());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -14,31 +14,44 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.apache.dolphinscheduler.api.controller;
|
||||
|
||||
import static org.apache.dolphinscheduler.api.enums.Status.CREATE_ALERT_GROUP_ERROR;
|
||||
import static org.apache.dolphinscheduler.api.enums.Status.DELETE_ALERT_GROUP_ERROR;
|
||||
import static org.apache.dolphinscheduler.api.enums.Status.LIST_PAGING_ALERT_GROUP_ERROR;
|
||||
import static org.apache.dolphinscheduler.api.enums.Status.QUERY_ALL_ALERTGROUP_ERROR;
|
||||
import static org.apache.dolphinscheduler.api.enums.Status.UPDATE_ALERT_GROUP_ERROR;
|
||||
|
||||
import org.apache.dolphinscheduler.api.enums.Status;
|
||||
import org.apache.dolphinscheduler.api.exceptions.ApiException;
|
||||
import org.apache.dolphinscheduler.api.service.AlertGroupService;
|
||||
import org.apache.dolphinscheduler.api.utils.Result;
|
||||
import org.apache.dolphinscheduler.common.Constants;
|
||||
import org.apache.dolphinscheduler.common.enums.AlertType;
|
||||
import org.apache.dolphinscheduler.common.utils.ParameterUtils;
|
||||
import org.apache.dolphinscheduler.common.utils.StringUtils;
|
||||
import org.apache.dolphinscheduler.dao.entity.User;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiImplicitParam;
|
||||
import io.swagger.annotations.ApiImplicitParams;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.apache.dolphinscheduler.api.enums.Status;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import springfox.documentation.annotations.ApiIgnore;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.apache.dolphinscheduler.api.enums.Status.*;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestAttribute;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiImplicitParam;
|
||||
import io.swagger.annotations.ApiImplicitParams;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import springfox.documentation.annotations.ApiIgnore;
|
||||
|
||||
/**
|
||||
* alert group controller
|
||||
|
|
@ -57,28 +70,31 @@ public class AlertGroupController extends BaseController {
|
|||
/**
|
||||
* create alert group
|
||||
*
|
||||
* @param loginUser login user
|
||||
* @param groupName group name
|
||||
* @param groupType group type
|
||||
* @param loginUser login user
|
||||
* @param groupName group name
|
||||
* @param description description
|
||||
* @return create result code
|
||||
*/
|
||||
@ApiOperation(value = "createAlertgroup", notes = "CREATE_ALERT_GROUP_NOTES")
|
||||
@ApiImplicitParams({
|
||||
@ApiImplicitParam(name = "groupName", value = "GROUP_NAME", required = true, dataType = "String"),
|
||||
@ApiImplicitParam(name = "groupType", value = "GROUP_TYPE", required = true, dataType = "AlertType"),
|
||||
@ApiImplicitParam(name = "description", value = "DESC", dataType = "String")
|
||||
@ApiImplicitParam(name = "description", value = "DESC", dataType = "String"),
|
||||
@ApiImplicitParam(name = "alertInstanceIds", value = "alertInstanceIds", dataType = "String")
|
||||
})
|
||||
@PostMapping(value = "/create")
|
||||
@ResponseStatus(HttpStatus.CREATED)
|
||||
@ApiException(CREATE_ALERT_GROUP_ERROR)
|
||||
public Result createAlertgroup(@ApiIgnore @RequestAttribute(value = Constants.SESSION_USER) User loginUser,
|
||||
@RequestParam(value = "groupName") String groupName,
|
||||
@RequestParam(value = "groupType") AlertType groupType,
|
||||
@RequestParam(value = "description", required = false) String description) {
|
||||
logger.info("loginUser user {}, create alertgroup, groupName: {}, groupType: {}, desc: {}",
|
||||
loginUser.getUserName(), groupName, groupType, description);
|
||||
Map<String, Object> result = alertGroupService.createAlertgroup(loginUser, groupName, groupType, description);
|
||||
@RequestParam(value = "description", required = false) String description,
|
||||
@RequestParam(value = "alertInstanceIds") String alertInstanceIds) {
|
||||
String strUserName = StringUtils.replaceNRTtoUnderline(loginUser.getUserName());
|
||||
String strGroupName = StringUtils.replaceNRTtoUnderline(groupName);
|
||||
String strDescription = StringUtils.replaceNRTtoUnderline(description);
|
||||
String strAlertInstanceIds = StringUtils.replaceNRTtoUnderline(alertInstanceIds);
|
||||
logger.info("loginUser user {}, create alert group, groupName: {}, desc: {},alertInstanceIds:{}",
|
||||
strUserName, strGroupName, strDescription, strAlertInstanceIds);
|
||||
Map<String, Object> result = alertGroupService.createAlertgroup(loginUser, groupName, description, alertInstanceIds);
|
||||
return returnDataList(result);
|
||||
}
|
||||
|
||||
|
|
@ -103,9 +119,9 @@ public class AlertGroupController extends BaseController {
|
|||
* paging query alarm group list
|
||||
*
|
||||
* @param loginUser login user
|
||||
* @param pageNo page number
|
||||
* @param pageNo page number
|
||||
* @param searchVal search value
|
||||
* @param pageSize page size
|
||||
* @param pageSize page size
|
||||
* @return alert group list page
|
||||
*/
|
||||
@ApiOperation(value = "queryAlertGroupListPaging", notes = "QUERY_ALERT_GROUP_LIST_PAGING_NOTES")
|
||||
|
|
@ -136,10 +152,9 @@ public class AlertGroupController extends BaseController {
|
|||
/**
|
||||
* updateProcessInstance alert group
|
||||
*
|
||||
* @param loginUser login user
|
||||
* @param id alert group id
|
||||
* @param groupName group name
|
||||
* @param groupType group type
|
||||
* @param loginUser login user
|
||||
* @param id alert group id
|
||||
* @param groupName group name
|
||||
* @param description description
|
||||
* @return update result code
|
||||
*/
|
||||
|
|
@ -147,8 +162,8 @@ public class AlertGroupController extends BaseController {
|
|||
@ApiImplicitParams({
|
||||
@ApiImplicitParam(name = "id", value = "ALERT_GROUP_ID", required = true, dataType = "Int", example = "100"),
|
||||
@ApiImplicitParam(name = "groupName", value = "GROUP_NAME", required = true, dataType = "String"),
|
||||
@ApiImplicitParam(name = "groupType", value = "GROUP_TYPE", required = true, dataType = "AlertType"),
|
||||
@ApiImplicitParam(name = "description", value = "DESC", dataType = "String")
|
||||
@ApiImplicitParam(name = "description", value = "DESC", dataType = "String"),
|
||||
@ApiImplicitParam(name = "alertInstanceIds", value = "alertInstanceIds", dataType = "String")
|
||||
})
|
||||
@PostMapping(value = "/update")
|
||||
@ResponseStatus(HttpStatus.OK)
|
||||
|
|
@ -156,11 +171,13 @@ public class AlertGroupController extends BaseController {
|
|||
public Result updateAlertgroup(@ApiIgnore @RequestAttribute(value = Constants.SESSION_USER) User loginUser,
|
||||
@RequestParam(value = "id") int id,
|
||||
@RequestParam(value = "groupName") String groupName,
|
||||
@RequestParam(value = "groupType") AlertType groupType,
|
||||
@RequestParam(value = "description", required = false) String description) {
|
||||
logger.info("login user {}, updateProcessInstance alertgroup, groupName: {}, groupType: {}, desc: {}",
|
||||
loginUser.getUserName(), groupName, groupType, description);
|
||||
Map<String, Object> result = alertGroupService.updateAlertgroup(loginUser, id, groupName, groupType, description);
|
||||
@RequestParam(value = "description", required = false) String description,
|
||||
@RequestParam(value = "alertInstanceIds") String alertInstanceIds) {
|
||||
logger.info("login user {}, updateProcessInstance alert group, groupName: {}, desc: {}",
|
||||
StringUtils.replaceNRTtoUnderline(loginUser.getUserName()),
|
||||
StringUtils.replaceNRTtoUnderline(groupName),
|
||||
StringUtils.replaceNRTtoUnderline(description));
|
||||
Map<String, Object> result = alertGroupService.updateAlertgroup(loginUser, id, groupName, description, alertInstanceIds);
|
||||
return returnDataList(result);
|
||||
}
|
||||
|
||||
|
|
@ -168,7 +185,7 @@ public class AlertGroupController extends BaseController {
|
|||
* delete alert group by id
|
||||
*
|
||||
* @param loginUser login user
|
||||
* @param id alert group id
|
||||
* @param id alert group id
|
||||
* @return delete result code
|
||||
*/
|
||||
@ApiOperation(value = "delAlertgroupById", notes = "DELETE_ALERT_GROUP_BY_ID_NOTES")
|
||||
|
|
@ -215,28 +232,4 @@ public class AlertGroupController extends BaseController {
|
|||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* grant user
|
||||
*
|
||||
* @param loginUser login user
|
||||
* @param userIds user ids in the group
|
||||
* @param alertgroupId alert group id
|
||||
* @return grant result code
|
||||
*/
|
||||
@ApiOperation(value = "grantUser", notes = "GRANT_ALERT_GROUP_NOTES")
|
||||
@ApiImplicitParams({
|
||||
@ApiImplicitParam(name = "id", value = "ALERT_GROUP_ID", required = true, dataType = "Int", example = "100"),
|
||||
@ApiImplicitParam(name = "userIds", value = "USER_IDS", required = true, dataType = "String")
|
||||
})
|
||||
@PostMapping(value = "/grant-user")
|
||||
@ResponseStatus(HttpStatus.OK)
|
||||
@ApiException(ALERT_GROUP_GRANT_USER_ERROR)
|
||||
public Result grantUser(@ApiIgnore @RequestAttribute(value = Constants.SESSION_USER) User loginUser,
|
||||
@RequestParam(value = "alertgroupId") int alertgroupId,
|
||||
@RequestParam(value = "userIds") String userIds) {
|
||||
logger.info("login user {}, grant user, alertGroupId: {},userIds : {}", loginUser.getUserName(), alertgroupId, userIds);
|
||||
Map<String, Object> result = alertGroupService.grantUser(loginUser, alertgroupId, userIds);
|
||||
return returnDataList(result);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,240 @@
|
|||
/*
|
||||
* 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.api.controller;
|
||||
|
||||
import static org.apache.dolphinscheduler.api.enums.Status.CREATE_ALERT_PLUGIN_INSTANCE_ERROR;
|
||||
import static org.apache.dolphinscheduler.api.enums.Status.DELETE_ALERT_PLUGIN_INSTANCE_ERROR;
|
||||
import static org.apache.dolphinscheduler.api.enums.Status.GET_ALERT_PLUGIN_INSTANCE_ERROR;
|
||||
import static org.apache.dolphinscheduler.api.enums.Status.LIST_PAGING_ALERT_PLUGIN_INSTANCE_ERROR;
|
||||
import static org.apache.dolphinscheduler.api.enums.Status.QUERY_ALL_ALERT_PLUGIN_INSTANCE_ERROR;
|
||||
import static org.apache.dolphinscheduler.api.enums.Status.UPDATE_ALERT_PLUGIN_INSTANCE_ERROR;
|
||||
|
||||
import org.apache.dolphinscheduler.api.enums.Status;
|
||||
import org.apache.dolphinscheduler.api.exceptions.ApiException;
|
||||
import org.apache.dolphinscheduler.api.service.AlertPluginInstanceService;
|
||||
import org.apache.dolphinscheduler.api.utils.Result;
|
||||
import org.apache.dolphinscheduler.common.Constants;
|
||||
import org.apache.dolphinscheduler.common.utils.StringUtils;
|
||||
import org.apache.dolphinscheduler.dao.entity.User;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestAttribute;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiImplicitParam;
|
||||
import io.swagger.annotations.ApiImplicitParams;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import springfox.documentation.annotations.ApiIgnore;
|
||||
|
||||
/**
|
||||
* alert plugin instance controller
|
||||
*/
|
||||
@Api(tags = "ALERT_PLUGIN_INSTANCE_TAG", position = 1)
|
||||
@RestController
|
||||
@RequestMapping("alert-plugin-instance")
|
||||
public class AlertPluginInstanceController extends BaseController {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(AlertPluginInstanceController.class);
|
||||
|
||||
@Autowired
|
||||
private AlertPluginInstanceService alertPluginInstanceService;
|
||||
|
||||
|
||||
/**
|
||||
* create alert plugin instance
|
||||
*
|
||||
* @param loginUser login user
|
||||
* @param pluginDefineId alert plugin define id
|
||||
* @param instanceName instance name
|
||||
* @param pluginInstanceParams instance params
|
||||
* @return result
|
||||
*/
|
||||
@ApiOperation(value = "createAlertPluginInstance", notes = "CREATE_ALERT_PLUGIN_INSTANCE_NOTES")
|
||||
@ApiImplicitParams({
|
||||
@ApiImplicitParam(name = "pluginDefineId", value = "ALERT_PLUGIN_DEFINE_ID", required = true, dataType = "Int", example = "100"),
|
||||
@ApiImplicitParam(name = "instanceName", value = "ALERT_PLUGIN_INSTANCE_NAME", required = true, dataType = "String", example = "DING TALK"),
|
||||
@ApiImplicitParam(name = "pluginInstanceParams", value = "ALERT_PLUGIN_INSTANCE_PARAMS", required = true, dataType = "String", example = "ALERT_PLUGIN_INSTANCE_PARAMS")
|
||||
})
|
||||
@PostMapping(value = "/create")
|
||||
@ResponseStatus(HttpStatus.CREATED)
|
||||
@ApiException(CREATE_ALERT_PLUGIN_INSTANCE_ERROR)
|
||||
public Result createAlertPluginInstance(@ApiIgnore @RequestAttribute(value = Constants.SESSION_USER) User loginUser,
|
||||
@RequestParam(value = "pluginDefineId") int pluginDefineId,
|
||||
@RequestParam(value = "instanceName") String instanceName,
|
||||
@RequestParam(value = "pluginInstanceParams") String pluginInstanceParams) {
|
||||
logger.info("login user {},create alert plugin instance, instanceName:{} ",
|
||||
StringUtils.replaceNRTtoUnderline(loginUser.getUserName()),
|
||||
StringUtils.replaceNRTtoUnderline(instanceName));
|
||||
Map<String, Object> result = alertPluginInstanceService.create(loginUser, pluginDefineId, instanceName, pluginInstanceParams);
|
||||
return returnDataList(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* updateAlertPluginInstance
|
||||
*
|
||||
* @param loginUser login user
|
||||
* @param alertPluginInstanceId alert plugin instance id
|
||||
* @param instanceName instance name
|
||||
* @param pluginInstanceParams instance params
|
||||
* @return result
|
||||
*/
|
||||
@ApiOperation(value = "update", notes = "UPDATE_ALERT_PLUGIN_INSTANCE_NOTES")
|
||||
@ApiImplicitParams({
|
||||
@ApiImplicitParam(name = "alertPluginInstanceId", value = "ALERT_PLUGIN_INSTANCE_ID", required = true, dataType = "Int", example = "100"),
|
||||
@ApiImplicitParam(name = "instanceName", value = "ALERT_PLUGIN_INSTANCE_NAME", required = true, dataType = "String", example = "DING TALK"),
|
||||
@ApiImplicitParam(name = "pluginInstanceParams", value = "ALERT_PLUGIN_INSTANCE_PARAMS", required = true, dataType = "String", example = "ALERT_PLUGIN_INSTANCE_PARAMS")
|
||||
})
|
||||
@GetMapping(value = "/update")
|
||||
@ResponseStatus(HttpStatus.OK)
|
||||
@ApiException(UPDATE_ALERT_PLUGIN_INSTANCE_ERROR)
|
||||
public Result updateAlertPluginInstance(@ApiIgnore @RequestAttribute(value = Constants.SESSION_USER) User loginUser,
|
||||
@RequestParam(value = "alertPluginInstanceId") int alertPluginInstanceId,
|
||||
@RequestParam(value = "instanceName") String instanceName,
|
||||
@RequestParam(value = "pluginInstanceParams") String pluginInstanceParams) {
|
||||
logger.info("login user {},update alert plugin instance id {}", StringUtils.replaceNRTtoUnderline(loginUser.getUserName()), alertPluginInstanceId);
|
||||
Map<String, Object> result = alertPluginInstanceService.update(loginUser, alertPluginInstanceId, instanceName, pluginInstanceParams);
|
||||
return returnDataList(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* deleteAlertPluginInstance
|
||||
*
|
||||
* @param loginUser login user
|
||||
* @param id id
|
||||
* @return result
|
||||
*/
|
||||
@ApiOperation(value = "delete", notes = "DELETE_ALERT_PLUGIN_INSTANCE_NOTES")
|
||||
@ApiImplicitParams({
|
||||
@ApiImplicitParam(name = "id", value = "ALERT_PLUGIN_ID", required = true, dataType = "Int", example = "100")
|
||||
})
|
||||
@GetMapping(value = "/delete")
|
||||
@ResponseStatus(HttpStatus.OK)
|
||||
@ApiException(DELETE_ALERT_PLUGIN_INSTANCE_ERROR)
|
||||
public Result deleteAlertPluginInstance(@ApiIgnore @RequestAttribute(value = Constants.SESSION_USER) User loginUser,
|
||||
@RequestParam(value = "id") int id) {
|
||||
logger.info("login user {},delete alert plugin instance id {}", StringUtils.replaceNRTtoUnderline(loginUser.getUserName()), id);
|
||||
|
||||
Map<String, Object> result = alertPluginInstanceService.delete(loginUser, id);
|
||||
return returnDataList(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* getAlertPluginInstance
|
||||
*
|
||||
* @param loginUser login user
|
||||
* @param id alert plugin instance id
|
||||
* @return result
|
||||
*/
|
||||
@ApiOperation(value = "get", notes = "GET_ALERT_PLUGIN_INSTANCE_NOTES")
|
||||
@PostMapping(value = "/get")
|
||||
@ResponseStatus(HttpStatus.OK)
|
||||
@ApiException(GET_ALERT_PLUGIN_INSTANCE_ERROR)
|
||||
public Result getAlertPluginInstance(@ApiIgnore @RequestAttribute(value = Constants.SESSION_USER) User loginUser,
|
||||
@RequestParam(value = "id") int id) {
|
||||
logger.info("login user {},get alert plugin instance, id {}", StringUtils.replaceNRTtoUnderline(loginUser.getUserName()), id);
|
||||
Map<String, Object> result = alertPluginInstanceService.get(loginUser, id);
|
||||
return returnDataList(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* getAlertPluginInstance
|
||||
*
|
||||
* @param loginUser login user
|
||||
* @return result
|
||||
*/
|
||||
@ApiOperation(value = "/queryAll", notes = "QUERY_ALL_ALERT_PLUGIN_INSTANCE_NOTES")
|
||||
@PostMapping(value = "/queryAll")
|
||||
@ResponseStatus(HttpStatus.OK)
|
||||
@ApiException(QUERY_ALL_ALERT_PLUGIN_INSTANCE_ERROR)
|
||||
public Result getAlertPluginInstance(@ApiIgnore @RequestAttribute(value = Constants.SESSION_USER) User loginUser) {
|
||||
logger.info("login user {}, query all alert plugin instance", StringUtils.replaceNRTtoUnderline(loginUser.getUserName()));
|
||||
Map<String, Object> result = alertPluginInstanceService.queryAll();
|
||||
return returnDataList(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* check alert group exist
|
||||
*
|
||||
* @param loginUser login user
|
||||
* @param alertInstanceName alert instance name
|
||||
* @return check result code
|
||||
*/
|
||||
@ApiOperation(value = "verifyAlertInstanceName", notes = "VERIFY_ALERT_INSTANCE_NAME_NOTES")
|
||||
@ApiImplicitParams({
|
||||
@ApiImplicitParam(name = "groupName", value = "GROUP_NAME", required = true, dataType = "String"),
|
||||
})
|
||||
@GetMapping(value = "/verify-alert-instance-name")
|
||||
@ResponseStatus(HttpStatus.OK)
|
||||
public Result verifyGroupName(@ApiIgnore @RequestAttribute(value = Constants.SESSION_USER) User loginUser,
|
||||
@RequestParam(value = "alertInstanceName") String alertInstanceName) {
|
||||
logger.info("login user {},verify alert instance name: {}", StringUtils.replaceNRTtoUnderline(loginUser.getUserName()), StringUtils.replaceNRTtoUnderline(alertInstanceName));
|
||||
|
||||
boolean exist = alertPluginInstanceService.checkExistPluginInstanceName(alertInstanceName);
|
||||
Result result = new Result();
|
||||
if (exist) {
|
||||
logger.error("alert plugin instance {} has exist, can't create again.", alertInstanceName);
|
||||
result.setCode(Status.PLUGIN_INSTANCE_ALREADY_EXIT.getCode());
|
||||
result.setMsg(Status.PLUGIN_INSTANCE_ALREADY_EXIT.getMsg());
|
||||
} else {
|
||||
result.setCode(Status.SUCCESS.getCode());
|
||||
result.setMsg(Status.SUCCESS.getMsg());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* paging query alert plugin instance group list
|
||||
*
|
||||
* @param loginUser login user
|
||||
* @param pageNo page number
|
||||
* @param pageSize page size
|
||||
* @return alert plugin instance list page
|
||||
*/
|
||||
@ApiOperation(value = "queryAlertPluginInstanceListPaging", notes = "QUERY_ALERT_PLUGIN_INSTANCE_LIST_PAGING_NOTES")
|
||||
@ApiImplicitParams({
|
||||
@ApiImplicitParam(name = "pageNo", value = "PAGE_NO", dataType = "Int", example = "1"),
|
||||
@ApiImplicitParam(name = "pageSize", value = "PAGE_SIZE", dataType = "Int", example = "20")
|
||||
})
|
||||
@GetMapping(value = "/list-paging")
|
||||
@ResponseStatus(HttpStatus.OK)
|
||||
@ApiException(LIST_PAGING_ALERT_PLUGIN_INSTANCE_ERROR)
|
||||
public Result listPaging(@ApiIgnore @RequestAttribute(value = Constants.SESSION_USER) User loginUser,
|
||||
@RequestParam("pageNo") Integer pageNo,
|
||||
@RequestParam("pageSize") Integer pageSize) {
|
||||
logger.info("login user {}, list paging, pageNo: {}, pageSize: {}",StringUtils.replaceNRTtoUnderline(loginUser.getUserName()), pageNo, pageSize);
|
||||
Map<String, Object> result = checkPageParams(pageNo, pageSize);
|
||||
if (result.get(Constants.STATUS) != Status.SUCCESS) {
|
||||
return returnDataListPaging(result);
|
||||
}
|
||||
|
||||
result = alertPluginInstanceService.queryPluginPage(pageNo, pageSize);
|
||||
return returnDataListPaging(result);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -14,30 +14,48 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.apache.dolphinscheduler.api.controller;
|
||||
|
||||
import static org.apache.dolphinscheduler.api.enums.Status.CHECK_PROCESS_DEFINITION_ERROR;
|
||||
import static org.apache.dolphinscheduler.api.enums.Status.EXECUTE_PROCESS_INSTANCE_ERROR;
|
||||
import static org.apache.dolphinscheduler.api.enums.Status.START_PROCESS_INSTANCE_ERROR;
|
||||
|
||||
import org.apache.dolphinscheduler.api.enums.ExecuteType;
|
||||
import org.apache.dolphinscheduler.api.exceptions.ApiException;
|
||||
import org.apache.dolphinscheduler.api.service.ExecutorService;
|
||||
import org.apache.dolphinscheduler.api.utils.Result;
|
||||
import org.apache.dolphinscheduler.common.Constants;
|
||||
import org.apache.dolphinscheduler.common.enums.CommandType;
|
||||
import org.apache.dolphinscheduler.common.enums.FailureStrategy;
|
||||
import org.apache.dolphinscheduler.common.enums.Priority;
|
||||
import org.apache.dolphinscheduler.common.enums.RunMode;
|
||||
import org.apache.dolphinscheduler.common.enums.TaskDependType;
|
||||
import org.apache.dolphinscheduler.common.enums.WarningType;
|
||||
import org.apache.dolphinscheduler.common.utils.JSONUtils;
|
||||
import org.apache.dolphinscheduler.dao.entity.User;
|
||||
import io.swagger.annotations.*;
|
||||
import org.apache.dolphinscheduler.common.enums.*;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import springfox.documentation.annotations.ApiIgnore;
|
||||
|
||||
import java.text.ParseException;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.apache.dolphinscheduler.api.enums.Status.*;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestAttribute;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiImplicitParam;
|
||||
import io.swagger.annotations.ApiImplicitParams;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import io.swagger.annotations.ApiParam;
|
||||
import springfox.documentation.annotations.ApiIgnore;
|
||||
|
||||
/**
|
||||
* execute process controller
|
||||
|
|
@ -55,22 +73,20 @@ public class ExecutorController extends BaseController {
|
|||
/**
|
||||
* execute process instance
|
||||
*
|
||||
* @param loginUser login user
|
||||
* @param projectName project name
|
||||
* @param processDefinitionId process definition id
|
||||
* @param scheduleTime schedule time
|
||||
* @param failureStrategy failure strategy
|
||||
* @param startNodeList start nodes list
|
||||
* @param taskDependType task depend type
|
||||
* @param execType execute type
|
||||
* @param warningType warning type
|
||||
* @param warningGroupId warning group id
|
||||
* @param receivers receivers
|
||||
* @param receiversCc receivers cc
|
||||
* @param runMode run mode
|
||||
* @param loginUser login user
|
||||
* @param projectName project name
|
||||
* @param processDefinitionId process definition id
|
||||
* @param scheduleTime schedule time
|
||||
* @param failureStrategy failure strategy
|
||||
* @param startNodeList start nodes list
|
||||
* @param taskDependType task depend type
|
||||
* @param execType execute type
|
||||
* @param warningType warning type
|
||||
* @param warningGroupId warning group id
|
||||
* @param runMode run mode
|
||||
* @param processInstancePriority process instance priority
|
||||
* @param workerGroup worker group
|
||||
* @param timeout timeout
|
||||
* @param workerGroup worker group
|
||||
* @param timeout timeout
|
||||
* @return start process result code
|
||||
*/
|
||||
@ApiOperation(value = "startProcessInstance", notes = "RUN_PROCESS_INSTANCE_NOTES")
|
||||
|
|
@ -83,8 +99,6 @@ public class ExecutorController extends BaseController {
|
|||
@ApiImplicitParam(name = "execType", value = "COMMAND_TYPE", dataType = "CommandType"),
|
||||
@ApiImplicitParam(name = "warningType", value = "WARNING_TYPE", required = true, dataType = "WarningType"),
|
||||
@ApiImplicitParam(name = "warningGroupId", value = "WARNING_GROUP_ID", required = true, dataType = "Int", example = "100"),
|
||||
@ApiImplicitParam(name = "receivers", value = "RECEIVERS", dataType = "String"),
|
||||
@ApiImplicitParam(name = "receiversCc", value = "RECEIVERS_CC", dataType = "String"),
|
||||
@ApiImplicitParam(name = "runMode", value = "RUN_MODE", dataType = "RunMode"),
|
||||
@ApiImplicitParam(name = "processInstancePriority", value = "PROCESS_INSTANCE_PRIORITY", required = true, dataType = "Priority"),
|
||||
@ApiImplicitParam(name = "workerGroup", value = "WORKER_GROUP", dataType = "String", example = "default"),
|
||||
|
|
@ -103,19 +117,16 @@ public class ExecutorController extends BaseController {
|
|||
@RequestParam(value = "execType", required = false) CommandType execType,
|
||||
@RequestParam(value = "warningType", required = true) WarningType warningType,
|
||||
@RequestParam(value = "warningGroupId", required = false) int warningGroupId,
|
||||
@RequestParam(value = "receivers", required = false) String receivers,
|
||||
@RequestParam(value = "receiversCc", required = false) String receiversCc,
|
||||
@RequestParam(value = "runMode", required = false) RunMode runMode,
|
||||
@RequestParam(value = "processInstancePriority", required = false) Priority processInstancePriority,
|
||||
@RequestParam(value = "workerGroup", required = false, defaultValue = "default") String workerGroup,
|
||||
@RequestParam(value = "timeout", required = false) Integer timeout,
|
||||
@RequestParam(value = "startParams", required = false) String startParams) throws ParseException {
|
||||
logger.info("login user {}, start process instance, project name: {}, process definition id: {}, schedule time: {}, "
|
||||
logger.info("login user {}, start process instance, project name: {}, process definition id: {}, schedule time: {}, "
|
||||
+ "failure policy: {}, node name: {}, node dep: {}, notify type: {}, "
|
||||
+ "notify group id: {},receivers:{},receiversCc:{}, run mode: {},process instance priority:{}, workerGroup: {}, timeout: {}, "
|
||||
+ "startParams: {}",
|
||||
+ "notify group id: {}, run mode: {},process instance priority:{}, workerGroup: {}, timeout: {}, startParams: {} ",
|
||||
loginUser.getUserName(), projectName, processDefinitionId, scheduleTime,
|
||||
failureStrategy, startNodeList, taskDependType, warningType, workerGroup, receivers, receiversCc, runMode, processInstancePriority,
|
||||
failureStrategy, startNodeList, taskDependType, warningType, workerGroup, runMode, processInstancePriority,
|
||||
workerGroup, timeout, startParams);
|
||||
|
||||
if (timeout == null) {
|
||||
|
|
@ -127,7 +138,7 @@ public class ExecutorController extends BaseController {
|
|||
}
|
||||
Map<String, Object> result = execService.execProcessInstance(loginUser, projectName, processDefinitionId, scheduleTime, execType, failureStrategy,
|
||||
startNodeList, taskDependType, warningType,
|
||||
warningGroupId, receivers, receiversCc, runMode, processInstancePriority, workerGroup, timeout, startParamMap);
|
||||
warningGroupId, runMode, processInstancePriority, workerGroup, timeout, startParamMap);
|
||||
return returnDataList(result);
|
||||
}
|
||||
|
||||
|
|
@ -135,10 +146,10 @@ public class ExecutorController extends BaseController {
|
|||
/**
|
||||
* do action to process instance:pause, stop, repeat, recover from pause, recover from stop
|
||||
*
|
||||
* @param loginUser login user
|
||||
* @param projectName project name
|
||||
* @param loginUser login user
|
||||
* @param projectName project name
|
||||
* @param processInstanceId process instance id
|
||||
* @param executeType execute type
|
||||
* @param executeType execute type
|
||||
* @return execute result code
|
||||
*/
|
||||
@ApiOperation(value = "execute", notes = "EXECUTE_ACTION_TO_PROCESS_INSTANCE_NOTES")
|
||||
|
|
@ -163,7 +174,7 @@ public class ExecutorController extends BaseController {
|
|||
/**
|
||||
* check process definition and all of the son process definitions is on line.
|
||||
*
|
||||
* @param loginUser login user
|
||||
* @param loginUser login user
|
||||
* @param processDefinitionId process definition id
|
||||
* @return check result code
|
||||
*/
|
||||
|
|
@ -180,32 +191,4 @@ public class ExecutorController extends BaseController {
|
|||
Map<String, Object> result = execService.startCheckByProcessDefinedId(processDefinitionId);
|
||||
return returnDataList(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* query recipients and copyers by process definition ID
|
||||
*
|
||||
* @param loginUser login user
|
||||
* @param processDefinitionId process definition id
|
||||
* @param processInstanceId process instance id
|
||||
* @return receivers cc list
|
||||
*/
|
||||
@ApiIgnore
|
||||
@ApiOperation(value = "getReceiverCc", notes = "GET_RECEIVER_CC_NOTES")
|
||||
@ApiImplicitParams({
|
||||
@ApiImplicitParam(name = "processDefinitionId", value = "PROCESS_DEFINITION_ID", required = true, dataType = "Int", example = "100"),
|
||||
@ApiImplicitParam(name = "processInstanceId", value = "PROCESS_INSTANCE_ID", required = true, dataType = "Int", example = "100")
|
||||
|
||||
})
|
||||
@GetMapping(value = "/get-receiver-cc")
|
||||
@ResponseStatus(HttpStatus.OK)
|
||||
@ApiException(QUERY_RECIPIENTS_AND_COPYERS_BY_PROCESS_DEFINITION_ERROR)
|
||||
public Result getReceiverCc(@ApiIgnore @RequestAttribute(value = Constants.SESSION_USER) User loginUser,
|
||||
@RequestParam(value = "processDefinitionId", required = false) Integer processDefinitionId,
|
||||
@RequestParam(value = "processInstanceId", required = false) Integer processInstanceId) {
|
||||
logger.info("login user {}, get process definition receiver and cc", loginUser.getUserName());
|
||||
Map<String, Object> result = execService.getReceiverCc(processDefinitionId, processInstanceId);
|
||||
return returnDataList(result);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,8 +14,18 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.apache.dolphinscheduler.api.controller;
|
||||
|
||||
import static org.apache.dolphinscheduler.api.enums.Status.CREATE_SCHEDULE_ERROR;
|
||||
import static org.apache.dolphinscheduler.api.enums.Status.DELETE_SCHEDULE_CRON_BY_ID_ERROR;
|
||||
import static org.apache.dolphinscheduler.api.enums.Status.OFFLINE_SCHEDULE_ERROR;
|
||||
import static org.apache.dolphinscheduler.api.enums.Status.PREVIEW_SCHEDULE_ERROR;
|
||||
import static org.apache.dolphinscheduler.api.enums.Status.PUBLISH_SCHEDULE_ONLINE_ERROR;
|
||||
import static org.apache.dolphinscheduler.api.enums.Status.QUERY_SCHEDULE_LIST_ERROR;
|
||||
import static org.apache.dolphinscheduler.api.enums.Status.QUERY_SCHEDULE_LIST_PAGING_ERROR;
|
||||
import static org.apache.dolphinscheduler.api.enums.Status.UPDATE_SCHEDULE_ERROR;
|
||||
import static org.apache.dolphinscheduler.common.Constants.SESSION_USER;
|
||||
|
||||
import org.apache.dolphinscheduler.api.exceptions.ApiException;
|
||||
import org.apache.dolphinscheduler.api.service.SchedulerService;
|
||||
|
|
@ -25,21 +35,31 @@ import org.apache.dolphinscheduler.common.enums.Priority;
|
|||
import org.apache.dolphinscheduler.common.enums.ReleaseState;
|
||||
import org.apache.dolphinscheduler.common.enums.WarningType;
|
||||
import org.apache.dolphinscheduler.common.utils.ParameterUtils;
|
||||
import org.apache.dolphinscheduler.common.utils.StringUtils;
|
||||
import org.apache.dolphinscheduler.dao.entity.User;
|
||||
import io.swagger.annotations.*;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestAttribute;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiImplicitParam;
|
||||
import io.swagger.annotations.ApiImplicitParams;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import io.swagger.annotations.ApiParam;
|
||||
import springfox.documentation.annotations.ApiIgnore;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.apache.dolphinscheduler.api.enums.Status.*;
|
||||
import static org.apache.dolphinscheduler.common.Constants.SESSION_USER;
|
||||
|
||||
/**
|
||||
* schedule controller
|
||||
*/
|
||||
|
|
@ -61,17 +81,15 @@ public class SchedulerController extends BaseController {
|
|||
/**
|
||||
* create schedule
|
||||
*
|
||||
* @param loginUser login user
|
||||
* @param projectName project name
|
||||
* @param processDefinitionId process definition id
|
||||
* @param schedule scheduler
|
||||
* @param warningType warning type
|
||||
* @param warningGroupId warning group id
|
||||
* @param failureStrategy failure strategy
|
||||
* @param loginUser login user
|
||||
* @param projectName project name
|
||||
* @param processDefinitionId process definition id
|
||||
* @param schedule scheduler
|
||||
* @param warningType warning type
|
||||
* @param warningGroupId warning group id
|
||||
* @param failureStrategy failure strategy
|
||||
* @param processInstancePriority process instance priority
|
||||
* @param receivers receivers
|
||||
* @param receiversCc receivers cc
|
||||
* @param workerGroup worker group
|
||||
* @param workerGroup worker group
|
||||
* @return create result code
|
||||
*/
|
||||
@ApiOperation(value = "createSchedule", notes = "CREATE_SCHEDULE_NOTES")
|
||||
|
|
@ -81,8 +99,6 @@ public class SchedulerController extends BaseController {
|
|||
@ApiImplicitParam(name = "warningType", value = "WARNING_TYPE", type = "WarningType"),
|
||||
@ApiImplicitParam(name = "warningGroupId", value = "WARNING_GROUP_ID", dataType = "Int", example = "100"),
|
||||
@ApiImplicitParam(name = "failureStrategy", value = "FAILURE_STRATEGY", type = "FailureStrategy"),
|
||||
@ApiImplicitParam(name = "receivers", value = "RECEIVERS", type = "String"),
|
||||
@ApiImplicitParam(name = "receiversCc", value = "RECEIVERS_CC", type = "String"),
|
||||
@ApiImplicitParam(name = "workerGroupId", value = "WORKER_GROUP_ID", dataType = "Int", example = "100"),
|
||||
@ApiImplicitParam(name = "processInstancePriority", value = "PROCESS_INSTANCE_PRIORITY", type = "Priority"),
|
||||
})
|
||||
|
|
@ -96,16 +112,14 @@ public class SchedulerController extends BaseController {
|
|||
@RequestParam(value = "warningType", required = false, defaultValue = DEFAULT_WARNING_TYPE) WarningType warningType,
|
||||
@RequestParam(value = "warningGroupId", required = false, defaultValue = DEFAULT_NOTIFY_GROUP_ID) int warningGroupId,
|
||||
@RequestParam(value = "failureStrategy", required = false, defaultValue = DEFAULT_FAILURE_POLICY) FailureStrategy failureStrategy,
|
||||
@RequestParam(value = "receivers", required = false) String receivers,
|
||||
@RequestParam(value = "receiversCc", required = false) String receiversCc,
|
||||
@RequestParam(value = "workerGroup", required = false, defaultValue = "default") String workerGroup,
|
||||
@RequestParam(value = "processInstancePriority", required = false, defaultValue = DEFAULT_PROCESS_INSTANCE_PRIORITY) Priority processInstancePriority) throws IOException {
|
||||
logger.info("login user {}, project name: {}, process name: {}, create schedule: {}, warning type: {}, warning group id: {}," +
|
||||
"failure policy: {},receivers : {},receiversCc : {},processInstancePriority : {}, workGroupId:{}",
|
||||
loginUser.getUserName(), projectName, processDefinitionId, schedule, warningType, warningGroupId,
|
||||
failureStrategy, receivers, receiversCc, processInstancePriority, workerGroup);
|
||||
@RequestParam(value = "processInstancePriority", required = false, defaultValue = DEFAULT_PROCESS_INSTANCE_PRIORITY) Priority processInstancePriority) {
|
||||
logger.info("login user {},project name: {}, process name: {}, create schedule: {}, warning type: {}, warning group id: {},"
|
||||
+ "failure policy: {},processInstancePriority : {}, workGroupId:{}",
|
||||
StringUtils.replaceNRTtoUnderline(loginUser.getUserName()), StringUtils.replaceNRTtoUnderline(projectName), processDefinitionId, schedule, warningType, warningGroupId,
|
||||
failureStrategy, processInstancePriority, workerGroup);
|
||||
Map<String, Object> result = schedulerService.insertSchedule(loginUser, projectName, processDefinitionId, schedule,
|
||||
warningType, warningGroupId, failureStrategy, receivers, receiversCc, processInstancePriority, workerGroup);
|
||||
warningType, warningGroupId, failureStrategy, processInstancePriority, workerGroup);
|
||||
|
||||
return returnDataList(result);
|
||||
}
|
||||
|
|
@ -113,17 +127,15 @@ public class SchedulerController extends BaseController {
|
|||
/**
|
||||
* updateProcessInstance schedule
|
||||
*
|
||||
* @param loginUser login user
|
||||
* @param projectName project name
|
||||
* @param id scheduler id
|
||||
* @param schedule scheduler
|
||||
* @param warningType warning type
|
||||
* @param warningGroupId warning group id
|
||||
* @param failureStrategy failure strategy
|
||||
* @param receivers receivers
|
||||
* @param workerGroup worker group
|
||||
* @param loginUser login user
|
||||
* @param projectName project name
|
||||
* @param id scheduler id
|
||||
* @param schedule scheduler
|
||||
* @param warningType warning type
|
||||
* @param warningGroupId warning group id
|
||||
* @param failureStrategy failure strategy
|
||||
* @param workerGroup worker group
|
||||
* @param processInstancePriority process instance priority
|
||||
* @param receiversCc receivers cc
|
||||
* @return update result code
|
||||
*/
|
||||
@ApiOperation(value = "updateSchedule", notes = "UPDATE_SCHEDULE_NOTES")
|
||||
|
|
@ -133,8 +145,6 @@ public class SchedulerController extends BaseController {
|
|||
@ApiImplicitParam(name = "warningType", value = "WARNING_TYPE", type = "WarningType"),
|
||||
@ApiImplicitParam(name = "warningGroupId", value = "WARNING_GROUP_ID", dataType = "Int", example = "100"),
|
||||
@ApiImplicitParam(name = "failureStrategy", value = "FAILURE_STRATEGY", type = "FailureStrategy"),
|
||||
@ApiImplicitParam(name = "receivers", value = "RECEIVERS", type = "String"),
|
||||
@ApiImplicitParam(name = "receiversCc", value = "RECEIVERS_CC", type = "String"),
|
||||
@ApiImplicitParam(name = "workerGroupId", value = "WORKER_GROUP_ID", dataType = "Int", example = "100"),
|
||||
@ApiImplicitParam(name = "processInstancePriority", value = "PROCESS_INSTANCE_PRIORITY", type = "Priority"),
|
||||
})
|
||||
|
|
@ -147,26 +157,24 @@ public class SchedulerController extends BaseController {
|
|||
@RequestParam(value = "warningType", required = false, defaultValue = DEFAULT_WARNING_TYPE) WarningType warningType,
|
||||
@RequestParam(value = "warningGroupId", required = false) int warningGroupId,
|
||||
@RequestParam(value = "failureStrategy", required = false, defaultValue = "END") FailureStrategy failureStrategy,
|
||||
@RequestParam(value = "receivers", required = false) String receivers,
|
||||
@RequestParam(value = "receiversCc", required = false) String receiversCc,
|
||||
@RequestParam(value = "workerGroup", required = false, defaultValue = "default") String workerGroup,
|
||||
@RequestParam(value = "processInstancePriority", required = false) Priority processInstancePriority) throws IOException {
|
||||
logger.info("login user {}, project name: {},id: {}, updateProcessInstance schedule: {}, notify type: {}, notify mails: {}, " +
|
||||
"failure policy: {},receivers : {},receiversCc : {},processInstancePriority : {},workerGroupId:{}",
|
||||
loginUser.getUserName(), projectName, id, schedule, warningType, warningGroupId, failureStrategy,
|
||||
receivers, receiversCc, processInstancePriority, workerGroup);
|
||||
@RequestParam(value = "processInstancePriority", required = false) Priority processInstancePriority) {
|
||||
logger.info("login user {},project name: {},id: {}, updateProcessInstance schedule: {}, notify type: {}, notify mails: {}, "
|
||||
+ "failure policy: {},processInstancePriority : {},workerGroupId:{}",
|
||||
StringUtils.replaceNRTtoUnderline(loginUser.getUserName()), StringUtils.replaceNRTtoUnderline(projectName), id, schedule, warningType, warningGroupId, failureStrategy,
|
||||
processInstancePriority, workerGroup);
|
||||
|
||||
Map<String, Object> result = schedulerService.updateSchedule(loginUser, projectName, id, schedule,
|
||||
warningType, warningGroupId, failureStrategy, receivers, receiversCc, null, processInstancePriority, workerGroup);
|
||||
warningType, warningGroupId, failureStrategy, null, processInstancePriority, workerGroup);
|
||||
return returnDataList(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* publish schedule setScheduleState
|
||||
*
|
||||
* @param loginUser login user
|
||||
* @param loginUser login user
|
||||
* @param projectName project name
|
||||
* @param id scheduler id
|
||||
* @param id scheduler id
|
||||
* @return publish result code
|
||||
*/
|
||||
@ApiOperation(value = "online", notes = "ONLINE_SCHEDULE_NOTES")
|
||||
|
|
@ -187,9 +195,9 @@ public class SchedulerController extends BaseController {
|
|||
/**
|
||||
* offline schedule
|
||||
*
|
||||
* @param loginUser login user
|
||||
* @param loginUser login user
|
||||
* @param projectName project name
|
||||
* @param id schedule id
|
||||
* @param id schedule id
|
||||
* @return operation result code
|
||||
*/
|
||||
@ApiOperation(value = "offline", notes = "OFFLINE_SCHEDULE_NOTES")
|
||||
|
|
@ -211,12 +219,12 @@ public class SchedulerController extends BaseController {
|
|||
/**
|
||||
* query schedule list paging
|
||||
*
|
||||
* @param loginUser login user
|
||||
* @param projectName project name
|
||||
* @param loginUser login user
|
||||
* @param projectName project name
|
||||
* @param processDefinitionId process definition id
|
||||
* @param pageNo page number
|
||||
* @param pageSize page size
|
||||
* @param searchVal search value
|
||||
* @param pageNo page number
|
||||
* @param pageSize page size
|
||||
* @param searchVal search value
|
||||
* @return schedule list page
|
||||
*/
|
||||
@ApiOperation(value = "queryScheduleListPaging", notes = "QUERY_SCHEDULE_LIST_PAGING_NOTES")
|
||||
|
|
@ -245,9 +253,9 @@ public class SchedulerController extends BaseController {
|
|||
/**
|
||||
* delete schedule by id
|
||||
*
|
||||
* @param loginUser login user
|
||||
* @param loginUser login user
|
||||
* @param projectName project name
|
||||
* @param scheduleId scheule id
|
||||
* @param scheduleId scheule id
|
||||
* @return delete result code
|
||||
*/
|
||||
@ApiOperation(value = "deleteScheduleById", notes = "OFFLINE_SCHEDULE_NOTES")
|
||||
|
|
@ -270,7 +278,7 @@ public class SchedulerController extends BaseController {
|
|||
/**
|
||||
* query schedule list
|
||||
*
|
||||
* @param loginUser login user
|
||||
* @param loginUser login user
|
||||
* @param projectName project name
|
||||
* @return schedule list
|
||||
*/
|
||||
|
|
@ -288,9 +296,9 @@ public class SchedulerController extends BaseController {
|
|||
/**
|
||||
* preview schedule
|
||||
*
|
||||
* @param loginUser login user
|
||||
* @param loginUser login user
|
||||
* @param projectName project name
|
||||
* @param schedule schedule expression
|
||||
* @param schedule schedule expression
|
||||
* @return the next five fire time
|
||||
*/
|
||||
@ApiOperation(value = "previewSchedule", notes = "PREVIEW_SCHEDULE_NOTES")
|
||||
|
|
|
|||
|
|
@ -0,0 +1,93 @@
|
|||
/*
|
||||
* 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.api.controller;
|
||||
|
||||
import static org.apache.dolphinscheduler.api.enums.Status.QUERY_PLUGINS_ERROR;
|
||||
|
||||
import org.apache.dolphinscheduler.api.exceptions.ApiException;
|
||||
import org.apache.dolphinscheduler.api.service.UiPluginService;
|
||||
import org.apache.dolphinscheduler.api.utils.Result;
|
||||
import org.apache.dolphinscheduler.common.Constants;
|
||||
import org.apache.dolphinscheduler.common.enums.PluginType;
|
||||
import org.apache.dolphinscheduler.dao.entity.User;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestAttribute;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiImplicitParam;
|
||||
import io.swagger.annotations.ApiImplicitParams;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import springfox.documentation.annotations.ApiIgnore;
|
||||
|
||||
/**
|
||||
* UiPluginController
|
||||
* Some plugins (such as alert plugin) need to provide UI interfaces to users.
|
||||
* We use from-creat to dynamically generate UI interfaces. Related parameters are mainly provided by pluginParams.
|
||||
* From-create can generate dynamic ui based on this parameter.
|
||||
*/
|
||||
@Api(tags = "UI_PLUGINS", position = 1)
|
||||
@RestController
|
||||
@RequestMapping("ui-plugins")
|
||||
public class UiPluginController extends BaseController {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(UiPluginController.class);
|
||||
|
||||
@Autowired
|
||||
UiPluginService uiPluginService;
|
||||
|
||||
@ApiOperation(value = "queryUiPluginsByType", notes = "QUERY_UI_PLUGINS_BY_TYPE")
|
||||
@ApiImplicitParams({
|
||||
@ApiImplicitParam(name = "pluginType", value = "pluginType", required = true, dataType = "PluginType"),
|
||||
})
|
||||
@PostMapping(value = "/queryUiPluginsByType")
|
||||
@ResponseStatus(HttpStatus.CREATED)
|
||||
@ApiException(QUERY_PLUGINS_ERROR)
|
||||
public Result queryUiPluginsByType(@ApiIgnore @RequestAttribute(value = Constants.SESSION_USER) User loginUser,
|
||||
@RequestParam(value = "pluginType") PluginType pluginType) {
|
||||
|
||||
logger.info("query plugins by type , pluginType: {}", pluginType);
|
||||
Map<String, Object> result = uiPluginService.queryUiPluginsByType(pluginType);
|
||||
return returnDataList(result);
|
||||
}
|
||||
|
||||
@ApiOperation(value = "queryUiPluginDetailById", notes = "QUERY_UI_PLUGIN_DETAIL_BY_ID")
|
||||
@ApiImplicitParams({
|
||||
@ApiImplicitParam(name = "id", value = "id", required = true, dataType = "PluginType"),
|
||||
})
|
||||
@PostMapping(value = "/queryUiPluginDetailById")
|
||||
@ResponseStatus(HttpStatus.CREATED)
|
||||
@ApiException(QUERY_PLUGINS_ERROR)
|
||||
public Result queryUiPluginDetailById(@ApiIgnore @RequestAttribute(value = Constants.SESSION_USER) User loginUser,
|
||||
@RequestParam("pluginId") Integer pluginId) {
|
||||
|
||||
logger.info("query plugin detail by id , pluginId: {}", pluginId);
|
||||
Map<String, Object> result = uiPluginService.queryUiPluginDetailById(pluginId);
|
||||
return returnDataList(result);
|
||||
}
|
||||
}
|
||||
|
|
@ -276,13 +276,28 @@ public enum Status {
|
|||
QUEUE_COUNT_ERROR(90001, "queue count error", "查询队列数据错误"),
|
||||
|
||||
KERBEROS_STARTUP_STATE(100001, "get kerberos startup state error", "获取kerberos启动状态错误"),
|
||||
|
||||
//plugin
|
||||
PLUGIN_NOT_A_UI_COMPONENT(110001, "query plugin error, this plugin has no UI component", "查询插件错误,此插件无UI组件"),
|
||||
QUERY_PLUGINS_RESULT_IS_NULL(110002, "query plugins result is null", "查询插件为空"),
|
||||
QUERY_PLUGINS_ERROR(110003, "query plugins error", "查询插件错误"),
|
||||
QUERY_PLUGIN_DETAIL_RESULT_IS_NULL(110004, "query plugin detail result is null", "查询插件详情结果为空"),
|
||||
|
||||
UPDATE_ALERT_PLUGIN_INSTANCE_ERROR(110005, "update alert plugin instance error", "更新告警组和告警组插件实例错误"),
|
||||
DELETE_ALERT_PLUGIN_INSTANCE_ERROR(110006, "delete alert plugin instance error", "删除告警组和告警组插件实例错误"),
|
||||
GET_ALERT_PLUGIN_INSTANCE_ERROR(110007, "get alert plugin instance error", "获取告警组和告警组插件实例错误"),
|
||||
CREATE_ALERT_PLUGIN_INSTANCE_ERROR(110008, "create alert plugin instance error", "创建告警组和告警组插件实例错误"),
|
||||
QUERY_ALL_ALERT_PLUGIN_INSTANCE_ERROR(110009, "query all alert plugin instance error", "查询所有告警实例失败"),
|
||||
PLUGIN_INSTANCE_ALREADY_EXIT(110010,"plugin instance already exit","该告警插件实例已存在"),
|
||||
LIST_PAGING_ALERT_PLUGIN_INSTANCE_ERROR(110011,"query plugin instance page error","分页查询告警实例失败"),
|
||||
|
||||
;
|
||||
|
||||
private final int code;
|
||||
private final String enMsg;
|
||||
private final String zhMsg;
|
||||
|
||||
private Status(int code, String enMsg, String zhMsg) {
|
||||
Status(int code, String enMsg, String zhMsg) {
|
||||
this.code = code;
|
||||
this.enMsg = enMsg;
|
||||
this.zhMsg = zhMsg;
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue