Browse Source

[DSIP-62][Http Alert Plugin] Refactor http alert plugin (#16484)

* add dsip_62

* fix sonar

* fix spotless
dev
xiangzihao 3 months ago committed by GitHub
parent
commit
66548a2ef2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 21
      docs/docs/en/guide/alert/http.md
  2. 39
      docs/docs/zh/guide/alert/http.md
  3. BIN
      docs/img/alert/http-alert-example.png
  4. BIN
      docs/img/alert/http-get-example.png
  5. BIN
      docs/img/alert/http-post-example.png
  6. 12
      dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-http/pom.xml
  7. 42
      dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-http/src/main/java/org/apache/dolphinscheduler/plugin/alert/http/HttpAlertChannelFactory.java
  8. 11
      dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-http/src/main/java/org/apache/dolphinscheduler/plugin/alert/http/HttpAlertConstants.java
  9. 22
      dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-http/src/main/java/org/apache/dolphinscheduler/plugin/alert/http/HttpRequestMethod.java
  10. 246
      dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-http/src/main/java/org/apache/dolphinscheduler/plugin/alert/http/HttpSender.java
  11. 134
      dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-http/src/test/java/org/apache/dolphinscheduler/plugin/alert/http/HttpSenderTest.java
  12. 6
      dolphinscheduler-alert/dolphinscheduler-alert-server/src/main/java/org/apache/dolphinscheduler/alert/plugin/AlertPluginManager.java
  13. 4
      dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/interceptor/LocaleChangeInterceptor.java
  14. 7
      dolphinscheduler-spi/src/main/java/org/apache/dolphinscheduler/spi/params/base/DataType.java
  15. 29
      dolphinscheduler-spi/src/main/java/org/apache/dolphinscheduler/spi/params/base/Validate.java
  16. 2
      dolphinscheduler-ui/src/locales/en_US/security.ts
  17. 2
      dolphinscheduler-ui/src/locales/zh_CN/security.ts
  18. 1
      dolphinscheduler-ui/src/views/security/alarm-instance-manage/detail.tsx

21
docs/docs/en/guide/alert/http.md

@ -7,25 +7,16 @@ If you need to use `Http script` for alerting, create an alert instance in the a
| **Parameter** | **Description** |
|---------------|-----------------------------------------------------------------------------------------------------|
| URL | The `Http` request URL needs to contain protocol, host, path and parameters if the method is `GET`. |
| Request Type | Select the request type from `POST` or `GET`. |
| Headers | The headers of the `Http` request in JSON format. |
| Body | The request body of the `Http` request in JSON format, when using `POST` method to alert. |
| Content Field | The field name to place the alert information. |
| Request Type | Select the request type from `POST` or `GET` or `PUT`. |
| Headers | The headers of the `Http` request in JSON format. Not including content-type. |
| Body | The request body of the `Http` request in JSON format, when using `POST` or `PUT` method to alert. |
| Content Type | The content-type of header. |
## Send Type
Using `POST` and `GET` method to send `Http` request in the `Request Type`.
> Alarm message supports variables `$msg`, which can be used in `URL`, `Headers`, and `Body`.
### GET HTTP
Send alert information by `Http` GET method.
The following shows the `GET` configuration example:
![enterprise-wechat-app-msg-config](../../../../img/alert/http-get-example.png)
### POST HTTP
Send alert information inside `Http` body by `Http` POST method.
The following shows the `POST` configuration example:
![enterprise-wechat-app-msg-config](../../../../img/alert/http-post-example.png)
![http-alert-msg-config](../../../../img/alert/http-alert-example.png)

39
docs/docs/zh/guide/alert/http.md

@ -4,40 +4,19 @@
## 参数配置
* URL
| **参数** | **描述** |
|--------------|------------------------------------------------|
| URL | 访问的`Http`连接URL,需要包含协议、Host、路径,如果是GET方法可以添加参数 |
| 请求方式 | 当前支持`GET`和`POST`以及`PUT`三种请求方式 |
| 请求头(Headers) | `Http`请求的完整请求头,以JSON为格式(注意不包含Content-Type),非必填 |
| 请求体(Body) | Http`请求的完整请求体,以JSON为格式,非必填 |
| Content-Type | 请求体的`Content-Type`,默认为`application/json` |
> 访问的`Http`连接URL,需要包含协议、Host、路径,如果是GET方法可以添加参数
* 请求方式
> 选择该请求为POST或GET方法
* 请求头
> `Http`请求的完整请求头,以JSON为格式
* 请求体
> `Http`请求的完整请求体,以JSON为格式,GET方法不需要写该参数
* 内容字段
> 放置本次告警告警信息的字段名称
## 发送类型
其中`Request Type`分别对应使用`POST`方法和`GET`方法进行`Http`告警。
> 告警消息,支持变量`$msg`,可在`URL`,`请求头`,`请求体`中使用,非必填。
### GET Http告警
GET `Http`告警指将告警结果作为参数通过`Http` GET方法进行请求。
下图是GET告警配置的示例:
![enterprise-wechat-app-msg-config](../../../../img/alert/http-get-example.png)
### POST Http告警
POST `Http`告警指将告警结果作为`BODY`参数通过`Http`POST方法进行请求。
下图是POST告警配置的示例:
![enterprise-wechat-app-msg-config](../../../../img/alert/http-post-example.png)
![http-alert-msg-config](../../../../img/alert/http-alert-example.png)

BIN
docs/img/alert/http-alert-example.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 130 KiB

BIN
docs/img/alert/http-get-example.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

BIN
docs/img/alert/http-post-example.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

12
dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-http/pom.xml

@ -41,5 +41,17 @@
<artifactId>jackson-databind</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>mockwebserver</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
</project>

42
dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-http/src/main/java/org/apache/dolphinscheduler/plugin/alert/http/HttpAlertChannelFactory.java

@ -20,11 +20,14 @@ package org.apache.dolphinscheduler.plugin.alert.http;
import org.apache.dolphinscheduler.alert.api.AlertChannel;
import org.apache.dolphinscheduler.alert.api.AlertChannelFactory;
import org.apache.dolphinscheduler.alert.api.AlertInputTips;
import org.apache.dolphinscheduler.common.model.OkHttpRequestHeaderContentType;
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.params.input.InputParam;
import org.apache.dolphinscheduler.spi.params.input.number.InputNumberParam;
import org.apache.dolphinscheduler.spi.params.radio.RadioParam;
import java.util.Arrays;
import java.util.List;
@ -52,35 +55,42 @@ public final class HttpAlertChannelFactory implements AlertChannelFactory {
InputParam headerParams =
InputParam.newBuilder(HttpAlertConstants.NAME_HEADER_PARAMS, HttpAlertConstants.HEADER_PARAMS)
.setPlaceholder(AlertInputTips.HEADER.getMsg())
.addValidate(Validate.newBuilder()
.setRequired(true)
.build())
.build();
InputParam bodyParams =
InputParam.newBuilder(HttpAlertConstants.NAME_BODY_PARAMS, HttpAlertConstants.BODY_PARAMS)
.setPlaceholder(AlertInputTips.JSON_BODY.getMsg())
.addValidate(Validate.newBuilder()
.setRequired(false)
.build())
.build();
InputParam contentField =
InputParam.newBuilder(HttpAlertConstants.NAME_CONTENT_FIELD, HttpAlertConstants.CONTENT_FIELD)
.setPlaceholder(AlertInputTips.FIELD_NAME.getMsg())
RadioParam contentType =
RadioParam.newBuilder(HttpAlertConstants.NAME_CONTENT_TYPE, HttpAlertConstants.CONTENT_TYPE)
.addParamsOptions(new ParamsOptions(OkHttpRequestHeaderContentType.APPLICATION_JSON.getValue(),
OkHttpRequestHeaderContentType.APPLICATION_JSON.getValue(), false))
.addParamsOptions(
new ParamsOptions(OkHttpRequestHeaderContentType.APPLICATION_FORM_URLENCODED.getValue(),
OkHttpRequestHeaderContentType.APPLICATION_FORM_URLENCODED.getValue(), false))
.setValue(OkHttpRequestHeaderContentType.APPLICATION_JSON.getValue())
.addValidate(Validate.newBuilder()
.setRequired(true)
.build())
.build();
InputParam requestType =
InputParam.newBuilder(HttpAlertConstants.NAME_REQUEST_TYPE, HttpAlertConstants.REQUEST_TYPE)
.setPlaceholder(AlertInputTips.HTTP_METHOD.getMsg())
InputParam bodyParams =
InputParam.newBuilder(HttpAlertConstants.NAME_BODY_PARAMS, HttpAlertConstants.BODY_PARAMS)
.setPlaceholder(AlertInputTips.JSON_BODY.getMsg())
.addValidate(Validate.newBuilder()
.setRequired(true)
.setRequired(false)
.build())
.build();
RadioParam requestType = RadioParam
.newBuilder(HttpAlertConstants.NAME_REQUEST_TYPE, HttpAlertConstants.REQUEST_TYPE)
.addParamsOptions(new ParamsOptions(HttpRequestMethod.GET.name(), HttpRequestMethod.GET.name(), false))
.addParamsOptions(
new ParamsOptions(HttpRequestMethod.POST.name(), HttpRequestMethod.POST.name(), false))
.addParamsOptions(new ParamsOptions(HttpRequestMethod.PUT.name(), HttpRequestMethod.PUT.name(), false))
.setValue(HttpRequestMethod.GET.name())
.addValidate(Validate.newBuilder().setRequired(true).build())
.build();
InputNumberParam timeout =
InputNumberParam.newBuilder(HttpAlertConstants.NAME_TIMEOUT, HttpAlertConstants.TIMEOUT)
.setValue(HttpAlertConstants.DEFAULT_TIMEOUT)
@ -90,7 +100,7 @@ public final class HttpAlertChannelFactory implements AlertChannelFactory {
.build())
.build();
return Arrays.asList(url, requestType, headerParams, bodyParams, contentField, timeout);
return Arrays.asList(url, requestType, headerParams, bodyParams, contentType, timeout);
}
@Override

11
dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-http/src/main/java/org/apache/dolphinscheduler/plugin/alert/http/HttpAlertConstants.java

@ -17,6 +17,9 @@
package org.apache.dolphinscheduler.plugin.alert.http;
import lombok.experimental.UtilityClass;
@UtilityClass
public final class HttpAlertConstants {
public static final String URL = "$t('url')";
@ -27,6 +30,10 @@ public final class HttpAlertConstants {
public static final String NAME_HEADER_PARAMS = "headerParams";
public static final String CONTENT_TYPE = "$t('contentType')";
public static final String NAME_CONTENT_TYPE = "contentType";
public static final String BODY_PARAMS = "$t('bodyParams')";
public static final String NAME_BODY_PARAMS = "bodyParams";
@ -45,7 +52,5 @@ public final class HttpAlertConstants {
public static final int DEFAULT_TIMEOUT = 120;
private HttpAlertConstants() {
throw new UnsupportedOperationException("This is a utility class and cannot be instantiated");
}
public static final String MSG_PARAMS = "${msg}";
}

22
dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-http/src/main/java/org/apache/dolphinscheduler/plugin/alert/http/HttpRequestMethod.java

@ -0,0 +1,22 @@
/*
* 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 enum HttpRequestMethod {
GET, POST, PUT
}

246
dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-http/src/main/java/org/apache/dolphinscheduler/plugin/alert/http/HttpSender.java

@ -18,146 +18,172 @@
package org.apache.dolphinscheduler.plugin.alert.http;
import org.apache.dolphinscheduler.alert.api.AlertResult;
import org.apache.dolphinscheduler.alert.api.HttpServiceRetryStrategy;
import org.apache.dolphinscheduler.common.model.OkHttpRequestHeaderContentType;
import org.apache.dolphinscheduler.common.model.OkHttpRequestHeaders;
import org.apache.dolphinscheduler.common.model.OkHttpResponse;
import org.apache.dolphinscheduler.common.utils.JSONUtils;
import org.apache.dolphinscheduler.common.utils.OkHttpUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.client.config.RequestConfig;
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.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.apache.http.HttpStatus;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import com.fasterxml.jackson.databind.node.ObjectNode;
@Slf4j
public final class HttpSender {
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 final String headerParams;
private final String bodyParams;
private final String contentField;
private final String requestType;
private final int timeout;
private Map<String, String> headerParams;
private OkHttpRequestHeaderContentType contentType;
private Map<String, String> bodyParams;
private HttpRequestMethod requestType;
private int timeout;
private String url;
private HttpRequestBase httpRequest;
public HttpSender(Map<String, String> paramsMap) {
paramsValidator(paramsMap);
}
private void paramsValidator(Map<String, String> paramsMap) {
url = paramsMap.get(HttpAlertConstants.NAME_URL);
headerParams = paramsMap.get(HttpAlertConstants.NAME_HEADER_PARAMS);
bodyParams = paramsMap.get(HttpAlertConstants.NAME_BODY_PARAMS);
contentField = paramsMap.get(HttpAlertConstants.NAME_CONTENT_FIELD);
requestType = paramsMap.get(HttpAlertConstants.NAME_REQUEST_TYPE);
if (StringUtils.isBlank(url)) {
throw new IllegalArgumentException("url can not be null");
}
String headerParamsString = paramsMap.get(HttpAlertConstants.NAME_HEADER_PARAMS);
if (StringUtils.isNotBlank(headerParamsString)) {
headerParams = JSONUtils.toMap(headerParamsString);
if (headerParams == null) {
throw new IllegalArgumentException("headerParams is not a valid json");
}
} else {
headerParams = new HashMap<>();
}
String bodyParamsString = paramsMap.get(HttpAlertConstants.NAME_BODY_PARAMS);
if (StringUtils.isNotBlank(bodyParamsString)) {
bodyParams = JSONUtils.toMap(bodyParamsString);
if (bodyParams == null) {
throw new IllegalArgumentException("bodyParams is not a valid json");
}
} else {
bodyParams = new HashMap<>();
}
try {
requestType = HttpRequestMethod.valueOf(paramsMap.get(HttpAlertConstants.NAME_REQUEST_TYPE));
} catch (IllegalArgumentException e) {
throw new IllegalArgumentException("requestType is not a valid value");
}
contentType = OkHttpRequestHeaderContentType.fromValue(paramsMap.get(HttpAlertConstants.NAME_CONTENT_TYPE));
if (contentType == null) {
throw new IllegalArgumentException("contentType is not a valid value");
}
timeout = StringUtils.isNotBlank(paramsMap.get(HttpAlertConstants.NAME_TIMEOUT))
? Integer.parseInt(paramsMap.get(HttpAlertConstants.NAME_TIMEOUT))
: HttpAlertConstants.DEFAULT_TIMEOUT;
: HttpAlertConstants.DEFAULT_TIMEOUT * 1000;
}
public AlertResult send(String msg) {
AlertResult alertResult = new AlertResult();
OkHttpResponse okHttpResponse;
try {
createHttpRequest(msg);
} catch (MalformedURLException e) {
throw new RuntimeException(e);
} catch (URISyntaxException e) {
okHttpResponse = sendHttpRequest(msg);
} catch (RuntimeException e) {
throw new RuntimeException(e);
}
if (httpRequest == null) {
alertResult.setSuccess(false);
alertResult.setMessage("Request types are not supported");
return alertResult;
}
validateResponse(okHttpResponse, alertResult);
try {
String resp = this.getResponseString(httpRequest);
alertResult.setSuccess(true);
alertResult.setMessage(resp);
} catch (Exception e) {
log.error("send http alert msg exception : {}", e.getMessage());
return alertResult;
}
private void validateResponse(OkHttpResponse okHttpResponse, AlertResult alertResult) {
if (okHttpResponse.getStatusCode() != HttpStatus.SC_OK) {
alertResult.setSuccess(false);
alertResult.setMessage(
String.format("Send http request alert failed: %s", e.getMessage()));
alertResult
.setMessage(String.format("send http alert failed, response body: %s", okHttpResponse.getBody()));
} else {
alertResult.setSuccess(true);
alertResult
.setMessage(String.format("send http alert success, response body: %s", okHttpResponse.getBody()));
}
return alertResult;
}
public String getResponseString(HttpRequestBase httpRequest) throws Exception {
private OkHttpResponse sendHttpRequest(String msg) throws RuntimeException {
switch (requestType) {
case POST:
setMsgInHeader(msg);
setMsgInRequestBody(msg);
return sendPostRequest();
case GET:
setMsgInUrl(msg);
setMsgInHeader(msg);
return sendGetRequest();
case PUT:
setMsgInHeader(msg);
setMsgInRequestBody(msg);
return sendPutRequest();
default:
throw new RuntimeException(String.format("http request method %s not supported",
requestType));
}
}
RequestConfig requestConfig = RequestConfig.custom()
.setConnectTimeout(timeout * 1000)
.setConnectionRequestTimeout(timeout * 1000)
.setSocketTimeout(timeout * 1000)
.build();
CloseableHttpClient httpClient = HttpClients.custom()
.setDefaultRequestConfig(requestConfig)
.setRetryHandler(HttpServiceRetryStrategy.retryStrategy).build();
@SneakyThrows
private OkHttpResponse sendGetRequest() {
OkHttpRequestHeaders okHttpRequestHeaders = new OkHttpRequestHeaders();
okHttpRequestHeaders.setHeaders(headerParams);
okHttpRequestHeaders.setOkHttpRequestHeaderContentType(contentType);
Map<String, Object> requestParams = new HashMap<>();
log.info("sending http alert get request, url: {}, header: {}, requestParams: {}, contentType: {}",
url, headerParams, requestParams, contentType.getValue());
return OkHttpUtils.get(url, okHttpRequestHeaders,
requestParams, timeout, timeout, timeout);
}
CloseableHttpResponse response = httpClient.execute(httpRequest);
HttpEntity entity = response.getEntity();
return EntityUtils.toString(entity, StandardCharsets.UTF_8);
@SneakyThrows
private OkHttpResponse sendPostRequest() {
OkHttpRequestHeaders okHttpRequestHeaders = new OkHttpRequestHeaders();
okHttpRequestHeaders.setHeaders(headerParams);
okHttpRequestHeaders.setOkHttpRequestHeaderContentType(contentType);
Map<String, Object> requestBody = Collections.unmodifiableMap(bodyParams);
log.info("sending http alert post request, url: {}, header: {}, requestBody: {}, contentType: {}",
url, headerParams, requestBody, contentType.getValue());
return OkHttpUtils.post(url, okHttpRequestHeaders, null,
requestBody, timeout, timeout, timeout);
}
private void createHttpRequest(String msg) throws MalformedURLException, URISyntaxException {
if (REQUEST_TYPE_POST.equalsIgnoreCase(requestType)) {
httpRequest = new HttpPost(url);
setHeader();
// POST request add param in request body
setMsgInRequestBody(msg);
} else if (REQUEST_TYPE_GET.equalsIgnoreCase(requestType)) {
// GET request add param in url
setMsgInUrl(msg);
URL unencodeUrl = new URL(url);
URI uri = new URI(unencodeUrl.getProtocol(), unencodeUrl.getAuthority(), unencodeUrl.getPath(),
unencodeUrl.getQuery(), null);
httpRequest = new HttpGet(uri);
setHeader();
}
@SneakyThrows
private OkHttpResponse sendPutRequest() {
OkHttpRequestHeaders okHttpRequestHeaders = new OkHttpRequestHeaders();
okHttpRequestHeaders.setHeaders(headerParams);
okHttpRequestHeaders.setOkHttpRequestHeaderContentType(contentType);
Map<String, Object> requestBody = Collections.unmodifiableMap(bodyParams);
log.info("sending http alert put request, url: {}, header: {}, requestBody: {}, contentType: {}",
url, headerParams, requestBody, contentType.getValue());
return OkHttpUtils.put(url, okHttpRequestHeaders,
requestBody, timeout, timeout, timeout);
}
/**
* 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;
}
if (url.contains(HttpAlertConstants.MSG_PARAMS)) {
try {
url = String.format("%s%s%s=%s", url, type, contentField,
url = url.replace(HttpAlertConstants.MSG_PARAMS,
URLEncoder.encode(msg, StandardCharsets.UTF_8.name()));
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
@ -168,37 +194,31 @@ public final class HttpSender {
/**
* set header params
*/
private void setHeader() {
if (httpRequest == null) {
private void setMsgInHeader(String msg) {
if (msg == 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()));
}
headerParams.forEach((key, value) -> {
if (value.contains(HttpAlertConstants.MSG_PARAMS)) {
headerParams.put(key, value.replace(HttpAlertConstants.MSG_PARAMS, msg));
}
});
}
/**
* set body params
*/
private void setMsgInRequestBody(String msg) {
try {
ObjectNode objectNode = JSONUtils.createObjectNode();
if (StringUtils.isNotBlank(bodyParams)) {
objectNode = JSONUtils.parseObject(bodyParams);
}
// set msg content field
objectNode.put(contentField, msg);
StringEntity entity = new StringEntity(JSONUtils.toJsonString(objectNode), StandardCharsets.UTF_8);
((HttpPost) httpRequest).setEntity(entity);
} catch (Exception e) {
log.error("send http alert msg exception : {}", e.getMessage());
if (bodyParams == null) {
return;
}
}
public String getRequestUrl() {
return httpRequest.getURI().toString();
bodyParams.forEach((key, value) -> {
if (value.contains(HttpAlertConstants.MSG_PARAMS)) {
bodyParams.put(key, value.replace(HttpAlertConstants.MSG_PARAMS, msg));
}
});
}
}

134
dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-http/src/test/java/org/apache/dolphinscheduler/plugin/alert/http/HttpSenderTest.java

@ -17,37 +17,131 @@
package org.apache.dolphinscheduler.plugin.alert.http;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
import org.apache.dolphinscheduler.alert.api.AlertResult;
import org.apache.dolphinscheduler.common.model.OkHttpRequestHeaderContentType;
import org.apache.dolphinscheduler.common.utils.JSONUtils;
import org.apache.commons.io.IOUtils;
import org.apache.http.HttpStatus;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import okhttp3.mockwebserver.Dispatcher;
import okhttp3.mockwebserver.MockResponse;
import okhttp3.mockwebserver.MockWebServer;
import okhttp3.mockwebserver.RecordedRequest;
import org.jetbrains.annotations.NotNull;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.junit.jupiter.MockitoExtension;
@ExtendWith(MockitoExtension.class)
public class HttpSenderTest {
private final List<MockWebServer> mockWebServers = new ArrayList<>();
private Map<String, String> paramsMap = new HashMap<>();
@AfterEach
public void after() {
mockWebServers.forEach(IOUtils::closeQuietly);
mockWebServers.clear();
}
@Test
public void sendTest() throws Exception {
Map<String, String> paramsMap = new HashMap<>();
String url = "https://www.dolphinscheduler-not-exists-web.com:12345";
String contentField = "content";
paramsMap.put(HttpAlertConstants.NAME_URL, url);
paramsMap.put(HttpAlertConstants.NAME_REQUEST_TYPE, "GET");
paramsMap.put(HttpAlertConstants.NAME_HEADER_PARAMS, "{\"Content-Type\":\"application/json\"}");
paramsMap.put(HttpAlertConstants.NAME_BODY_PARAMS, "{\"number\":\"123456\"}");
paramsMap.put(HttpAlertConstants.NAME_CONTENT_FIELD, contentField);
paramsMap.put(HttpAlertConstants.NAME_TIMEOUT, String.valueOf(HttpAlertConstants.DEFAULT_TIMEOUT));
HttpSender httpSender = spy(new HttpSender(paramsMap));
doReturn("success").when(httpSender).getResponseString(any());
AlertResult alertResult = httpSender.send("Fault tolerance warning");
void testHttpSenderGet() throws Exception {
String msg = "msg_test";
Map<String, String> headerParams = new HashMap<>();
headerParams.put("msg", msg);
paramsMap.put(HttpAlertConstants.NAME_HEADER_PARAMS, JSONUtils.toJsonString(headerParams));
paramsMap.put(HttpAlertConstants.NAME_CONTENT_TYPE, OkHttpRequestHeaderContentType.APPLICATION_JSON.getValue());
String mockGetUrl = createMockWebServer(String.format("/get/%s", msg), HttpStatus.SC_OK);
String actualGetUrl = mockGetUrl.replace(msg, HttpAlertConstants.MSG_PARAMS);
paramsMap.put(HttpAlertConstants.NAME_URL, actualGetUrl);
paramsMap.put(HttpAlertConstants.NAME_REQUEST_TYPE, HttpRequestMethod.GET.name());
HttpSender httpSender = new HttpSender(paramsMap);
AlertResult alertResult = httpSender.send(msg);
Assertions.assertTrue(alertResult.isSuccess());
Assertions.assertTrue(httpSender.getRequestUrl().contains(url));
Assertions.assertTrue(httpSender.getRequestUrl().contains(contentField));
Assertions.assertTrue(alertResult.getMessage().contains(msg));
}
@Test
void testHttpSenderPost() throws Exception {
String msg = "msg_test";
Map<String, String> bodyParams = new HashMap<>();
bodyParams.put("msg", msg);
paramsMap.put(HttpAlertConstants.NAME_BODY_PARAMS, JSONUtils.toJsonString(bodyParams));
paramsMap.put(HttpAlertConstants.NAME_CONTENT_TYPE, OkHttpRequestHeaderContentType.APPLICATION_JSON.getValue());
String mockPostUrl = createMockWebServer("/post", HttpStatus.SC_OK);
paramsMap.put(HttpAlertConstants.NAME_URL, mockPostUrl);
paramsMap.put(HttpAlertConstants.NAME_REQUEST_TYPE, HttpRequestMethod.POST.name());
HttpSender httpSender = new HttpSender(paramsMap);
AlertResult alertResult = httpSender.send(msg);
Assertions.assertTrue(alertResult.isSuccess());
Assertions.assertTrue(alertResult.getMessage().contains(msg));
}
@Test
void testHttpSenderPut() throws Exception {
String msg = "msg_test";
Map<String, String> bodyParams = new HashMap<>();
bodyParams.put("msg", msg);
paramsMap.put(HttpAlertConstants.NAME_BODY_PARAMS, JSONUtils.toJsonString(bodyParams));
paramsMap.put(HttpAlertConstants.NAME_CONTENT_TYPE, OkHttpRequestHeaderContentType.APPLICATION_JSON.getValue());
String mockPostUrl = createMockWebServer("/post", HttpStatus.SC_OK);
paramsMap.put(HttpAlertConstants.NAME_URL, mockPostUrl);
paramsMap.put(HttpAlertConstants.NAME_REQUEST_TYPE, HttpRequestMethod.PUT.name());
HttpSender httpSender = new HttpSender(paramsMap);
AlertResult alertResult = httpSender.send(msg);
Assertions.assertTrue(alertResult.isSuccess());
Assertions.assertTrue(alertResult.getMessage().contains(msg));
}
private String createMockWebServer(String path, int actualResponseCode) throws IOException {
MockWebServer server = new MockWebServer();
mockWebServers.add(server);
server.start();
server.setDispatcher(generateMockDispatcher(actualResponseCode));
return server.url(path).toString();
}
private Dispatcher generateMockDispatcher(int actualResponseCode) {
return new Dispatcher() {
@NotNull
@Override
public MockResponse dispatch(@NotNull RecordedRequest request) {
Map<String, String> responseMap = new HashMap<>();
responseMap.put("url", request.getRequestUrl().toString());
responseMap.put("headers", request.getHeaders().toString());
responseMap.put("body", request.getBody().toString());
String responseBody = JSONUtils.toJsonString(responseMap);
return new MockResponse()
.setResponseCode(actualResponseCode)
.setBody(responseBody);
}
};
}
}

6
dolphinscheduler-alert/dolphinscheduler-alert-server/src/main/java/org/apache/dolphinscheduler/alert/plugin/AlertPluginManager.java

@ -54,10 +54,10 @@ public final class AlertPluginManager {
private final Map<Integer, AlertChannel> alertPluginMap = new HashMap<>();
public void start() {
log.info("AlertPluginManager start ...");
log.info("AlertPluginManager start...");
checkAlertPluginExist();
installAlertPlugin();
log.info("AlertPluginManager started ...");
log.info("AlertPluginManager started...");
}
public Optional<AlertChannel> getAlertChannel(int id) {
@ -70,7 +70,7 @@ public final class AlertPluginManager {
private void checkAlertPluginExist() {
if (!pluginDao.checkPluginDefineTableExist()) {
log.error("Plugin Define Table t_ds_plugin_define Not Exist . Please Create it First !");
log.error("Plugin Define Table t_ds_plugin_define Not Exist. Please Create it First!");
System.exit(1);
}
}

4
dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/interceptor/LocaleChangeInterceptor.java

@ -28,10 +28,10 @@ import javax.servlet.http.HttpServletResponse;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.lang.Nullable;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.util.WebUtils;
public class LocaleChangeInterceptor extends HandlerInterceptorAdapter {
public class LocaleChangeInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {

7
dolphinscheduler-spi/src/main/java/org/apache/dolphinscheduler/spi/params/base/DataType.java

@ -17,9 +17,12 @@
package org.apache.dolphinscheduler.spi.params.base;
import lombok.Getter;
/**
* param datetype
*/
@Getter
public enum DataType {
STRING("string"),
@ -32,8 +35,4 @@ public enum DataType {
this.dataType = dataType;
}
public String getDataType() {
return this.dataType;
}
}

29
dolphinscheduler-spi/src/main/java/org/apache/dolphinscheduler/spi/params/base/Validate.java

@ -17,6 +17,8 @@
package org.apache.dolphinscheduler.spi.params.base;
import lombok.Data;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder;
@ -25,6 +27,7 @@ import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder;
* form validate
*/
@JsonDeserialize(builder = Validate.Builder.class)
@Data
public class Validate {
@JsonProperty("required")
@ -62,7 +65,7 @@ public class Validate {
return new Builder();
}
@JsonPOJOBuilder(buildMethodName = "build", withPrefix = "set")
@JsonPOJOBuilder(withPrefix = "set")
public static class Builder {
private boolean required = false;
@ -111,28 +114,4 @@ public class Validate {
return new Validate(this);
}
}
public boolean isRequired() {
return required;
}
public String getMessage() {
return message;
}
public String getType() {
return type;
}
public String getTrigger() {
return trigger;
}
public Double getMin() {
return min;
}
public Double getMax() {
return max;
}
}

2
dolphinscheduler-ui/src/locales/en_US/security.ts

@ -244,7 +244,7 @@ export default {
requestType: 'Request Type',
headerParams: 'Headers',
bodyParams: 'Body',
contentField: 'Content Field',
contentType: 'Content Type',
timeout: 'Timeout(s)',
Keyword: 'Keyword',
userParams: 'User Params',

2
dolphinscheduler-ui/src/locales/zh_CN/security.ts

@ -240,7 +240,7 @@ export default {
requestType: '请求方式',
headerParams: '请求头',
bodyParams: '请求体',
contentField: '内容字段',
contentType: 'Content Type',
timeout: '超时时间(秒)',
Keyword: '关键词',
userParams: '自定义参数',

1
dolphinscheduler-ui/src/views/security/alarm-instance-manage/detail.tsx

@ -203,6 +203,7 @@ const DetailModal = defineComponent({
'security.alarm_instance.select_plugin_tips'
)}
on-update:value={onChangePlugin}
filterable
/>
)
},

Loading…
Cancel
Save