hgaol
5 years ago
28 changed files with 1251 additions and 115 deletions
@ -0,0 +1,133 @@ |
|||||||
|
/* |
||||||
|
* 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.EmailManager; |
||||||
|
import org.apache.dolphinscheduler.alert.manager.EnterpriseWeChatManager; |
||||||
|
import org.apache.dolphinscheduler.alert.utils.Constants; |
||||||
|
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 org.slf4j.Logger; |
||||||
|
import org.slf4j.LoggerFactory; |
||||||
|
|
||||||
|
import java.util.*; |
||||||
|
|
||||||
|
/** |
||||||
|
* EmailAlertPlugin |
||||||
|
* |
||||||
|
* 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(); |
||||||
|
|
||||||
|
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; |
||||||
|
} |
||||||
|
|
||||||
|
@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> receviersList = (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(","); |
||||||
|
receviersList.addAll(Arrays.asList(splits)); |
||||||
|
} |
||||||
|
|
||||||
|
List<String> receviersCcList = new ArrayList<>(); |
||||||
|
// Custom Copier
|
||||||
|
String receiversCc = alert.getReceiversCc(); |
||||||
|
if (StringUtils.isNotEmpty(receiversCc)) { |
||||||
|
String[] splits = receiversCc.split(","); |
||||||
|
receviersCcList.addAll(Arrays.asList(splits)); |
||||||
|
} |
||||||
|
|
||||||
|
if (CollectionUtils.isEmpty(receviersList) && CollectionUtils.isEmpty(receviersCcList)) { |
||||||
|
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(receviersList, receviersCcList, 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); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} else { |
||||||
|
retMaps.put(Constants.MESSAGE, "alert send error."); |
||||||
|
logger.info("alert send error : {}", retMaps.get(Constants.MESSAGE)); |
||||||
|
} |
||||||
|
|
||||||
|
return retMaps; |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -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.alert.plugin; |
||||||
|
|
||||||
|
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 java.util.ArrayList; |
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
import static org.junit.Assert.*; |
||||||
|
|
||||||
|
public class EmailAlertPluginTest { |
||||||
|
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(EmailAlertPluginTest.class); |
||||||
|
|
||||||
|
private AlertPlugin plugin; |
||||||
|
|
||||||
|
@Before |
||||||
|
public void before() { |
||||||
|
plugin = new EmailAlertPlugin(); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void getId() { |
||||||
|
String id = plugin.getId(); |
||||||
|
assertEquals(Constants.PLUGIN_DEFAULT_EMAIL, id); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void getName() { |
||||||
|
PluginName pluginName = plugin.getName(); |
||||||
|
assertEquals(Constants.PLUGIN_DEFAULT_EMAIL_CH, pluginName.getChinese()); |
||||||
|
assertEquals(Constants.PLUGIN_DEFAULT_EMAIL_EN, pluginName.getEnglish()); |
||||||
|
} |
||||||
|
|
||||||
|
@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("bitace@163.com") |
||||||
|
.setReceiversCc("bitace@163.com") |
||||||
|
.setShowType(ShowType.TEXT.getDescp()) |
||||||
|
.setTitle("test title"); |
||||||
|
|
||||||
|
alertInfo.setAlertData(alertData); |
||||||
|
List<String> list = new ArrayList<String>(){{ add("bitace@163.com"); }}; |
||||||
|
alertInfo.addProp("receivers", list); |
||||||
|
plugin.process(alertInfo); |
||||||
|
} |
||||||
|
} |
@ -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.common.plugin; |
||||||
|
|
||||||
|
import org.apache.dolphinscheduler.common.Constants; |
||||||
|
import org.apache.dolphinscheduler.plugin.api.AlertPlugin; |
||||||
|
import org.apache.dolphinscheduler.plugin.spi.AlertPluginProvider; |
||||||
|
import org.slf4j.Logger; |
||||||
|
import org.slf4j.LoggerFactory; |
||||||
|
|
||||||
|
import java.io.File; |
||||||
|
import java.net.MalformedURLException; |
||||||
|
import java.net.URL; |
||||||
|
import java.util.Map; |
||||||
|
import java.util.ServiceLoader; |
||||||
|
import java.util.concurrent.ConcurrentHashMap; |
||||||
|
|
||||||
|
/** |
||||||
|
* FilePluginManager |
||||||
|
*/ |
||||||
|
public class FilePluginManager implements PluginManager { |
||||||
|
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(FilePluginManager.class); |
||||||
|
|
||||||
|
private Map<String, AlertPlugin> pluginMap = new ConcurrentHashMap<>(); |
||||||
|
|
||||||
|
private Map<String, ServiceLoader<AlertPluginProvider>> pluginLoaderMap = new ConcurrentHashMap<>(); |
||||||
|
|
||||||
|
private Map<String, PluginClassLoader> classLoaderMap = new ConcurrentHashMap<>(); |
||||||
|
|
||||||
|
public FilePluginManager(String dirPath, String[] whitePrefixes, String[] excludePrefixes) throws MalformedURLException { |
||||||
|
logger.info("start to load jar files in {}", dirPath); |
||||||
|
File[] files = new File(dirPath).listFiles(); |
||||||
|
if (files == null) { |
||||||
|
logger.error("not a valid path - {}", dirPath); |
||||||
|
System.exit(1); |
||||||
|
} |
||||||
|
for (File file : files) { |
||||||
|
if (file.isDirectory() && !file.getPath().endsWith(Constants.PLUGIN_JAR_SUFFIX)) { |
||||||
|
continue; |
||||||
|
} |
||||||
|
String pluginName = file.getName() |
||||||
|
.substring(0, file.getName().length() - Constants.PLUGIN_JAR_SUFFIX.length()); |
||||||
|
URL[] urls = new URL[]{ file.toURI().toURL() }; |
||||||
|
PluginClassLoader classLoader = |
||||||
|
new PluginClassLoader(urls, Thread.currentThread().getContextClassLoader(), whitePrefixes, excludePrefixes); |
||||||
|
classLoaderMap.put(pluginName, classLoader); |
||||||
|
|
||||||
|
ServiceLoader<AlertPluginProvider> loader = ServiceLoader.load(AlertPluginProvider.class, classLoader); |
||||||
|
pluginLoaderMap.put(pluginName, loader); |
||||||
|
|
||||||
|
loader.forEach(provider -> { |
||||||
|
AlertPlugin plugin = provider.createPlugin(); |
||||||
|
pluginMap.put(plugin.getId(), plugin); |
||||||
|
logger.info("loaded plugin - {}", plugin.getId()); |
||||||
|
}); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public AlertPlugin findOne(String name) { |
||||||
|
return pluginMap.get(name); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Map<String, AlertPlugin> findAll() { |
||||||
|
return pluginMap; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void addPlugin(AlertPlugin plugin) { |
||||||
|
pluginMap.put(plugin.getId(), plugin); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,134 @@ |
|||||||
|
package org.apache.dolphinscheduler.common.plugin; |
||||||
|
|
||||||
|
import org.slf4j.Logger; |
||||||
|
import org.slf4j.LoggerFactory; |
||||||
|
|
||||||
|
import java.io.IOException; |
||||||
|
import java.net.URL; |
||||||
|
import java.net.URLClassLoader; |
||||||
|
import java.util.Enumeration; |
||||||
|
import java.util.Iterator; |
||||||
|
import java.util.LinkedList; |
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
/** |
||||||
|
* Plugin Class Loader |
||||||
|
*/ |
||||||
|
public class PluginClassLoader extends URLClassLoader { |
||||||
|
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(PluginClassLoader.class); |
||||||
|
|
||||||
|
private static final String JAVA_PACKAGE_PREFIX = "java."; |
||||||
|
private static final String JAVAX_PACKAGE_PREFIX = "javax."; |
||||||
|
|
||||||
|
private final String[] whitePrefixes; |
||||||
|
|
||||||
|
private final String[] excludePrefixes; |
||||||
|
|
||||||
|
public PluginClassLoader(URL[] urls, ClassLoader parent, String[] whitePrefix, String[] excludePreifx) { |
||||||
|
super(urls, parent); |
||||||
|
this.whitePrefixes = whitePrefix; |
||||||
|
this.excludePrefixes = excludePreifx; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Class<?> loadClass(String name) throws ClassNotFoundException { |
||||||
|
logger.trace("Received request to load class '{}'", name); |
||||||
|
synchronized (getClassLoadingLock(name)) { |
||||||
|
if (name.startsWith(JAVA_PACKAGE_PREFIX) || name.startsWith(JAVAX_PACKAGE_PREFIX)) { |
||||||
|
return findSystemClass(name); |
||||||
|
} |
||||||
|
|
||||||
|
boolean isWhitePrefixes = fromWhitePrefix(name); |
||||||
|
boolean isExcludePrefixed = fromExcludePrefix(name); |
||||||
|
|
||||||
|
// if the class is part of the plugin engine use parent class loader
|
||||||
|
if (!isWhitePrefixes && isExcludePrefixed) { |
||||||
|
return getParent().loadClass(name); |
||||||
|
} |
||||||
|
|
||||||
|
// check whether it's already been loaded
|
||||||
|
Class<?> loadedClass = findLoadedClass(name); |
||||||
|
if (loadedClass != null) { |
||||||
|
logger.debug("Found loaded class '{}'", name); |
||||||
|
return loadedClass; |
||||||
|
} |
||||||
|
|
||||||
|
// nope, try to load locally
|
||||||
|
try { |
||||||
|
loadedClass = findClass(name); |
||||||
|
logger.debug("Found class '{}' in plugin classpath", name); |
||||||
|
return loadedClass; |
||||||
|
} catch (ClassNotFoundException e) { |
||||||
|
// try next step
|
||||||
|
} |
||||||
|
|
||||||
|
// use the standard ClassLoader (which follows normal parent delegation)
|
||||||
|
return super.loadClass(name); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private boolean fromWhitePrefix(String name) { |
||||||
|
for (String whitePrefix : this.whitePrefixes) { |
||||||
|
if (name.startsWith(whitePrefix)) { |
||||||
|
return true; |
||||||
|
} |
||||||
|
} |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
private boolean fromExcludePrefix(String name) { |
||||||
|
for (String excludePrefix : this.excludePrefixes) { |
||||||
|
if (name.startsWith(excludePrefix)) { |
||||||
|
return true; |
||||||
|
} |
||||||
|
} |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Enumeration<URL> getResources(String name) throws IOException { |
||||||
|
List<URL> allRes = new LinkedList<>(); |
||||||
|
|
||||||
|
Enumeration<URL> thisRes = findResources(name); |
||||||
|
if (thisRes != null) { |
||||||
|
while (thisRes.hasMoreElements()) { |
||||||
|
allRes.add(thisRes.nextElement()); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
Enumeration<URL> parentRes = super.findResources(name); |
||||||
|
if (parentRes != null) { |
||||||
|
while (parentRes.hasMoreElements()) { |
||||||
|
allRes.add(parentRes.nextElement()); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
return new Enumeration<URL>() { |
||||||
|
Iterator<URL> it = allRes.iterator(); |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean hasMoreElements() { |
||||||
|
return it.hasNext(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public URL nextElement() { |
||||||
|
return it.next(); |
||||||
|
} |
||||||
|
}; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public URL getResource(String name) { |
||||||
|
URL res = null; |
||||||
|
|
||||||
|
if (res == null) { |
||||||
|
res = findResource(name); |
||||||
|
} |
||||||
|
if (res == null) { |
||||||
|
res = super.getResource(name); |
||||||
|
} |
||||||
|
return res; |
||||||
|
} |
||||||
|
} |
@ -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.common.plugin; |
||||||
|
|
||||||
|
import org.apache.dolphinscheduler.plugin.api.AlertPlugin; |
||||||
|
|
||||||
|
import java.util.Map; |
||||||
|
|
||||||
|
/** |
||||||
|
* PluginManager |
||||||
|
*/ |
||||||
|
public interface PluginManager { |
||||||
|
|
||||||
|
AlertPlugin findOne(String name); |
||||||
|
|
||||||
|
Map<String, AlertPlugin> findAll(); |
||||||
|
|
||||||
|
void addPlugin(AlertPlugin plugin); |
||||||
|
} |
@ -0,0 +1,35 @@ |
|||||||
|
<?xml version="1.0"?> |
||||||
|
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" |
||||||
|
xmlns="http://maven.apache.org/POM/4.0.0" |
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> |
||||||
|
<modelVersion>4.0.0</modelVersion> |
||||||
|
<parent> |
||||||
|
<groupId>org.apache.dolphinscheduler</groupId> |
||||||
|
<artifactId>dolphinscheduler</artifactId> |
||||||
|
<version>1.2.1-SNAPSHOT</version> |
||||||
|
</parent> |
||||||
|
<artifactId>dolphinscheduler-plugin-api</artifactId> |
||||||
|
<name>${project.artifactId}</name> |
||||||
|
<packaging>jar</packaging> |
||||||
|
|
||||||
|
<properties> |
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> |
||||||
|
</properties> |
||||||
|
|
||||||
|
<dependencies> |
||||||
|
<dependency> |
||||||
|
<groupId>org.slf4j</groupId> |
||||||
|
<artifactId>slf4j-api</artifactId> |
||||||
|
</dependency> |
||||||
|
<dependency> |
||||||
|
<groupId>junit</groupId> |
||||||
|
<artifactId>junit</artifactId> |
||||||
|
<scope>test</scope> |
||||||
|
</dependency> |
||||||
|
<dependency> |
||||||
|
<groupId>commons-io</groupId> |
||||||
|
<artifactId>commons-io</artifactId> |
||||||
|
</dependency> |
||||||
|
</dependencies> |
||||||
|
|
||||||
|
</project> |
@ -0,0 +1,45 @@ |
|||||||
|
/* |
||||||
|
* 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.api; |
||||||
|
|
||||||
|
import org.apache.dolphinscheduler.plugin.model.AlertInfo; |
||||||
|
import org.apache.dolphinscheduler.plugin.model.PluginName; |
||||||
|
|
||||||
|
import java.util.Map; |
||||||
|
|
||||||
|
/** |
||||||
|
* Plugin |
||||||
|
*/ |
||||||
|
public interface AlertPlugin { |
||||||
|
|
||||||
|
/** |
||||||
|
* Get alert plugin id |
||||||
|
* |
||||||
|
* @return alert plugin id, which should be unique |
||||||
|
*/ |
||||||
|
String getId(); |
||||||
|
|
||||||
|
/** |
||||||
|
* Get alert plugin name, which will show in front end portal |
||||||
|
* |
||||||
|
* @return plugin name |
||||||
|
*/ |
||||||
|
PluginName getName(); |
||||||
|
|
||||||
|
Map<String, Object> process(AlertInfo info); |
||||||
|
|
||||||
|
} |
@ -0,0 +1,125 @@ |
|||||||
|
package org.apache.dolphinscheduler.plugin.model; |
||||||
|
|
||||||
|
/** |
||||||
|
* AlertData |
||||||
|
*/ |
||||||
|
public class AlertData { |
||||||
|
|
||||||
|
/** |
||||||
|
* alert primary key |
||||||
|
*/ |
||||||
|
private int id; |
||||||
|
/** |
||||||
|
* title |
||||||
|
*/ |
||||||
|
private String title; |
||||||
|
/** |
||||||
|
* content |
||||||
|
*/ |
||||||
|
private String content; |
||||||
|
/** |
||||||
|
* log |
||||||
|
*/ |
||||||
|
private String log; |
||||||
|
/** |
||||||
|
* alertgroup_id |
||||||
|
*/ |
||||||
|
private int alertGroupId; |
||||||
|
/** |
||||||
|
* receivers |
||||||
|
*/ |
||||||
|
private String receivers; |
||||||
|
/** |
||||||
|
* show_type |
||||||
|
*/ |
||||||
|
private String showType; |
||||||
|
/** |
||||||
|
* receivers_cc |
||||||
|
*/ |
||||||
|
private String receiversCc; |
||||||
|
|
||||||
|
public AlertData() { |
||||||
|
} |
||||||
|
|
||||||
|
public int getId() { |
||||||
|
return id; |
||||||
|
} |
||||||
|
|
||||||
|
public AlertData setId(int id) { |
||||||
|
this.id = id; |
||||||
|
return this; |
||||||
|
} |
||||||
|
|
||||||
|
public String getTitle() { |
||||||
|
return title; |
||||||
|
} |
||||||
|
|
||||||
|
public AlertData setTitle(String title) { |
||||||
|
this.title = title; |
||||||
|
return this; |
||||||
|
} |
||||||
|
|
||||||
|
public String getContent() { |
||||||
|
return content; |
||||||
|
} |
||||||
|
|
||||||
|
public AlertData setContent(String content) { |
||||||
|
this.content = content; |
||||||
|
return this; |
||||||
|
} |
||||||
|
|
||||||
|
public String getLog() { |
||||||
|
return log; |
||||||
|
} |
||||||
|
|
||||||
|
public AlertData setLog(String log) { |
||||||
|
this.log = log; |
||||||
|
return this; |
||||||
|
} |
||||||
|
|
||||||
|
public int getAlertGroupId() { |
||||||
|
return alertGroupId; |
||||||
|
} |
||||||
|
|
||||||
|
public AlertData setAlertGroupId(int alertGroupId) { |
||||||
|
this.alertGroupId = alertGroupId; |
||||||
|
return this; |
||||||
|
} |
||||||
|
|
||||||
|
public String getReceivers() { |
||||||
|
return receivers; |
||||||
|
} |
||||||
|
|
||||||
|
public AlertData setReceivers(String receivers) { |
||||||
|
this.receivers = receivers; |
||||||
|
return this; |
||||||
|
} |
||||||
|
|
||||||
|
public String getReceiversCc() { |
||||||
|
return receiversCc; |
||||||
|
} |
||||||
|
|
||||||
|
public AlertData setReceiversCc(String receiversCc) { |
||||||
|
this.receiversCc = receiversCc; |
||||||
|
return this; |
||||||
|
} |
||||||
|
|
||||||
|
public String getShowType() { |
||||||
|
return showType; |
||||||
|
} |
||||||
|
|
||||||
|
public AlertData setShowType(String showType) { |
||||||
|
this.showType = showType; |
||||||
|
return this; |
||||||
|
} |
||||||
|
|
||||||
|
public AlertData(int id, String title, String content, String log, int alertGroupId, String receivers, String receiversCc) { |
||||||
|
this.id = id; |
||||||
|
this.title = title; |
||||||
|
this.content = content; |
||||||
|
this.log = log; |
||||||
|
this.alertGroupId = alertGroupId; |
||||||
|
this.receivers = receivers; |
||||||
|
this.receiversCc = receiversCc; |
||||||
|
} |
||||||
|
} |
@ -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.plugin.model; |
||||||
|
|
||||||
|
import java.util.HashMap; |
||||||
|
import java.util.Map; |
||||||
|
|
||||||
|
/** |
||||||
|
* AlertInfo |
||||||
|
*/ |
||||||
|
public class AlertInfo { |
||||||
|
|
||||||
|
private Map<String, Object> alertProps; |
||||||
|
|
||||||
|
private AlertData alertData; |
||||||
|
|
||||||
|
public AlertInfo() { |
||||||
|
this.alertProps = new HashMap<>(); |
||||||
|
} |
||||||
|
|
||||||
|
public Map<String, Object> getAlertProps() { |
||||||
|
return alertProps; |
||||||
|
} |
||||||
|
|
||||||
|
public AlertInfo setAlertProps(Map<String, Object> alertProps) { |
||||||
|
this.alertProps = alertProps; |
||||||
|
return this; |
||||||
|
} |
||||||
|
|
||||||
|
public AlertInfo addProp(String key, Object value) { |
||||||
|
this.alertProps.put(key, value); |
||||||
|
return this; |
||||||
|
} |
||||||
|
|
||||||
|
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; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,45 @@ |
|||||||
|
/* |
||||||
|
* 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.model; |
||||||
|
|
||||||
|
/** |
||||||
|
* PluginName |
||||||
|
*/ |
||||||
|
public class PluginName { |
||||||
|
|
||||||
|
private String chinese; |
||||||
|
|
||||||
|
private String english; |
||||||
|
|
||||||
|
public String getChinese() { |
||||||
|
return chinese; |
||||||
|
} |
||||||
|
|
||||||
|
public PluginName setChinese(String chinese) { |
||||||
|
this.chinese = chinese; |
||||||
|
return this; |
||||||
|
} |
||||||
|
|
||||||
|
public String getEnglish() { |
||||||
|
return english; |
||||||
|
} |
||||||
|
|
||||||
|
public PluginName setEnglish(String english) { |
||||||
|
this.english = english; |
||||||
|
return this; |
||||||
|
} |
||||||
|
} |
@ -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.spi; |
||||||
|
|
||||||
|
import org.apache.dolphinscheduler.plugin.api.AlertPlugin; |
||||||
|
|
||||||
|
/** |
||||||
|
* PluginProvider |
||||||
|
*/ |
||||||
|
public interface AlertPluginProvider { |
||||||
|
|
||||||
|
/** |
||||||
|
* create an alert plugin |
||||||
|
* |
||||||
|
* @return an alert plugin |
||||||
|
*/ |
||||||
|
AlertPlugin createPlugin(); |
||||||
|
|
||||||
|
} |
@ -0,0 +1,232 @@ |
|||||||
|
/* |
||||||
|
* 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.utils; |
||||||
|
|
||||||
|
import org.apache.commons.io.IOUtils; |
||||||
|
import org.slf4j.Logger; |
||||||
|
import org.slf4j.LoggerFactory; |
||||||
|
|
||||||
|
import java.io.IOException; |
||||||
|
import java.io.InputStream; |
||||||
|
import java.util.HashMap; |
||||||
|
import java.util.Map; |
||||||
|
import java.util.Properties; |
||||||
|
|
||||||
|
/** |
||||||
|
* property utils |
||||||
|
* single instance |
||||||
|
*/ |
||||||
|
public class PropertyUtils { |
||||||
|
|
||||||
|
/** |
||||||
|
* logger |
||||||
|
*/ |
||||||
|
private static final Logger logger = LoggerFactory.getLogger(PropertyUtils.class); |
||||||
|
|
||||||
|
private static final Properties properties = new Properties(); |
||||||
|
|
||||||
|
private PropertyUtils() { |
||||||
|
throw new IllegalStateException("PropertyUtils class"); |
||||||
|
} |
||||||
|
|
||||||
|
static { |
||||||
|
String[] propertyFiles = new String[]{"/plugin.properties"}; |
||||||
|
for (String fileName : propertyFiles) { |
||||||
|
InputStream fis = null; |
||||||
|
try { |
||||||
|
fis = PropertyUtils.class.getResourceAsStream(fileName); |
||||||
|
properties.load(fis); |
||||||
|
|
||||||
|
} catch (IOException e) { |
||||||
|
logger.error(e.getMessage(), e); |
||||||
|
if (fis != null) { |
||||||
|
IOUtils.closeQuietly(fis); |
||||||
|
} |
||||||
|
System.exit(1); |
||||||
|
} finally { |
||||||
|
IOUtils.closeQuietly(fis); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* get property value |
||||||
|
* |
||||||
|
* @param key property name |
||||||
|
* @return property value |
||||||
|
*/ |
||||||
|
public static String getString(String key) { |
||||||
|
if (key == null) { |
||||||
|
return null; |
||||||
|
} |
||||||
|
return properties.getProperty(key.trim()); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* get property value |
||||||
|
* |
||||||
|
* @param key property name |
||||||
|
* @param defaultVal default value |
||||||
|
* @return property value |
||||||
|
*/ |
||||||
|
public static String getString(String key, String defaultVal) { |
||||||
|
String val = properties.getProperty(key.trim()); |
||||||
|
return val == null ? defaultVal : val; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* get property value |
||||||
|
* |
||||||
|
* @param key property name |
||||||
|
* @return get property int value , if key == null, then return -1 |
||||||
|
*/ |
||||||
|
public static int getInt(String key) { |
||||||
|
return getInt(key, -1); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* |
||||||
|
* @param key key |
||||||
|
* @param defaultValue default value |
||||||
|
* @return property value |
||||||
|
*/ |
||||||
|
public static int getInt(String key, int defaultValue) { |
||||||
|
String value = getString(key); |
||||||
|
if (value == null) { |
||||||
|
return defaultValue; |
||||||
|
} |
||||||
|
|
||||||
|
try { |
||||||
|
return Integer.parseInt(value); |
||||||
|
} catch (NumberFormatException e) { |
||||||
|
logger.info(e.getMessage(),e); |
||||||
|
} |
||||||
|
return defaultValue; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* get property value |
||||||
|
* |
||||||
|
* @param key property name |
||||||
|
* @return property value |
||||||
|
*/ |
||||||
|
public static boolean getBoolean(String key) { |
||||||
|
String value = properties.getProperty(key.trim()); |
||||||
|
if(null != value){ |
||||||
|
return Boolean.parseBoolean(value); |
||||||
|
} |
||||||
|
|
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* get property value |
||||||
|
* |
||||||
|
* @param key property name |
||||||
|
* @param defaultValue default value |
||||||
|
* @return property value |
||||||
|
*/ |
||||||
|
public static Boolean getBoolean(String key, boolean defaultValue) { |
||||||
|
String value = properties.getProperty(key.trim()); |
||||||
|
if(null != value){ |
||||||
|
return Boolean.parseBoolean(value); |
||||||
|
} |
||||||
|
|
||||||
|
return defaultValue; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* get property long value |
||||||
|
* @param key key |
||||||
|
* @param defaultVal default value |
||||||
|
* @return property value |
||||||
|
*/ |
||||||
|
public static long getLong(String key, long defaultVal) { |
||||||
|
String val = getString(key); |
||||||
|
return val == null ? defaultVal : Long.parseLong(val); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* |
||||||
|
* @param key key |
||||||
|
* @return property value |
||||||
|
*/ |
||||||
|
public static long getLong(String key) { |
||||||
|
return getLong(key,-1); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* |
||||||
|
* @param key key |
||||||
|
* @param defaultVal default value |
||||||
|
* @return property value |
||||||
|
*/ |
||||||
|
public static double getDouble(String key, double defaultVal) { |
||||||
|
String val = getString(key); |
||||||
|
return val == null ? defaultVal : Double.parseDouble(val); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* get array |
||||||
|
* @param key property name |
||||||
|
* @param splitStr separator |
||||||
|
* @return property value through array |
||||||
|
*/ |
||||||
|
public static String[] getArray(String key, String splitStr) { |
||||||
|
String value = getString(key); |
||||||
|
if (value == null) { |
||||||
|
return new String[0]; |
||||||
|
} |
||||||
|
try { |
||||||
|
String[] propertyArray = value.split(splitStr); |
||||||
|
return propertyArray; |
||||||
|
} catch (NumberFormatException e) { |
||||||
|
logger.info(e.getMessage(),e); |
||||||
|
} |
||||||
|
return new String[0]; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* |
||||||
|
* @param key key |
||||||
|
* @param type type |
||||||
|
* @param defaultValue default value |
||||||
|
* @param <T> T |
||||||
|
* @return get enum value |
||||||
|
*/ |
||||||
|
public <T extends Enum<T>> T getEnum(String key, Class<T> type, |
||||||
|
T defaultValue) { |
||||||
|
String val = getString(key); |
||||||
|
return val == null ? defaultValue : Enum.valueOf(type, val); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* get all properties with specified prefix, like: fs. |
||||||
|
* @param prefix prefix to search |
||||||
|
* @return all properties with specified prefix |
||||||
|
*/ |
||||||
|
public static Map<String, String> getPrefixedProperties(String prefix) { |
||||||
|
Map<String, String> matchedProperties = new HashMap<>(); |
||||||
|
for (String propName : properties.stringPropertyNames()) { |
||||||
|
if (propName.startsWith(prefix)) { |
||||||
|
matchedProperties.put(propName, properties.getProperty(propName)); |
||||||
|
} |
||||||
|
} |
||||||
|
return matchedProperties; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,67 @@ |
|||||||
|
package org.apache.dolphinscheduler.plugin.utils; |
||||||
|
|
||||||
|
import org.junit.Test; |
||||||
|
import org.slf4j.Logger; |
||||||
|
import org.slf4j.LoggerFactory; |
||||||
|
|
||||||
|
import static org.junit.Assert.*; |
||||||
|
|
||||||
|
public class PropertyUtilsTest { |
||||||
|
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(PropertyUtilsTest.class); |
||||||
|
|
||||||
|
/** |
||||||
|
* Test getString |
||||||
|
*/ |
||||||
|
@Test |
||||||
|
public void testGetString() { |
||||||
|
|
||||||
|
String result = PropertyUtils.getString("test.string"); |
||||||
|
logger.info(result); |
||||||
|
assertEquals("teststring", result); |
||||||
|
|
||||||
|
//If key is null, then return null
|
||||||
|
result = PropertyUtils.getString(null); |
||||||
|
assertNull(result); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Test getBoolean |
||||||
|
*/ |
||||||
|
@Test |
||||||
|
public void testGetBoolean() { |
||||||
|
|
||||||
|
//Expected true
|
||||||
|
Boolean result = PropertyUtils.getBoolean("test.true"); |
||||||
|
assertTrue(result); |
||||||
|
|
||||||
|
//Expected false
|
||||||
|
result = PropertyUtils.getBoolean("test.false"); |
||||||
|
assertFalse(result); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Test getLong |
||||||
|
*/ |
||||||
|
@Test |
||||||
|
public void testGetLong() { |
||||||
|
long result = PropertyUtils.getLong("test.long"); |
||||||
|
assertSame(result, 100L); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Test getDouble |
||||||
|
*/ |
||||||
|
@Test |
||||||
|
public void testGetDouble() { |
||||||
|
|
||||||
|
//If key is undefine in alert.properties, and there is a defaultval, then return defaultval
|
||||||
|
double result = PropertyUtils.getDouble("abc", 5.0); |
||||||
|
assertEquals(result, 5.0, 0); |
||||||
|
|
||||||
|
result = PropertyUtils.getDouble("cba", 5.0); |
||||||
|
assertEquals(3.1, result, 0.01); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,5 @@ |
|||||||
|
test.string=teststring |
||||||
|
test.false=false |
||||||
|
test.true=true |
||||||
|
cba=3.1 |
||||||
|
test.long=100 |
Loading…
Reference in new issue