You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@dolphinscheduler.apache.org by ca...@apache.org on 2022/01/29 03:37:15 UTC

[dolphinscheduler] branch dev updated: [DS-8215][feat] Support WebexTeams Plugin (#8217)

This is an automated email from the ASF dual-hosted git repository.

caishunfeng pushed a commit to branch dev
in repository https://gitbox.apache.org/repos/asf/dolphinscheduler.git


The following commit(s) were added to refs/heads/dev by this push:
     new 49d581d  [DS-8215][feat] Support WebexTeams Plugin (#8217)
49d581d is described below

commit 49d581d72e62ce45bb942f2b314d9606a45d5d1c
Author: wangyang <wa...@lqwang.net>
AuthorDate: Sat Jan 29 11:36:38 2022 +0800

    [DS-8215][feat] Support WebexTeams Plugin (#8217)
    
    Co-authored-by: qingwli <qi...@cisco.com>
---
 .../pom.xml                                        |  27 ++--
 .../plugin/alert/webexteams/WebexMessage.java      |  75 +++++++++
 .../alert/webexteams/WebexTeamsAlertChannel.java   |  38 +++++
 .../webexteams/WebexTeamsAlertChannelFactory.java  | 100 ++++++++++++
 .../alert/webexteams/WebexTeamsDestination.java    |  63 ++++++++
 .../webexteams/WebexTeamsParamsConstants.java      |  39 +++++
 .../plugin/alert/webexteams/WebexTeamsSender.java  | 170 +++++++++++++++++++++
 .../WebexTeamsAlertChannelFactoryTest.java         |  43 ++++++
 .../alert/webexteams/WebexTeamsSenderTest.java     |  86 +++++++++++
 .../dolphinscheduler-alert-plugins/pom.xml         |   1 +
 .../dolphinscheduler-alert-server/pom.xml          |   4 +
 pom.xml                                            |   5 +
 12 files changed, 634 insertions(+), 17 deletions(-)

diff --git a/dolphinscheduler-alert/dolphinscheduler-alert-plugins/pom.xml b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-webexteams/pom.xml
similarity index 64%
copy from dolphinscheduler-alert/dolphinscheduler-alert-plugins/pom.xml
copy to dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-webexteams/pom.xml
index aaa4b32..37e7899 100644
--- a/dolphinscheduler-alert/dolphinscheduler-alert-plugins/pom.xml
+++ b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-webexteams/pom.xml
@@ -19,30 +19,23 @@
          xmlns="http://maven.apache.org/POM/4.0.0"
          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     <parent>
-        <artifactId>dolphinscheduler-alert</artifactId>
+        <artifactId>dolphinscheduler-alert-plugins</artifactId>
         <groupId>org.apache.dolphinscheduler</groupId>
         <version>2.0.4-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
-    <artifactId>dolphinscheduler-alert-plugins</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>
-        <module>dolphinscheduler-alert-feishu</module>
-        <module>dolphinscheduler-alert-slack</module>
-        <module>dolphinscheduler-alert-pagerduty</module>
-    </modules>
+    <artifactId>dolphinscheduler-alert-webexteams</artifactId>
+    <packaging>jar</packaging>
 
     <dependencies>
         <dependency>
-            <groupId>org.apache.dolphinscheduler</groupId>
-            <artifactId>dolphinscheduler-alert-api</artifactId>
+            <groupId>com.google.guava</groupId>
+            <artifactId>guava</artifactId>
         </dependency>
-    </dependencies>
 
+        <dependency>
+            <groupId>org.apache.httpcomponents</groupId>
+            <artifactId>httpclient</artifactId>
+        </dependency>
+    </dependencies>
 </project>
diff --git a/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-webexteams/src/main/java/org/apache/dolphinscheduler/plugin/alert/webexteams/WebexMessage.java b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-webexteams/src/main/java/org/apache/dolphinscheduler/plugin/alert/webexteams/WebexMessage.java
new file mode 100644
index 0000000..f1b908f
--- /dev/null
+++ b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-webexteams/src/main/java/org/apache/dolphinscheduler/plugin/alert/webexteams/WebexMessage.java
@@ -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.webexteams;
+
+public class WebexMessage {
+    private String roomId;
+    private String toPersonId;
+    private String toPersonEmail;
+    private String text;
+    private String markdown;
+    private String html;
+
+    public String getRoomId() {
+        return roomId;
+    }
+
+    public void setRoomId(String roomId) {
+        this.roomId = roomId;
+    }
+
+    public String getToPersonId() {
+        return toPersonId;
+    }
+
+    public void setToPersonId(String toPersonId) {
+        this.toPersonId = toPersonId;
+    }
+
+    public String getToPersonEmail() {
+        return toPersonEmail;
+    }
+
+    public void setToPersonEmail(String toPersonEmail) {
+        this.toPersonEmail = toPersonEmail;
+    }
+
+    public String getText() {
+        return text;
+    }
+
+    public void setText(String text) {
+        this.text = text;
+    }
+
+    public String getMarkdown() {
+        return markdown;
+    }
+
+    public void setMarkdown(String markdown) {
+        this.markdown = markdown;
+    }
+
+    public String getHtml() {
+        return html;
+    }
+
+    public void setHtml(String html) {
+        this.html = html;
+    }
+}
diff --git a/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-webexteams/src/main/java/org/apache/dolphinscheduler/plugin/alert/webexteams/WebexTeamsAlertChannel.java b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-webexteams/src/main/java/org/apache/dolphinscheduler/plugin/alert/webexteams/WebexTeamsAlertChannel.java
new file mode 100644
index 0000000..08963ca
--- /dev/null
+++ b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-webexteams/src/main/java/org/apache/dolphinscheduler/plugin/alert/webexteams/WebexTeamsAlertChannel.java
@@ -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.webexteams;
+
+import org.apache.dolphinscheduler.alert.api.AlertChannel;
+import org.apache.dolphinscheduler.alert.api.AlertData;
+import org.apache.dolphinscheduler.alert.api.AlertInfo;
+import org.apache.dolphinscheduler.alert.api.AlertResult;
+
+import java.util.Map;
+
+public final class WebexTeamsAlertChannel implements AlertChannel {
+    @Override
+    public AlertResult process(AlertInfo alertInfo) {
+        AlertData alertData = alertInfo.getAlertData();
+        Map<String, String> alertParams = alertInfo.getAlertParams();
+        if (alertParams == null || alertParams.size() == 0) {
+            return new AlertResult("false", "WebexTeams alert params is empty");
+        }
+
+        return new WebexTeamsSender(alertParams).sendWebexTeamsAlter(alertData);
+    }
+}
diff --git a/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-webexteams/src/main/java/org/apache/dolphinscheduler/plugin/alert/webexteams/WebexTeamsAlertChannelFactory.java b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-webexteams/src/main/java/org/apache/dolphinscheduler/plugin/alert/webexteams/WebexTeamsAlertChannelFactory.java
new file mode 100644
index 0000000..f17c3cd
--- /dev/null
+++ b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-webexteams/src/main/java/org/apache/dolphinscheduler/plugin/alert/webexteams/WebexTeamsAlertChannelFactory.java
@@ -0,0 +1,100 @@
+/*
+ * 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.webexteams;
+
+import org.apache.dolphinscheduler.alert.api.AlertChannel;
+import org.apache.dolphinscheduler.alert.api.AlertChannelFactory;
+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.radio.RadioParam;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import com.google.auto.service.AutoService;
+
+@AutoService(AlertChannelFactory.class)
+public final class WebexTeamsAlertChannelFactory implements AlertChannelFactory {
+    @Override
+    public String name() {
+        return "WebexTeams";
+    }
+
+    @Override
+    public List<PluginParams> params() {
+        List<PluginParams> paramsList = new ArrayList<>();
+        InputParam botAccessToken = InputParam.newBuilder(WebexTeamsParamsConstants.NAME_WEBEX_TEAMS_BOT_ACCESS_TOKEN, WebexTeamsParamsConstants.WEBEX_TEAMS_BOT_ACCESS_TOKEN)
+            .setPlaceholder("Please enter the robot's access token you were given")
+            .addValidate(Validate.newBuilder()
+                .setRequired(true)
+                .build())
+            .build();
+
+        InputParam roomId = InputParam.newBuilder(WebexTeamsParamsConstants.NAME_WEBEX_TEAMS_ROOM_ID, WebexTeamsParamsConstants.WEBEX_TEAMS_ROOM_ID)
+            .setPlaceholder("The room ID of the message")
+            .addValidate(Validate.newBuilder()
+                .setRequired(false)
+                .build())
+            .build();
+
+        InputParam toPersonId = InputParam.newBuilder(WebexTeamsParamsConstants.NAME_WEBEX_TEAMS_TO_PERSON_ID, WebexTeamsParamsConstants.WEBEX_TEAMS_TO_PERSON_ID)
+            .setPlaceholder("The person ID of the message recipient")
+            .addValidate(Validate.newBuilder()
+                .setRequired(false)
+                .build())
+            .build();
+
+        InputParam toPersonEmail = InputParam.newBuilder(WebexTeamsParamsConstants.NAME_WEBEX_TEAMS_TO_PERSON_EMAIL, WebexTeamsParamsConstants.WEBEX_TEAMS_TO_PERSON_EMAIL)
+            .setPlaceholder("The email address of the message recipient")
+            .addValidate(Validate.newBuilder()
+                .setRequired(false)
+                .build())
+            .build();
+
+        InputParam atSomeoneInRoom = InputParam.newBuilder(WebexTeamsParamsConstants.NAME_WEBEX_TEAMS_AT_SOMEONE_IN_ROOM, WebexTeamsParamsConstants.WEBEX_TEAMS_AT_SOMEONE_IN_ROOM)
+            .setPlaceholder("use ,(eng commas) to separate multiple emails")
+            .addValidate(Validate.newBuilder()
+                .setRequired(false)
+                .build())
+            .build();
+
+        RadioParam destination = RadioParam.newBuilder(WebexTeamsParamsConstants.NAME_WEBEX_TEAMS_DESTINATION, WebexTeamsParamsConstants.WEBEX_TEAMS_DESTINATION)
+            .addParamsOptions(new ParamsOptions(WebexTeamsDestination.ROOM_ID.getDescp(), WebexTeamsDestination.ROOM_ID.getDescp(), false))
+            .addParamsOptions(new ParamsOptions(WebexTeamsDestination.PERSON_EMAIL.getDescp(), WebexTeamsDestination.PERSON_EMAIL.getDescp(), false))
+            .addParamsOptions(new ParamsOptions(WebexTeamsDestination.PERSON_ID.getDescp(), WebexTeamsDestination.PERSON_ID.getDescp(), false))
+            .setValue(WebexTeamsDestination.ROOM_ID.getDescp())
+            .addValidate(Validate.newBuilder().setRequired(true).build())
+            .build();
+
+        paramsList.add(botAccessToken);
+        paramsList.add(roomId);
+        paramsList.add(toPersonId);
+        paramsList.add(toPersonEmail);
+        paramsList.add(atSomeoneInRoom);
+        paramsList.add(destination);
+
+        return paramsList;
+    }
+
+    @Override
+    public AlertChannel create() {
+        return new WebexTeamsAlertChannel();
+    }
+}
diff --git a/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-webexteams/src/main/java/org/apache/dolphinscheduler/plugin/alert/webexteams/WebexTeamsDestination.java b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-webexteams/src/main/java/org/apache/dolphinscheduler/plugin/alert/webexteams/WebexTeamsDestination.java
new file mode 100644
index 0000000..1d23aed
--- /dev/null
+++ b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-webexteams/src/main/java/org/apache/dolphinscheduler/plugin/alert/webexteams/WebexTeamsDestination.java
@@ -0,0 +1,63 @@
+/*
+ * 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.webexteams;
+
+import static java.util.stream.Collectors.toMap;
+
+import java.util.Arrays;
+import java.util.Map;
+
+import com.google.common.base.Functions;
+
+public enum WebexTeamsDestination {
+    /**
+     * 0 ROOM_ID;
+     * 1 PERSON_EMAIL;
+     * 2 PERSON_ID;
+     */
+    ROOM_ID(0, "roomId"),
+    PERSON_EMAIL(1, "personEmail"),
+    PERSON_ID(2, "personId");
+
+    private final int code;
+    private final String descp;
+
+    WebexTeamsDestination(int code, String descp) {
+        this.code = code;
+        this.descp = descp;
+    }
+
+    public int getCode() {
+        return code;
+    }
+
+    public String getDescp() {
+        return descp;
+    }
+
+    private static final Map<String, WebexTeamsDestination> WEBEX_TEAMS_DESTINATION_MAP =
+        Arrays.stream(WebexTeamsDestination.values()).collect(toMap(WebexTeamsDestination::getDescp, Functions.identity()));
+
+    public static WebexTeamsDestination of(String descp) {
+        if (WEBEX_TEAMS_DESTINATION_MAP.containsKey(descp)) {
+            return WEBEX_TEAMS_DESTINATION_MAP.get(descp);
+        }
+
+        return null;
+    }
+}
diff --git a/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-webexteams/src/main/java/org/apache/dolphinscheduler/plugin/alert/webexteams/WebexTeamsParamsConstants.java b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-webexteams/src/main/java/org/apache/dolphinscheduler/plugin/alert/webexteams/WebexTeamsParamsConstants.java
new file mode 100644
index 0000000..16dddda
--- /dev/null
+++ b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-webexteams/src/main/java/org/apache/dolphinscheduler/plugin/alert/webexteams/WebexTeamsParamsConstants.java
@@ -0,0 +1,39 @@
+/*
+ * 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.webexteams;
+
+public final class WebexTeamsParamsConstants {
+
+    public static final String NAME_WEBEX_TEAMS_BOT_ACCESS_TOKEN = "BotAccessToken";
+    public static final String WEBEX_TEAMS_BOT_ACCESS_TOKEN = "botAccessToken";
+    public static final String NAME_WEBEX_TEAMS_DESTINATION = "Destination";
+    public static final String WEBEX_TEAMS_DESTINATION = "destination";
+    public static final String NAME_WEBEX_TEAMS_TO_PERSON_ID = "ToPersonId";
+    public static final String WEBEX_TEAMS_TO_PERSON_ID = "toPersonId";
+    public static final String NAME_WEBEX_TEAMS_TO_PERSON_EMAIL = "ToPersonEmail";
+    public static final String WEBEX_TEAMS_TO_PERSON_EMAIL = "toPersonEmail";
+    public static final String NAME_WEBEX_TEAMS_ROOM_ID = "RoomId";
+    public static final String WEBEX_TEAMS_ROOM_ID = "roomId";
+    public static final String NAME_WEBEX_TEAMS_AT_SOMEONE_IN_ROOM = "AtSomeoneInRoom";
+    public static final String WEBEX_TEAMS_AT_SOMEONE_IN_ROOM = "atSomeoneInRoom";
+    public static final String WEBEX_TEAMS_API = "https://webexapis.com/v1/messages";
+
+    private WebexTeamsParamsConstants() {
+        throw new UnsupportedOperationException("This is a utility class and cannot be instantiated");
+    }
+}
diff --git a/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-webexteams/src/main/java/org/apache/dolphinscheduler/plugin/alert/webexteams/WebexTeamsSender.java b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-webexteams/src/main/java/org/apache/dolphinscheduler/plugin/alert/webexteams/WebexTeamsSender.java
new file mode 100644
index 0000000..7b61696
--- /dev/null
+++ b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-webexteams/src/main/java/org/apache/dolphinscheduler/plugin/alert/webexteams/WebexTeamsSender.java
@@ -0,0 +1,170 @@
+/*
+ * 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.webexteams;
+
+import org.apache.dolphinscheduler.alert.api.AlertData;
+import org.apache.dolphinscheduler.alert.api.AlertResult;
+import org.apache.dolphinscheduler.spi.utils.JSONUtils;
+
+import org.apache.http.HttpStatus;
+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.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClients;
+
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+
+import org.slf4j.Logger;
+
+import com.google.common.base.Preconditions;
+
+public final class WebexTeamsSender {
+    private static final Logger log = org.slf4j.LoggerFactory.getLogger(WebexTeamsSender.class);
+
+    private final String botAccessToken;
+    private final String roomId;
+    private final String toPersonId;
+    private final String toPersonEmail;
+    private final String atSomeoneInRoom;
+    private final WebexTeamsDestination destination;
+
+    public WebexTeamsSender(Map<String, String> config) {
+        botAccessToken = config.get(WebexTeamsParamsConstants.NAME_WEBEX_TEAMS_BOT_ACCESS_TOKEN);
+        roomId = config.get(WebexTeamsParamsConstants.NAME_WEBEX_TEAMS_ROOM_ID);
+        toPersonId = config.get(WebexTeamsParamsConstants.NAME_WEBEX_TEAMS_TO_PERSON_ID);
+        toPersonEmail = config.get(WebexTeamsParamsConstants.NAME_WEBEX_TEAMS_TO_PERSON_EMAIL);
+        atSomeoneInRoom = config.get(WebexTeamsParamsConstants.NAME_WEBEX_TEAMS_AT_SOMEONE_IN_ROOM);
+        destination = WebexTeamsDestination.of(config.get(WebexTeamsParamsConstants.NAME_WEBEX_TEAMS_DESTINATION));
+        Preconditions.checkArgument(!Objects.isNull(botAccessToken), "WebexTeams bot access token can not be null");
+        Preconditions.checkArgument(!Objects.isNull(destination), "WebexTeams message destination can not be null");
+        Preconditions.checkArgument((!Objects.isNull(roomId) || !Objects.isNull(toPersonId) || !Objects.isNull(toPersonEmail)),"WebexTeams message destination could not be determined. Provide only one destination in the roomId, toPersonEmail, or toPersonId field");
+    }
+
+    public AlertResult sendWebexTeamsAlter(AlertData alertData) {
+        AlertResult alertResult = new AlertResult();
+        alertResult.setStatus("false");
+        alertResult.setMessage("send webex teams alert fail.");
+
+        try {
+            send(alertResult, alertData);
+        } catch (Exception e) {
+            log.info("send webex teams alert exception : {}", e.getMessage());
+        }
+
+        return alertResult;
+    }
+
+    private void send(AlertResult alertResult, AlertData alertData) throws IOException {
+        CloseableHttpClient httpClient = HttpClients.createDefault();
+
+        try {
+            HttpPost httpPost = constructHttpPost(getMessage(alertData), botAccessToken);
+            CloseableHttpResponse response = httpClient.execute(httpPost);
+
+            int statusCode = response.getStatusLine().getStatusCode();
+            try {
+                if (statusCode == HttpStatus.SC_OK) {
+                    alertResult.setStatus("true");
+                    alertResult.setMessage("send webex teams alert success");
+                } else {
+                    log.info("send webex teams alert fail, statusCode : {}", statusCode);
+                }
+            } finally {
+                response.close();
+            }
+        } catch (IOException e) {
+            log.info("send webex teams alert exception : {}", e.getMessage());
+        } finally {
+            httpClient.close();
+        }
+    }
+
+    private WebexMessage getMessage(AlertData alertData) {
+        WebexMessage message = new WebexMessage();
+        String formatContent = formatContent(alertData);
+
+        switch (destination) {
+            case ROOM_ID: {
+                message.setRoomId(roomId);
+                if (!Objects.isNull(atSomeoneInRoom)) {
+                    formatContent = addAtPersonEmailInRoom(formatContent, atSomeoneInRoom);
+                }
+                break;
+            }
+            case PERSON_EMAIL: {
+                message.setToPersonEmail(toPersonEmail);
+                break;
+            }
+            case PERSON_ID: {
+                message.setToPersonId(toPersonId);
+                break;
+            }
+        }
+
+        message.setMarkdown(formatContent);
+        return message;
+    }
+
+    private static HttpPost constructHttpPost(WebexMessage message, String botAccessToken) {
+        HttpPost post = new HttpPost(WebexTeamsParamsConstants.WEBEX_TEAMS_API);
+        StringEntity entity = new StringEntity(JSONUtils.toJsonString(message), StandardCharsets.UTF_8);
+        post.setEntity(entity);
+        post.addHeader("Content-Type", "application/json; charset=utf-8");
+        post.addHeader("Authorization", "Bearer " + botAccessToken);
+        return post;
+    }
+
+    public static String addAtPersonEmailInRoom(String formatContent, String atPersonEmailInRoom) {
+        String[] emailArr = atPersonEmailInRoom.split(",");
+        StringBuilder formatContentBuilder = new StringBuilder(formatContent);
+        for (String email: emailArr) {
+            formatContentBuilder.append(" <@personEmail:").append(email).append(">");
+        }
+
+        return  formatContentBuilder.toString();
+    }
+
+    public static String formatContent(AlertData alertData) {
+        if (alertData.getContent() != null) {
+            List<Map> list = JSONUtils.toList(alertData.getContent(), Map.class);
+            if (list.isEmpty()) {
+                return alertData.getTitle() + alertData.getContent();
+            }
+
+            StringBuilder contents = new StringBuilder(100);
+            contents.append(String.format("`%s`%n", alertData.getTitle()));
+            for (Map map : list) {
+                for (Map.Entry<String, Object> entry : (Iterable<Map.Entry<String, Object>>) map.entrySet()) {
+                    String key = entry.getKey();
+                    String value = entry.getValue().toString();
+                    contents.append(key).append(":").append(value);
+                    contents.append("\n");
+                }
+            }
+
+            return contents.toString();
+        }
+
+        return null;
+    }
+}
diff --git a/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-webexteams/src/test/java/org/apache/dolphinscheduler/plugin/alert/webexteams/WebexTeamsAlertChannelFactoryTest.java b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-webexteams/src/test/java/org/apache/dolphinscheduler/plugin/alert/webexteams/WebexTeamsAlertChannelFactoryTest.java
new file mode 100644
index 0000000..ce00602
--- /dev/null
+++ b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-webexteams/src/test/java/org/apache/dolphinscheduler/plugin/alert/webexteams/WebexTeamsAlertChannelFactoryTest.java
@@ -0,0 +1,43 @@
+/*
+ * 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.webexteams;
+
+import org.apache.dolphinscheduler.alert.api.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;
+
+public class WebexTeamsAlertChannelFactoryTest {
+
+    @Test
+    public void testGetParams() {
+        WebexTeamsAlertChannelFactory webexTeamsAlertChannelFactory = new WebexTeamsAlertChannelFactory();
+        List<PluginParams> params = webexTeamsAlertChannelFactory.params();
+        JSONUtils.toJsonString(params);
+        Assert.assertEquals(6, params.size());
+    }
+
+    @Test
+    public void testCreate() {
+        WebexTeamsAlertChannelFactory webexTeamsAlertChannelFactory = new WebexTeamsAlertChannelFactory();
+        AlertChannel alertChannel = webexTeamsAlertChannelFactory.create();
+        Assert.assertNotNull(alertChannel);
+    }
+}
diff --git a/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-webexteams/src/test/java/org/apache/dolphinscheduler/plugin/alert/webexteams/WebexTeamsSenderTest.java b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-webexteams/src/test/java/org/apache/dolphinscheduler/plugin/alert/webexteams/WebexTeamsSenderTest.java
new file mode 100644
index 0000000..4b9c552
--- /dev/null
+++ b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-webexteams/src/test/java/org/apache/dolphinscheduler/plugin/alert/webexteams/WebexTeamsSenderTest.java
@@ -0,0 +1,86 @@
+/*
+ * 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.webexteams;
+
+import org.apache.dolphinscheduler.alert.api.AlertData;
+import org.apache.dolphinscheduler.alert.api.AlertResult;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+public class WebexTeamsSenderTest {
+    private static final Map<String, String> webexTeamsConfig = new HashMap<>();
+
+    private AlertData alertData;
+
+    private String content = "[{" +
+        "\"projectId\":90001," +
+        "\"projectName\":\"test-k8s\"," +
+        "\"owner\":\"test@cisco.com\"," +
+        "\"processId\":90019," +
+        "\"processDefinitionCode\":1111111," +
+        "\"processName\":\"test-name\"," +
+        "\"taskCode\":2222222," +
+        "\"taskName\":\"test\"," +
+        "\"taskType\":\"SQL\"," +
+        "\"taskState\":\"FAILURE\"," +
+        "\"taskStartTime\":\"2022-01-12 11:05:27\"," +
+        "\"taskEndTime\":\"2022-01-12 11:05:28\"," +
+        "\"taskHost\":\"dolphinscheduler-test\"," +
+        "\"logPath\":\"test.log\"}]";
+
+    @Before
+    public void initDingTalkConfig() {
+        webexTeamsConfig.put(WebexTeamsParamsConstants.NAME_WEBEX_TEAMS_BOT_ACCESS_TOKEN, "accessToken");
+        webexTeamsConfig.put(WebexTeamsParamsConstants.NAME_WEBEX_TEAMS_ROOM_ID, "roomId");
+        webexTeamsConfig.put(WebexTeamsParamsConstants.NAME_WEBEX_TEAMS_TO_PERSON_EMAIL, "email");
+        webexTeamsConfig.put(WebexTeamsParamsConstants.NAME_WEBEX_TEAMS_TO_PERSON_ID, "id");
+        webexTeamsConfig.put(WebexTeamsParamsConstants.NAME_WEBEX_TEAMS_AT_SOMEONE_IN_ROOM, "email1,email2");
+        alertData = new AlertData();
+        alertData.setTitle("test");
+        alertData.setContent(content);
+    }
+
+    @Test
+    public void testSendToRoomId() {
+        webexTeamsConfig.put(WebexTeamsParamsConstants.NAME_WEBEX_TEAMS_DESTINATION, WebexTeamsDestination.ROOM_ID.getDescp());
+        testSend();
+    }
+
+    @Test
+    public void testSendToPersonEmail() {
+        webexTeamsConfig.put(WebexTeamsParamsConstants.NAME_WEBEX_TEAMS_DESTINATION, WebexTeamsDestination.PERSON_EMAIL.getDescp());
+        testSend();
+    }
+
+    @Test
+    public void testSendToPersonId() {
+        webexTeamsConfig.put(WebexTeamsParamsConstants.NAME_WEBEX_TEAMS_DESTINATION, WebexTeamsDestination.PERSON_ID.getDescp());
+        testSend();
+    }
+
+    public void testSend(){
+        WebexTeamsSender webexTeamsSender = new WebexTeamsSender(webexTeamsConfig);
+        AlertResult alertResult = webexTeamsSender.sendWebexTeamsAlter(alertData);
+        Assert.assertEquals("false", alertResult.getStatus());
+    }
+}
diff --git a/dolphinscheduler-alert/dolphinscheduler-alert-plugins/pom.xml b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/pom.xml
index aaa4b32..c3b9be8 100644
--- a/dolphinscheduler-alert/dolphinscheduler-alert-plugins/pom.xml
+++ b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/pom.xml
@@ -36,6 +36,7 @@
         <module>dolphinscheduler-alert-feishu</module>
         <module>dolphinscheduler-alert-slack</module>
         <module>dolphinscheduler-alert-pagerduty</module>
+        <module>dolphinscheduler-alert-webexteams</module>
     </modules>
 
     <dependencies>
diff --git a/dolphinscheduler-alert/dolphinscheduler-alert-server/pom.xml b/dolphinscheduler-alert/dolphinscheduler-alert-server/pom.xml
index 5b6a323..8be15f4 100644
--- a/dolphinscheduler-alert/dolphinscheduler-alert-server/pom.xml
+++ b/dolphinscheduler-alert/dolphinscheduler-alert-server/pom.xml
@@ -70,6 +70,10 @@
             <groupId>org.apache.dolphinscheduler</groupId>
             <artifactId>dolphinscheduler-alert-pagerduty</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.apache.dolphinscheduler</groupId>
+            <artifactId>dolphinscheduler-alert-webexteams</artifactId>
+        </dependency>
 
         <dependency>
             <groupId>org.apache.dolphinscheduler</groupId>
diff --git a/pom.xml b/pom.xml
index 4069198..e2cae23 100644
--- a/pom.xml
+++ b/pom.xml
@@ -359,6 +359,11 @@
             </dependency>
             <dependency>
                 <groupId>org.apache.dolphinscheduler</groupId>
+                <artifactId>dolphinscheduler-alert-webexteams</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.apache.dolphinscheduler</groupId>
                 <artifactId>dolphinscheduler-registry-api</artifactId>
                 <version>${project.version}</version>
             </dependency>