diff --git a/.github/workflows/ci_backend.yml b/.github/workflows/ci_backend.yml index c24a3ecf07..7b245d77ef 100644 --- a/.github/workflows/ci_backend.yml +++ b/.github/workflows/ci_backend.yml @@ -46,18 +46,14 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - # In the checkout@v2, it doesn't support git submodule. Execute the commands manually. - - name: checkout submodules - shell: bash - run: | - git submodule sync --recursive - git -c protocol.version=2 submodule update --init --force --recursive --depth=1 + with: + submodule: true + - name: Check License Header + uses: apache/skywalking-eyes@9bd5feb - name: Set up JDK 1.8 uses: actions/setup-java@v1 with: java-version: 1.8 - - name: Check license - run: ./mvnw -B apache-rat:check - name: Compile run: mvn -B clean compile install -Prelease -Dmaven.test.skip=true - name: Check dependency license diff --git a/.github/workflows/ci_e2e.yml b/.github/workflows/ci_e2e.yml index 8070d7e0c5..3e781056d0 100644 --- a/.github/workflows/ci_e2e.yml +++ b/.github/workflows/ci_e2e.yml @@ -30,12 +30,10 @@ jobs: steps: - uses: actions/checkout@v2 - # In the checkout@v2, it doesn't support git submodule. Execute the commands manually. - - name: checkout submodules - shell: bash - run: | - git submodule sync --recursive - git -c protocol.version=2 submodule update --init --force --recursive --depth=1 + with: + submodule: true + - name: Check License Header + uses: apache/skywalking-eyes@9bd5feb - uses: actions/cache@v1 with: path: ~/.m2/repository diff --git a/.github/workflows/ci_frontend.yml b/.github/workflows/ci_frontend.yml index 1feaabaeb3..afa0c8d672 100644 --- a/.github/workflows/ci_frontend.yml +++ b/.github/workflows/ci_frontend.yml @@ -35,12 +35,8 @@ jobs: os: [ubuntu-latest, macos-latest] steps: - uses: actions/checkout@v2 - # In the checkout@v2, it doesn't support git submodule. Execute the commands manually. - - name: checkout submodules - shell: bash - run: | - git submodule sync --recursive - git -c protocol.version=2 submodule update --init --force --recursive --depth=1 + with: + submodule: true - name: Set up Node.js uses: actions/setup-node@v1 with: @@ -52,19 +48,3 @@ jobs: npm install npm run lint npm run build - License-check: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - # In the checkout@v2, it doesn't support git submodule. Execute the commands manually. - - name: checkout submodules - shell: bash - run: | - git submodule sync --recursive - git -c protocol.version=2 submodule update --init --force --recursive --depth=1 - - name: Set up JDK 1.8 - uses: actions/setup-java@v1 - with: - java-version: 1.8 - - name: Check - run: mvn -B apache-rat:check \ No newline at end of file diff --git a/.github/workflows/ci_ut.yml b/.github/workflows/ci_ut.yml index 739c9be7fa..09542d97f1 100644 --- a/.github/workflows/ci_ut.yml +++ b/.github/workflows/ci_ut.yml @@ -33,12 +33,12 @@ jobs: steps: - uses: actions/checkout@v2 - # In the checkout@v2, it doesn't support git submodule. Execute the commands manually. - - name: checkout submodules - shell: bash - run: | - git submodule sync --recursive - git -c protocol.version=2 submodule update --init --force --recursive --depth=1 + with: + submodule: true + - name: Check License Header + uses: apache/skywalking-eyes@9bd5feb + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Only enable review / suggestion here - uses: actions/cache@v1 with: path: ~/.m2/repository @@ -98,12 +98,8 @@ jobs: steps: - name: Checkout uses: actions/checkout@v2 - # In the checkout@v2, it doesn't support git submodule. Execute the commands manually. - - name: checkout submodules - shell: bash - run: | - git submodule sync --recursive - git -c protocol.version=2 submodule update --init --force --recursive --depth=1 + with: + submodule: true - name: check code style env: WORKDIR: ./ @@ -117,4 +113,4 @@ jobs: | /opt/reviewdog -f=checkstyle \ -reporter="${INPUT_REPORTER:-github-pr-check}" \ -filter-mode="${INPUT_FILTER_MODE:-added}" \ - -fail-on-error="${INPUT_FAIL_ON_ERROR:-false}" \ No newline at end of file + -fail-on-error="${INPUT_FAIL_ON_ERROR:-false}" diff --git a/.licenserc.yaml b/.licenserc.yaml new file mode 100644 index 0000000000..ea6909e240 --- /dev/null +++ b/.licenserc.yaml @@ -0,0 +1,43 @@ +# Licensed to 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. Apache Software Foundation (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. + +header: + license: + spdx-id: Apache-2.0 + copyright-owner: Apache Software Foundation + + paths-ignore: + - dist + - NOTICE + - LICENSE + - DISCLAIMER + - dolphinscheduler-common/src/main/java/org/apache/dolphinscheduler/common/utils/ScriptRunner.java + - mvnw.cmd + - sql/soft_version + - .mvn + - .gitattributes + - '**/licenses/**/LICENSE-*' + - '**/*.md' + - '**/*.json' + - '**/*.iml' + - '**/.babelrc' + - '**/.eslintignore' + - '**/.gitignore' + - '**/LICENSE' + - '**/NOTICE' + + comment: on-failure diff --git a/DISCLAIMER b/DISCLAIMER index 1c269cd696..7abee7c705 100644 --- a/DISCLAIMER +++ b/DISCLAIMER @@ -1,4 +1,4 @@ -Apache DolphinScheduler (incubating) is an effort undergoing incubation at The Apache Software Foundation (ASF), sponsored by the Apache Incubator PMC. +Apache DolphinScheduler is an effort undergoing incubation at The Apache Software Foundation (ASF), sponsored by the Apache Incubator. Incubation is required of all newly accepted projects until a further review indicates that the infrastructure, communications, and decision making process have stabilized in a manner consistent with other successful ASF projects. While incubation status is not necessarily a reflection of the completeness or stability of the code, diff --git a/LICENSE b/LICENSE index 9a0c6aa66a..5d7c9f4cf7 100644 --- a/LICENSE +++ b/LICENSE @@ -216,3 +216,7 @@ The text of each license is the standard Apache 2.0 license. ScriptRunner from https://github.com/mybatis/mybatis-3 Apache 2.0 mvnw files from https://github.com/takari/maven-wrapper Apache 2.0 PropertyPlaceholderHelper from https://github.com/spring-projects/spring-framework Apache 2.0 + DolphinPluginClassLoader from https://github.com/prestosql/presto Apache 2.0 + DolphinPluginDiscovery from https://github.com/prestosql/presto Apache 2.0 + DolphinPluginLoader from https://github.com/prestosql/presto Apache 2.0 + diff --git a/NOTICE b/NOTICE index 3e5695849b..702a09cc63 100644 --- a/NOTICE +++ b/NOTICE @@ -1,5 +1,5 @@ Apache DolphinScheduler (incubating) -Copyright 2019-2020 The Apache Software Foundation +Copyright 2019-2021 The Apache Software Foundation This product includes software developed at The Apache Software Foundation (http://www.apache.org/). diff --git a/docker/build/hooks/build b/docker/build/hooks/build index 3276f167c4..6362fdd299 100644 --- a/docker/build/hooks/build +++ b/docker/build/hooks/build @@ -24,7 +24,8 @@ printenv if [ -z "${VERSION}" ] then echo "set default environment variable [VERSION]" - export VERSION=$(cat $(pwd)/pom.xml | grep '' -m 1 | awk '{print $1}' | sed 's///' | sed 's/<\/version>//') + VERSION=$(grep '' -m 1 "$(pwd)"/pom.xml | awk '{print $1}' | sed 's///' | sed 's/<\/version>//') + export VERSION fi if [ "${DOCKER_REPO}x" = "x" ] @@ -44,10 +45,10 @@ mvn -B clean compile package -Prelease -Dmaven.test.skip=true # mv dolphinscheduler-bin.tar.gz file to docker/build directory echo -e "mv $(pwd)/dolphinscheduler-dist/target/apache-dolphinscheduler-incubating-${VERSION}-dolphinscheduler-bin.tar.gz $(pwd)/docker/build/\n" -mv $(pwd)/dolphinscheduler-dist/target/apache-dolphinscheduler-incubating-${VERSION}-dolphinscheduler-bin.tar.gz $(pwd)/docker/build/ +mv "$(pwd)"/dolphinscheduler-dist/target/apache-dolphinscheduler-incubating-"${VERSION}"-dolphinscheduler-bin.tar.gz $(pwd)/docker/build/ # docker build echo -e "docker build --build-arg VERSION=${VERSION} -t $DOCKER_REPO:${VERSION} $(pwd)/docker/build/\n" -sudo docker build --build-arg VERSION=${VERSION} -t $DOCKER_REPO:${VERSION} $(pwd)/docker/build/ +sudo docker build --build-arg VERSION="${VERSION}" -t $DOCKER_REPO:"${VERSION}" "$(pwd)/docker/build/" echo "------ dolphinscheduler end - build -------" diff --git a/docker/build/hooks/push b/docker/build/hooks/push index 41a25c54fe..74ea06d5c5 100644 --- a/docker/build/hooks/push +++ b/docker/build/hooks/push @@ -19,6 +19,6 @@ echo "------ push start -------" printenv -docker push $DOCKER_REPO:${VERSION} +docker push "$DOCKER_REPO:${VERSION}" echo "------ push end -------" diff --git a/docker/kubernetes/dolphinscheduler/requirements.yaml~HEAD b/docker/kubernetes/dolphinscheduler/requirements.yaml~HEAD new file mode 100644 index 0000000000..e219975995 --- /dev/null +++ b/docker/kubernetes/dolphinscheduler/requirements.yaml~HEAD @@ -0,0 +1,25 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +dependencies: +- name: postgresql + version: 8.x.x + repository: https://charts.bitnami.com/bitnami + condition: postgresql.enabled +- name: zookeeper + version: 5.x.x + repository: https://charts.bitnami.com/bitnami + condition: redis.enabled \ No newline at end of file diff --git a/docker/kubernetes/dolphinscheduler/requirements.yaml~HEAD_0 b/docker/kubernetes/dolphinscheduler/requirements.yaml~HEAD_0 new file mode 100644 index 0000000000..e219975995 --- /dev/null +++ b/docker/kubernetes/dolphinscheduler/requirements.yaml~HEAD_0 @@ -0,0 +1,25 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +dependencies: +- name: postgresql + version: 8.x.x + repository: https://charts.bitnami.com/bitnami + condition: postgresql.enabled +- name: zookeeper + version: 5.x.x + repository: https://charts.bitnami.com/bitnami + condition: redis.enabled \ No newline at end of file diff --git a/docker/kubernetes/dolphinscheduler/requirements.yaml~dev b/docker/kubernetes/dolphinscheduler/requirements.yaml~dev new file mode 100644 index 0000000000..e219975995 --- /dev/null +++ b/docker/kubernetes/dolphinscheduler/requirements.yaml~dev @@ -0,0 +1,25 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +dependencies: +- name: postgresql + version: 8.x.x + repository: https://charts.bitnami.com/bitnami + condition: postgresql.enabled +- name: zookeeper + version: 5.x.x + repository: https://charts.bitnami.com/bitnami + condition: redis.enabled \ No newline at end of file diff --git a/docker/kubernetes/dolphinscheduler/requirements.yaml~dev_0 b/docker/kubernetes/dolphinscheduler/requirements.yaml~dev_0 new file mode 100644 index 0000000000..e219975995 --- /dev/null +++ b/docker/kubernetes/dolphinscheduler/requirements.yaml~dev_0 @@ -0,0 +1,25 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +dependencies: +- name: postgresql + version: 8.x.x + repository: https://charts.bitnami.com/bitnami + condition: postgresql.enabled +- name: zookeeper + version: 5.x.x + repository: https://charts.bitnami.com/bitnami + condition: redis.enabled \ No newline at end of file diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-dingtalk/pom.xml b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-dingtalk/pom.xml new file mode 100644 index 0000000000..930b92f855 --- /dev/null +++ b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-dingtalk/pom.xml @@ -0,0 +1,82 @@ + + + + + dolphinscheduler-alert-plugin + org.apache.dolphinscheduler + 1.3.4-SNAPSHOT + + 4.0.0 + + org.apache.dolphinscheduler + dolphinscheduler-alert-dingtalk + dolphinscheduler-plugin + + + + + org.apache.dolphinscheduler + dolphinscheduler-spi + provided + + + org.apache.httpcomponents + httpclient + + + com.google.guava + guava + + + + ch.qos.logback + logback-classic + + + + org.slf4j + slf4j-api + + + + com.fasterxml.jackson.core + jackson-annotations + provided + + + + junit + junit + test + + + + org.mockito + mockito-core + jar + test + + + + + dolphinscheduler-alert-dingtalk-${project.version} + + + \ No newline at end of file diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-dingtalk/src/main/java/org/apache/dolphinscheduler/plugin/alert/dingtalk/DingTalkAlertChannel.java b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-dingtalk/src/main/java/org/apache/dolphinscheduler/plugin/alert/dingtalk/DingTalkAlertChannel.java new file mode 100644 index 0000000000..7adfacce39 --- /dev/null +++ b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-dingtalk/src/main/java/org/apache/dolphinscheduler/plugin/alert/dingtalk/DingTalkAlertChannel.java @@ -0,0 +1,41 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.dolphinscheduler.plugin.alert.dingtalk; + +import org.apache.dolphinscheduler.spi.alert.AlertChannel; +import org.apache.dolphinscheduler.spi.alert.AlertData; +import org.apache.dolphinscheduler.spi.alert.AlertInfo; +import org.apache.dolphinscheduler.spi.alert.AlertResult; +import org.apache.dolphinscheduler.spi.params.PluginParamsTransfer; + +import java.util.Map; + +/** + * DingTalkAlertChannel + */ +public class DingTalkAlertChannel implements AlertChannel { + + @Override + public AlertResult process(AlertInfo alertInfo) { + + AlertData alertData = alertInfo.getAlertData(); + String alertParams = alertInfo.getAlertParams(); + Map paramsMap = PluginParamsTransfer.getPluginParamsMap(alertParams); + return new DingTalkSender(paramsMap).sendDingTalkMsg(alertData.getTitle(), alertData.getContent()); + } +} diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-dingtalk/src/main/java/org/apache/dolphinscheduler/plugin/alert/dingtalk/DingTalkAlertChannelFactory.java b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-dingtalk/src/main/java/org/apache/dolphinscheduler/plugin/alert/dingtalk/DingTalkAlertChannelFactory.java new file mode 100644 index 0000000000..0a6851a4ac --- /dev/null +++ b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-dingtalk/src/main/java/org/apache/dolphinscheduler/plugin/alert/dingtalk/DingTalkAlertChannelFactory.java @@ -0,0 +1,89 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.dolphinscheduler.plugin.alert.dingtalk; + +import org.apache.dolphinscheduler.spi.alert.AlertChannel; +import org.apache.dolphinscheduler.spi.alert.AlertChannelFactory; +import org.apache.dolphinscheduler.spi.params.InputParam; +import org.apache.dolphinscheduler.spi.params.PasswordParam; +import org.apache.dolphinscheduler.spi.params.RadioParam; +import org.apache.dolphinscheduler.spi.params.base.ParamsOptions; +import org.apache.dolphinscheduler.spi.params.base.PluginParams; +import org.apache.dolphinscheduler.spi.params.base.Validate; + +import java.util.Arrays; +import java.util.List; + +/** + * DingTalkAlertChannelFactory + */ +public class DingTalkAlertChannelFactory implements AlertChannelFactory { + @Override + public String getName() { + return "DingTalk"; + } + + @Override + public List getParams() { + InputParam webHookParam = InputParam.newBuilder(DingTalkParamsConstants.NAME_DING_TALK_WEB_HOOK, DingTalkParamsConstants.DING_TALK_WEB_HOOK) + .addValidate(Validate.newBuilder() + .setRequired(true) + .build()) + .build(); + InputParam keywordParam = InputParam.newBuilder(DingTalkParamsConstants.NAME_DING_TALK_KEYWORD, DingTalkParamsConstants.DING_TALK_KEYWORD) + .addValidate(Validate.newBuilder() + .setRequired(true) + .build()) + .build(); + RadioParam isEnableProxy = + RadioParam.newBuilder(DingTalkParamsConstants.NAME_DING_TALK_PROXY_ENABLE, DingTalkParamsConstants.NAME_DING_TALK_PROXY_ENABLE) + .addParamsOptions(new ParamsOptions("YES", true, false)) + .addParamsOptions(new ParamsOptions("NO", false, false)) + .setValue(true) + .addValidate(Validate.newBuilder() + .setRequired(false) + .build()) + .build(); + InputParam proxyParam = + InputParam.newBuilder(DingTalkParamsConstants.NAME_DING_TALK_PROXY, DingTalkParamsConstants.DING_TALK_PROXY) + .addValidate(Validate.newBuilder() + .setRequired(false).build()) + .build(); + + InputParam portParam = InputParam.newBuilder(DingTalkParamsConstants.NAME_DING_TALK_PORT, DingTalkParamsConstants.DING_TALK_PORT) + .addValidate(Validate.newBuilder() + .setRequired(false).build()) + .build(); + + InputParam userParam = + InputParam.newBuilder(DingTalkParamsConstants.NAME_DING_TALK_USER, DingTalkParamsConstants.DING_TALK_USER) + .addValidate(Validate.newBuilder() + .setRequired(false).build()) + .build(); + PasswordParam passwordParam = PasswordParam.newBuilder(DingTalkParamsConstants.NAME_DING_TALK_PASSWORD, DingTalkParamsConstants.DING_TALK_PASSWORD) + .setPlaceholder("if enable use authentication, you need input password") + .build(); + + return Arrays.asList(webHookParam, keywordParam, isEnableProxy, proxyParam, portParam, userParam, passwordParam); + } + + @Override + public AlertChannel create() { + return new DingTalkAlertChannel(); + } +} diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-dingtalk/src/main/java/org/apache/dolphinscheduler/plugin/alert/dingtalk/DingTalkAlertPlugin.java b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-dingtalk/src/main/java/org/apache/dolphinscheduler/plugin/alert/dingtalk/DingTalkAlertPlugin.java new file mode 100644 index 0000000000..2d15f499c9 --- /dev/null +++ b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-dingtalk/src/main/java/org/apache/dolphinscheduler/plugin/alert/dingtalk/DingTalkAlertPlugin.java @@ -0,0 +1,34 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.dolphinscheduler.plugin.alert.dingtalk; + +import org.apache.dolphinscheduler.spi.DolphinSchedulerPlugin; +import org.apache.dolphinscheduler.spi.alert.AlertChannelFactory; + +import com.google.common.collect.ImmutableList; + +/** + * DingTalkAlertPlugin + */ +public class DingTalkAlertPlugin implements DolphinSchedulerPlugin { + + @Override + public Iterable getAlertChannelFactorys() { + return ImmutableList.of(new DingTalkAlertChannelFactory()); + } +} diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-dingtalk/src/main/java/org/apache/dolphinscheduler/plugin/alert/dingtalk/DingTalkParamsConstants.java b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-dingtalk/src/main/java/org/apache/dolphinscheduler/plugin/alert/dingtalk/DingTalkParamsConstants.java new file mode 100644 index 0000000000..fb9f5f9f5d --- /dev/null +++ b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-dingtalk/src/main/java/org/apache/dolphinscheduler/plugin/alert/dingtalk/DingTalkParamsConstants.java @@ -0,0 +1,57 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.dolphinscheduler.plugin.alert.dingtalk; + +/** + * DingTalkParamsConstants + */ +public class DingTalkParamsConstants { + + public DingTalkParamsConstants() { + throw new IllegalStateException("Utility class"); + } + + static final String DING_TALK_WEB_HOOK = "dingtalk.webhook"; + + static final String NAME_DING_TALK_WEB_HOOK = "dingTalkWebHook"; + + static final String DING_TALK_KEYWORD = "dingtalk.keyword"; + + static final String NAME_DING_TALK_KEYWORD = "dingTalkKeyword"; + + public static final String DING_TALK_PROXY_ENABLE = "dingtalk.isEnableProxy"; + + static final String NAME_DING_TALK_PROXY_ENABLE = "dingTalkIsEnableProxy"; + + static final String DING_TALK_PROXY = "dingtalk.proxy"; + + static final String NAME_DING_TALK_PROXY = "dingTalkProxy"; + + static final String DING_TALK_PORT = "dingtalk.port"; + + static final String NAME_DING_TALK_PORT = "dingTalkPort"; + + static final String DING_TALK_USER = "dingtalk.user"; + + static final String NAME_DING_TALK_USER = "dingTalkUser"; + + static final String DING_TALK_PASSWORD = "dingtalk.password"; + + static final String NAME_DING_TALK_PASSWORD = "dingTalkPassword"; + +} diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-dingtalk/src/main/java/org/apache/dolphinscheduler/plugin/alert/dingtalk/DingTalkSender.java b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-dingtalk/src/main/java/org/apache/dolphinscheduler/plugin/alert/dingtalk/DingTalkSender.java new file mode 100644 index 0000000000..4500f3e28e --- /dev/null +++ b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-dingtalk/src/main/java/org/apache/dolphinscheduler/plugin/alert/dingtalk/DingTalkSender.java @@ -0,0 +1,204 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.dolphinscheduler.plugin.alert.dingtalk; + +import org.apache.dolphinscheduler.spi.alert.AlertResult; +import org.apache.dolphinscheduler.spi.utils.JSONUtils; + +import org.apache.commons.codec.binary.StringUtils; +import org.apache.http.HttpEntity; +import org.apache.http.HttpHost; +import org.apache.http.auth.AuthScope; +import org.apache.http.auth.UsernamePasswordCredentials; +import org.apache.http.client.CredentialsProvider; +import org.apache.http.client.config.RequestConfig; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.entity.StringEntity; +import org.apache.http.impl.client.BasicCredentialsProvider; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.util.EntityUtils; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Ding Talk Sender + */ +public class DingTalkSender { + private static final Logger logger = LoggerFactory.getLogger(DingTalkSender.class); + + private String url; + + private String keyword; + + private Boolean enableProxy; + + private String proxy; + + private Integer port; + + private String user; + + private String password; + + DingTalkSender(Map config) { + url = config.get(DingTalkParamsConstants.NAME_DING_TALK_WEB_HOOK); + keyword = config.get(DingTalkParamsConstants.NAME_DING_TALK_KEYWORD); + enableProxy = Boolean.valueOf(config.get(DingTalkParamsConstants.NAME_DING_TALK_PROXY_ENABLE)); + if (Boolean.TRUE.equals(enableProxy)) { + port = Integer.parseInt(config.get(DingTalkParamsConstants.NAME_DING_TALK_PORT)); + proxy = config.get(DingTalkParamsConstants.NAME_DING_TALK_PROXY); + user = config.get(DingTalkParamsConstants.DING_TALK_USER); + password = config.get(DingTalkParamsConstants.NAME_DING_TALK_PASSWORD); + } + + } + + public AlertResult sendDingTalkMsg(String msg, String charset) { + AlertResult alertResult; + try { + String resp = sendMsg(msg, charset); + return checkSendDingTalkSendMsgResult(resp); + } catch (Exception e) { + logger.info("send ding talk alert msg exception : {}", e.getMessage()); + alertResult = new AlertResult(); + alertResult.setStatus("false"); + alertResult.setMessage("send ding talk alert fail."); + } + return alertResult; + } + + private String sendMsg(String msg, String charset) throws IOException { + + String msgToJson = textToJsonString(msg + "#" + keyword); + HttpPost httpPost = constructHttpPost(url, msgToJson, charset); + + CloseableHttpClient httpClient; + if (Boolean.TRUE.equals(enableProxy)) { + httpClient = getProxyClient(proxy, port, user, password); + RequestConfig rcf = getProxyConfig(proxy, port); + httpPost.setConfig(rcf); + } else { + httpClient = getDefaultClient(); + } + + try { + CloseableHttpResponse response = httpClient.execute(httpPost); + String resp; + try { + HttpEntity entity = response.getEntity(); + resp = EntityUtils.toString(entity, charset); + EntityUtils.consume(entity); + } finally { + response.close(); + } + logger.info("Ding Talk send [ %s ], resp:{%s}", msg, resp); + return resp; + } finally { + httpClient.close(); + } + } + + private static HttpPost constructHttpPost(String url, String msg, String charset) { + HttpPost post = new HttpPost(url); + StringEntity entity = new StringEntity(msg, charset); + post.setEntity(entity); + post.addHeader("Content-Type", "application/json; charset=utf-8"); + return post; + } + + private static CloseableHttpClient getProxyClient(String proxy, int port, String user, String password) { + HttpHost httpProxy = new HttpHost(proxy, port); + CredentialsProvider provider = new BasicCredentialsProvider(); + provider.setCredentials(new AuthScope(httpProxy), new UsernamePasswordCredentials(user, password)); + return HttpClients.custom().setDefaultCredentialsProvider(provider).build(); + } + + private static CloseableHttpClient getDefaultClient() { + return HttpClients.createDefault(); + } + + private static RequestConfig getProxyConfig(String proxy, int port) { + HttpHost httpProxy = new HttpHost(proxy, port); + return RequestConfig.custom().setProxy(httpProxy).build(); + } + + private static String textToJsonString(String text) { + Map items = new HashMap<>(); + items.put("msgtype", "text"); + Map textContent = new HashMap<>(); + byte[] byt = StringUtils.getBytesUtf8(text); + String txt = StringUtils.newStringUtf8(byt); + textContent.put("content", txt); + items.put("text", textContent); + return JSONUtils.toJsonString(items); + } + + public static class DingTalkSendMsgResponse { + private Integer errcode; + private String errmsg; + + public Integer getErrcode() { + return errcode; + } + + public void setErrcode(Integer errcode) { + this.errcode = errcode; + } + + public String getErrmsg() { + return errmsg; + } + + public void setErrmsg(String errmsg) { + this.errmsg = errmsg; + } + } + + private static AlertResult checkSendDingTalkSendMsgResult(String result) { + AlertResult alertResult = new AlertResult(); + alertResult.setStatus("false"); + + if (null == result) { + alertResult.setMessage("send ding talk msg error"); + logger.info("send ding talk msg error,ding talk server resp is null"); + return alertResult; + } + DingTalkSendMsgResponse sendMsgResponse = JSONUtils.parseObject(result, DingTalkSendMsgResponse.class); + if (null == sendMsgResponse) { + alertResult.setMessage("send ding talk msg fail"); + logger.info("send ding talk msg error,resp error"); + return alertResult; + } + if (sendMsgResponse.errcode == 0) { + alertResult.setStatus("true"); + alertResult.setMessage("send ding talk msg success"); + return alertResult; + } + alertResult.setMessage(String.format("alert send ding talk msg error : %s", sendMsgResponse.getErrmsg())); + logger.info("alert send ding talk msg error : {}", sendMsgResponse.getErrmsg()); + return alertResult; + } + +} diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-dingtalk/src/test/java/org/apache/dolphinscheduler/plugin/alert/dingtalk/DingTalkAlertChannelFactoryTest.java b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-dingtalk/src/test/java/org/apache/dolphinscheduler/plugin/alert/dingtalk/DingTalkAlertChannelFactoryTest.java new file mode 100644 index 0000000000..2a26daad63 --- /dev/null +++ b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-dingtalk/src/test/java/org/apache/dolphinscheduler/plugin/alert/dingtalk/DingTalkAlertChannelFactoryTest.java @@ -0,0 +1,48 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.dolphinscheduler.plugin.alert.dingtalk; + +import org.apache.dolphinscheduler.spi.alert.AlertChannel; +import org.apache.dolphinscheduler.spi.params.base.PluginParams; +import org.apache.dolphinscheduler.spi.utils.JSONUtils; + +import java.util.List; + +import org.junit.Assert; +import org.junit.Test; + +/** + * DingTalkAlertChannelFactoryTest + */ +public class DingTalkAlertChannelFactoryTest { + + @Test + public void testGetParams() { + DingTalkAlertChannelFactory dingTalkAlertChannelFactory = new DingTalkAlertChannelFactory(); + List params = dingTalkAlertChannelFactory.getParams(); + JSONUtils.toJsonString(params); + Assert.assertEquals(7, params.size()); + } + + @Test + public void testCreate() { + DingTalkAlertChannelFactory dingTalkAlertChannelFactory = new DingTalkAlertChannelFactory(); + AlertChannel alertChannel = dingTalkAlertChannelFactory.create(); + Assert.assertNotNull(alertChannel); + } +} diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-dingtalk/src/test/java/org/apache/dolphinscheduler/plugin/alert/dingtalk/DingTalkSenderTest.java b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-dingtalk/src/test/java/org/apache/dolphinscheduler/plugin/alert/dingtalk/DingTalkSenderTest.java new file mode 100644 index 0000000000..4512402dc4 --- /dev/null +++ b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-dingtalk/src/test/java/org/apache/dolphinscheduler/plugin/alert/dingtalk/DingTalkSenderTest.java @@ -0,0 +1,57 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.dolphinscheduler.plugin.alert.dingtalk; + +import org.apache.dolphinscheduler.spi.alert.AlertResult; + +import java.util.HashMap; +import java.util.Map; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +/** + * DingTalkSenderTest + */ +public class DingTalkSenderTest { + + private static Map dingTalkConfig = new HashMap<>(); + + @Before + public void initDingTalkConfig() { + + dingTalkConfig.put(DingTalkParamsConstants.NAME_DING_TALK_KEYWORD, "keyWord"); + dingTalkConfig.put(DingTalkParamsConstants.NAME_DING_TALK_WEB_HOOK, "url"); + dingTalkConfig.put(DingTalkParamsConstants.NAME_DING_TALK_PROXY_ENABLE, "false"); + dingTalkConfig.put(DingTalkParamsConstants.NAME_DING_TALK_PASSWORD, "password"); + dingTalkConfig.put(DingTalkParamsConstants.NAME_DING_TALK_PORT, "9988"); + dingTalkConfig.put(DingTalkParamsConstants.NAME_DING_TALK_USER, "user1,user2"); + } + + @Test + public void testSend() { + DingTalkSender dingTalkSender = new DingTalkSender(dingTalkConfig); + dingTalkSender.sendDingTalkMsg("keyWord+Welcome", "UTF-8"); + dingTalkConfig.put(DingTalkParamsConstants.NAME_DING_TALK_PROXY_ENABLE, "true"); + dingTalkSender = new DingTalkSender(dingTalkConfig); + AlertResult alertResult = dingTalkSender.sendDingTalkMsg("keyWord+Welcome", "UTF-8"); + Assert.assertEquals("false",alertResult.getStatus()); + } + +} diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-email/pom.xml b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-email/pom.xml new file mode 100644 index 0000000000..f4524b2046 --- /dev/null +++ b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-email/pom.xml @@ -0,0 +1,128 @@ + + + + + dolphinscheduler-alert-plugin + org.apache.dolphinscheduler + 1.3.4-SNAPSHOT + + 4.0.0 + + org.apache.dolphinscheduler + dolphinscheduler-alert-email + + dolphinscheduler-plugin + + + + org.apache.dolphinscheduler + dolphinscheduler-spi + provided + + + + com.fasterxml.jackson.core + jackson-annotations + provided + + + com.fasterxml.jackson.core + jackson-databind + provided + + + org.apache.commons + commons-collections4 + + + + org.apache.poi + poi + + + + com.google.guava + guava + + + + ch.qos.logback + logback-classic + + + + org.slf4j + slf4j-api + + + + org.apache.commons + commons-email + + + + com.fasterxml.jackson.core + jackson-annotations + provided + + + + com.fasterxml.jackson.core + jackson-databind + provided + + + + junit + junit + test + + + + org.mockito + mockito-core + jar + test + + + + org.powermock + powermock-module-junit4 + test + + + + org.powermock + powermock-api-mockito2 + test + + + org.mockito + mockito-core + + + + + + + dolphinscheduler-alert-email-${project.version} + + + \ No newline at end of file diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-email/src/main/java/org/apache/dolphinscheduler/plugin/alert/email/EmailAlertChannel.java b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-email/src/main/java/org/apache/dolphinscheduler/plugin/alert/email/EmailAlertChannel.java new file mode 100644 index 0000000000..c793af5710 --- /dev/null +++ b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-email/src/main/java/org/apache/dolphinscheduler/plugin/alert/email/EmailAlertChannel.java @@ -0,0 +1,69 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.dolphinscheduler.plugin.alert.email; + +import org.apache.dolphinscheduler.spi.alert.AlertChannel; +import org.apache.dolphinscheduler.spi.alert.AlertData; +import org.apache.dolphinscheduler.spi.alert.AlertInfo; +import org.apache.dolphinscheduler.spi.alert.AlertResult; +import org.apache.dolphinscheduler.spi.params.PluginParamsTransfer; + +import java.util.Map; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * email alert channel . use email to seed the alertInfo + */ +public class EmailAlertChannel implements AlertChannel { + private static final Logger logger = LoggerFactory.getLogger(EmailAlertChannel.class); + + @Override + public AlertResult process(AlertInfo info) { + + AlertData alert = info.getAlertData(); + String alertParams = info.getAlertParams(); + Map paramsMap = PluginParamsTransfer.getPluginParamsMap(alertParams); + MailSender mailSender = new MailSender(paramsMap); + AlertResult alertResult = mailSender.sendMails(alert.getTitle(), alert.getContent()); + + //send flag + boolean flag = false; + + if (alertResult == null) { + alertResult = new AlertResult(); + alertResult.setStatus("false"); + alertResult.setMessage("alert send error."); + logger.info("alert send error : {}", alertResult.getMessage()); + return alertResult; + } + + flag = Boolean.parseBoolean(String.valueOf(alertResult.getStatus())); + + if (flag) { + logger.info("alert send success"); + alertResult.setMessage("email send success."); + } else { + alertResult.setMessage("alert send error."); + logger.info("alert send error : {}", alertResult.getMessage()); + } + + return alertResult; + } +} diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-email/src/main/java/org/apache/dolphinscheduler/plugin/alert/email/EmailAlertChannelFactory.java b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-email/src/main/java/org/apache/dolphinscheduler/plugin/alert/email/EmailAlertChannelFactory.java new file mode 100644 index 0000000000..f8aa17fca3 --- /dev/null +++ b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-email/src/main/java/org/apache/dolphinscheduler/plugin/alert/email/EmailAlertChannelFactory.java @@ -0,0 +1,137 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.dolphinscheduler.plugin.alert.email; + +import org.apache.dolphinscheduler.spi.alert.AlertChannel; +import org.apache.dolphinscheduler.spi.alert.AlertChannelFactory; +import org.apache.dolphinscheduler.spi.alert.AlertConstants; +import org.apache.dolphinscheduler.spi.alert.ShowType; +import org.apache.dolphinscheduler.spi.params.InputParam; +import org.apache.dolphinscheduler.spi.params.PasswordParam; +import org.apache.dolphinscheduler.spi.params.RadioParam; +import org.apache.dolphinscheduler.spi.params.base.DataType; +import org.apache.dolphinscheduler.spi.params.base.ParamsOptions; +import org.apache.dolphinscheduler.spi.params.base.PluginParams; +import org.apache.dolphinscheduler.spi.params.base.Validate; + +import java.util.ArrayList; +import java.util.List; + +/** + * email alert factory + */ +public class EmailAlertChannelFactory implements AlertChannelFactory { + @Override + public String getName() { + return "Email"; + } + + @Override + public List getParams() { + + List paramsList = new ArrayList<>(); + InputParam receivesParam = InputParam.newBuilder(MailParamsConstants.NAME_PLUGIN_DEFAULT_EMAIL_RECEIVERS, MailParamsConstants.PLUGIN_DEFAULT_EMAIL_RECEIVERS) + .setPlaceholder("please input receives") + .addValidate(Validate.newBuilder() + .setRequired(true) + .build()) + .build(); + + InputParam receiveCcsParam = InputParam.newBuilder(MailParamsConstants.NAME_PLUGIN_DEFAULT_EMAIL_RECEIVERCCS, MailParamsConstants.PLUGIN_DEFAULT_EMAIL_RECEIVERCCS) + .build(); + + InputParam mailSmtpHost = InputParam.newBuilder(MailParamsConstants.NAME_MAIL_SMTP_HOST, MailParamsConstants.MAIL_SMTP_HOST) + .addValidate(Validate.newBuilder().setRequired(true).build()) + .build(); + + InputParam mailSmtpPort = InputParam.newBuilder(MailParamsConstants.NAME_MAIL_SMTP_PORT, MailParamsConstants.MAIL_SMTP_PORT) + .setValue(25) + .addValidate(Validate.newBuilder() + .setRequired(true) + .setType(DataType.NUMBER.getDataType()) + .build()) + .build(); + + InputParam mailSender = InputParam.newBuilder(MailParamsConstants.NAME_MAIL_SENDER, MailParamsConstants.MAIL_SENDER) + .addValidate(Validate.newBuilder().setRequired(true).build()) + .build(); + + RadioParam enableSmtpAuth = RadioParam.newBuilder(MailParamsConstants.NAME_MAIL_SMTP_AUTH, MailParamsConstants.MAIL_SMTP_AUTH) + .addParamsOptions(new ParamsOptions("YES", true, false)) + .addParamsOptions(new ParamsOptions("NO", false, false)) + .setValue(true) + .addValidate(Validate.newBuilder().setRequired(true).build()) + .build(); + + InputParam mailUser = InputParam.newBuilder(MailParamsConstants.NAME_MAIL_USER, MailParamsConstants.MAIL_USER) + .setPlaceholder("if enable use authentication, you need input user") + .build(); + + PasswordParam mailPassword = PasswordParam.newBuilder(MailParamsConstants.NAME_MAIL_PASSWD, MailParamsConstants.MAIL_PASSWD) + .setPlaceholder("if enable use authentication, you need input password") + .build(); + + RadioParam enableTls = RadioParam.newBuilder(MailParamsConstants.NAME_MAIL_SMTP_STARTTLS_ENABLE, MailParamsConstants.MAIL_SMTP_STARTTLS_ENABLE) + .addParamsOptions(new ParamsOptions("YES", true, false)) + .addParamsOptions(new ParamsOptions("NO", false, false)) + .setValue(false) + .addValidate(Validate.newBuilder().setRequired(true).build()) + .build(); + + RadioParam enableSsl = RadioParam.newBuilder(MailParamsConstants.NAME_MAIL_SMTP_SSL_ENABLE, MailParamsConstants.MAIL_SMTP_SSL_ENABLE) + .addParamsOptions(new ParamsOptions("YES", true, false)) + .addParamsOptions(new ParamsOptions("NO", false, false)) + .setValue(false) + .addValidate(Validate.newBuilder().setRequired(true).build()) + .build(); + + InputParam sslTrust = InputParam.newBuilder(MailParamsConstants.NAME_MAIL_SMTP_SSL_TRUST, MailParamsConstants.MAIL_SMTP_SSL_TRUST) + .setValue("*") + .addValidate(Validate.newBuilder().setRequired(true).build()) + .build(); + + RadioParam showType = RadioParam.newBuilder(AlertConstants.SHOW_TYPE, AlertConstants.SHOW_TYPE) + .addParamsOptions(new ParamsOptions(ShowType.TABLE.getDescp(), ShowType.TABLE.getDescp(), false)) + .addParamsOptions(new ParamsOptions(ShowType.TEXT.getDescp(), ShowType.TEXT.getDescp(), false)) + .addParamsOptions(new ParamsOptions(ShowType.ATTACHMENT.getDescp(), ShowType.ATTACHMENT.getDescp(), false)) + .addParamsOptions(new ParamsOptions(ShowType.TABLEATTACHMENT.getDescp(), ShowType.TABLEATTACHMENT.getDescp(), false)) + .setValue(ShowType.TABLE.getDescp()) + .addValidate(Validate.newBuilder().setRequired(true).build()) + .build(); + + paramsList.add(receivesParam); + paramsList.add(receiveCcsParam); + paramsList.add(mailSmtpHost); + paramsList.add(mailSmtpPort); + paramsList.add(mailSender); + paramsList.add(enableSmtpAuth); + paramsList.add(mailUser); + paramsList.add(mailPassword); + paramsList.add(enableTls); + paramsList.add(enableSsl); + paramsList.add(sslTrust); + paramsList.add(showType); + + return paramsList; + } + + @Override + public AlertChannel create() { + return new EmailAlertChannel(); + } +} diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-email/src/main/java/org/apache/dolphinscheduler/plugin/alert/email/EmailAlertPlugin.java b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-email/src/main/java/org/apache/dolphinscheduler/plugin/alert/email/EmailAlertPlugin.java new file mode 100644 index 0000000000..175b518189 --- /dev/null +++ b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-email/src/main/java/org/apache/dolphinscheduler/plugin/alert/email/EmailAlertPlugin.java @@ -0,0 +1,33 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.dolphinscheduler.plugin.alert.email; + +import org.apache.dolphinscheduler.spi.DolphinSchedulerPlugin; +import org.apache.dolphinscheduler.spi.alert.AlertChannelFactory; + +import com.google.common.collect.ImmutableList; + +/** + * email alert plugin + */ +public class EmailAlertPlugin implements DolphinSchedulerPlugin { + @Override + public Iterable getAlertChannelFactorys() { + return ImmutableList.of(new EmailAlertChannelFactory()); + } +} diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-email/src/main/java/org/apache/dolphinscheduler/plugin/alert/email/EmailConstants.java b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-email/src/main/java/org/apache/dolphinscheduler/plugin/alert/email/EmailConstants.java new file mode 100644 index 0000000000..d0e85ffb03 --- /dev/null +++ b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-email/src/main/java/org/apache/dolphinscheduler/plugin/alert/email/EmailConstants.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.email; + +public class EmailConstants { + + + public static final String XLS_FILE_PATH = "xls.file.path"; + + public static final String MAIL_TRANSPORT_PROTOCOL = "mail.transport.protocol"; + + public static final String DEFAULT_SMTP_PORT = "25"; + + public static final String TEXT_HTML_CHARSET_UTF_8 = "text/html;charset=utf-8"; + + public static final int NUMBER_1000 = 1000; + + public static final String TR = ""; + + public static final String TD = ""; + + public static final String TD_END = ""; + + public static final String TR_END = ""; + + public static final String TITLE = "title"; + + public static final String CONTENT = "content"; + + public static final String TH = ""; + + public static final String TH_END = ""; + + public static final String MARKDOWN_QUOTE = ">"; + + public static final String MARKDOWN_ENTER = "\n"; + + public static final String HTML_HEADER_PREFIX = new StringBuilder("") + .append("") + .append("") + .append("dolphinscheduler") + .append("") + .append("") + .append("") + .append("") + .append(" ") + .toString(); + + public static final String TABLE_BODY_HTML_TAIL = "
"; + + public static final String UTF_8 = "UTF-8"; + + public static final String EXCEL_SUFFIX_XLS = ".xls"; + + public static final String SINGLE_SLASH = "/"; +} diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-email/src/main/java/org/apache/dolphinscheduler/plugin/alert/email/ExcelUtils.java b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-email/src/main/java/org/apache/dolphinscheduler/plugin/alert/email/ExcelUtils.java new file mode 100644 index 0000000000..1579f9548e --- /dev/null +++ b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-email/src/main/java/org/apache/dolphinscheduler/plugin/alert/email/ExcelUtils.java @@ -0,0 +1,153 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.dolphinscheduler.plugin.alert.email; + +import org.apache.dolphinscheduler.spi.utils.JSONUtils; + +import org.apache.commons.collections4.CollectionUtils; +import org.apache.poi.hssf.usermodel.HSSFCell; +import org.apache.poi.hssf.usermodel.HSSFRow; +import org.apache.poi.hssf.usermodel.HSSFSheet; +import org.apache.poi.hssf.usermodel.HSSFWorkbook; +import org.apache.poi.ss.usermodel.CellStyle; +import org.apache.poi.ss.usermodel.HorizontalAlignment; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * excel utils + */ +public class ExcelUtils { + + public ExcelUtils() { + throw new IllegalStateException("Utility class"); + } + + private static final Logger logger = LoggerFactory.getLogger(ExcelUtils.class); + + /** + * generate excel file + * + * @param content the content + * @param title the title + * @param xlsFilePath the xls path + */ + public static void genExcelFile(String content, String title, String xlsFilePath) { + List itemsList; + + //The JSONUtils.toList has been try catch ex + itemsList = JSONUtils.toList(content, LinkedHashMap.class); + + if (CollectionUtils.isEmpty(itemsList)) { + logger.error("itemsList is null"); + throw new RuntimeException("itemsList is null"); + } + + LinkedHashMap headerMap = itemsList.get(0); + + List headerList = new ArrayList<>(); + + Iterator> iter = headerMap.entrySet().iterator(); + while (iter.hasNext()) { + Map.Entry en = iter.next(); + headerList.add(en.getKey()); + } + + HSSFWorkbook wb = null; + FileOutputStream fos = null; + try { + // declare a workbook + wb = new HSSFWorkbook(); + // generate a table + HSSFSheet sheet = wb.createSheet(); + HSSFRow row = sheet.createRow(0); + //set the height of the first line + row.setHeight((short) 500); + + //set Horizontal right + CellStyle cellStyle = wb.createCellStyle(); + cellStyle.setAlignment(HorizontalAlignment.RIGHT); + + //setting excel headers + for (int i = 0; i < headerList.size(); i++) { + HSSFCell cell = row.createCell(i); + cell.setCellStyle(cellStyle); + cell.setCellValue(headerList.get(i)); + } + + //setting excel body + int rowIndex = 1; + for (LinkedHashMap itemsMap : itemsList) { + Object[] values = itemsMap.values().toArray(); + row = sheet.createRow(rowIndex); + //setting excel body height + row.setHeight((short) 500); + rowIndex++; + for (int j = 0; j < values.length; j++) { + HSSFCell cell1 = row.createCell(j); + cell1.setCellStyle(cellStyle); + cell1.setCellValue(String.valueOf(values[j])); + } + } + + for (int i = 0; i < headerList.size(); i++) { + sheet.setColumnWidth(i, headerList.get(i).length() * 800); + } + + File file = new File(xlsFilePath); + if (!file.exists()) { + file.mkdirs(); + } + + //setting file output + fos = new FileOutputStream(xlsFilePath + EmailConstants.SINGLE_SLASH + title + EmailConstants.EXCEL_SUFFIX_XLS); + + wb.write(fos); + + } catch (Exception e) { + logger.error("generate excel error", e); + throw new RuntimeException("generate excel error", e); + } finally { + if (wb != null) { + try { + wb.close(); + } catch (IOException e) { + logger.error(e.getMessage(), e); + } + } + if (fos != null) { + try { + fos.close(); + } catch (IOException e) { + logger.error(e.getMessage(), e); + } + } + } + } + +} \ No newline at end of file diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-email/src/main/java/org/apache/dolphinscheduler/plugin/alert/email/MailParamsConstants.java b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-email/src/main/java/org/apache/dolphinscheduler/plugin/alert/email/MailParamsConstants.java new file mode 100644 index 0000000000..3eaa420301 --- /dev/null +++ b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-email/src/main/java/org/apache/dolphinscheduler/plugin/alert/email/MailParamsConstants.java @@ -0,0 +1,65 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.dolphinscheduler.plugin.alert.email; + +/** + * mail plugin params json use + */ +public class MailParamsConstants { + + public MailParamsConstants() { + throw new IllegalStateException("Utility class"); + } + + public static final String PLUGIN_DEFAULT_EMAIL_RECEIVERS = "$t('receivers')"; + public static final String NAME_PLUGIN_DEFAULT_EMAIL_RECEIVERS = "receivers"; + + public static final String PLUGIN_DEFAULT_EMAIL_RECEIVERCCS = "$t('receiverCcs')"; + public static final String NAME_PLUGIN_DEFAULT_EMAIL_RECEIVERCCS = "receiverCcs"; + + public static final String MAIL_PROTOCOL = "transport.protocol"; + public static final String NAME_MAIL_PROTOCOL = "protocol"; + + public static final String MAIL_SMTP_HOST = "smtp.host"; + public static final String NAME_MAIL_SMTP_HOST = "serverHost"; + + public static final String MAIL_SMTP_PORT = "smtp.port"; + public static final String NAME_MAIL_SMTP_PORT = "serverPort"; + + public static final String MAIL_SENDER = "sender"; + public static final String NAME_MAIL_SENDER = "sender"; + + public static final String MAIL_SMTP_AUTH = "smtp.auth"; + public static final String NAME_MAIL_SMTP_AUTH = "enableSmtpAuth"; + + public static final String MAIL_USER = "user"; + public static final String NAME_MAIL_USER = "user"; + + public static final String MAIL_PASSWD = "passwd"; + public static final String NAME_MAIL_PASSWD = "passwd"; + + public static final String MAIL_SMTP_STARTTLS_ENABLE = "smtp.starttls.enable"; + public static final String NAME_MAIL_SMTP_STARTTLS_ENABLE = "starttlsEnable"; + + public static final String MAIL_SMTP_SSL_ENABLE = "smtp.ssl.enable"; + public static final String NAME_MAIL_SMTP_SSL_ENABLE = "sslEnable"; + + public static final String MAIL_SMTP_SSL_TRUST = "smtp.ssl.trust"; + public static final String NAME_MAIL_SMTP_SSL_TRUST = "smtpSslTrust"; + +} diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-email/src/main/java/org/apache/dolphinscheduler/plugin/alert/email/MailSender.java b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-email/src/main/java/org/apache/dolphinscheduler/plugin/alert/email/MailSender.java new file mode 100644 index 0000000000..03765b248d --- /dev/null +++ b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-email/src/main/java/org/apache/dolphinscheduler/plugin/alert/email/MailSender.java @@ -0,0 +1,429 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.dolphinscheduler.plugin.alert.email; + +import static java.util.Objects.requireNonNull; + +import org.apache.dolphinscheduler.plugin.alert.email.template.AlertTemplate; +import org.apache.dolphinscheduler.plugin.alert.email.template.DefaultHTMLTemplate; +import org.apache.dolphinscheduler.spi.alert.AlertConstants; +import org.apache.dolphinscheduler.spi.alert.AlertResult; +import org.apache.dolphinscheduler.spi.alert.ShowType; +import org.apache.dolphinscheduler.spi.utils.StringUtils; + +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.mail.EmailException; +import org.apache.commons.mail.HtmlEmail; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.Properties; + +import javax.mail.Authenticator; +import javax.mail.Message; +import javax.mail.MessagingException; +import javax.mail.PasswordAuthentication; +import javax.mail.Session; +import javax.mail.Transport; +import javax.mail.internet.InternetAddress; +import javax.mail.internet.MimeBodyPart; +import javax.mail.internet.MimeMessage; +import javax.mail.internet.MimeMultipart; +import javax.mail.internet.MimeUtility; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.sun.mail.smtp.SMTPProvider; + +/** + * mail utils + */ +public class MailSender { + + public static final Logger logger = LoggerFactory.getLogger(MailSender.class); + + private List receivers; + private List receiverCcs; + private String mailProtocol = "SMTP"; + private String mailSmtpHost; + private String mailSmtpPort; + private String mailSender; + private String enableSmtpAuth; + private String mailUser; + private String mailPasswd; + private String mailUseStartTLS; + private String mailUseSSL; + private String xlsFilePath; + private String sslTrust; + private String showType; + private AlertTemplate alertTemplate; + + public MailSender(Map config) { + + String receiversConfig = config.get(MailParamsConstants.NAME_PLUGIN_DEFAULT_EMAIL_RECEIVERS); + if (receiversConfig == null || "".equals(receiversConfig)) { + throw new RuntimeException(MailParamsConstants.PLUGIN_DEFAULT_EMAIL_RECEIVERS + "must not be null"); + } + + receivers = Arrays.asList(receiversConfig.split(",")); + + String receiverCcsConfig = config.get(MailParamsConstants.NAME_PLUGIN_DEFAULT_EMAIL_RECEIVERCCS); + + receiverCcs = new ArrayList<>(); + if (receiverCcsConfig != null && !"".equals(receiverCcsConfig)) { + receiverCcs = Arrays.asList(receiverCcsConfig.split(",")); + } + + mailSmtpHost = config.get(MailParamsConstants.NAME_MAIL_SMTP_HOST); + requireNonNull(mailSmtpHost, MailParamsConstants.MAIL_SMTP_HOST + " must not null"); + + mailSmtpPort = config.get(MailParamsConstants.NAME_MAIL_SMTP_PORT); + requireNonNull(mailSmtpPort, MailParamsConstants.MAIL_SMTP_PORT + " must not null"); + + mailSender = config.get(MailParamsConstants.NAME_MAIL_SENDER); + requireNonNull(mailSender, MailParamsConstants.MAIL_SENDER + " must not null"); + + enableSmtpAuth = config.get(MailParamsConstants.NAME_MAIL_SMTP_AUTH); + + mailUser = config.get(MailParamsConstants.NAME_MAIL_USER); + requireNonNull(mailUser, MailParamsConstants.MAIL_USER + " must not null"); + + mailPasswd = config.get(MailParamsConstants.NAME_MAIL_PASSWD); + requireNonNull(mailPasswd, MailParamsConstants.MAIL_PASSWD + " must not null"); + + mailUseStartTLS = config.get(MailParamsConstants.NAME_MAIL_SMTP_STARTTLS_ENABLE); + requireNonNull(mailUseStartTLS, MailParamsConstants.MAIL_SMTP_STARTTLS_ENABLE + " must not null"); + + mailUseSSL = config.get(MailParamsConstants.NAME_MAIL_SMTP_SSL_ENABLE); + requireNonNull(mailUseSSL, MailParamsConstants.MAIL_SMTP_SSL_ENABLE + " must not null"); + + sslTrust = config.get(MailParamsConstants.NAME_MAIL_SMTP_SSL_TRUST); + requireNonNull(sslTrust, MailParamsConstants.MAIL_SMTP_SSL_TRUST + " must not null"); + + showType = config.get(AlertConstants.SHOW_TYPE); + requireNonNull(showType, AlertConstants.SHOW_TYPE + " must not null"); + + xlsFilePath = config.get(EmailConstants.XLS_FILE_PATH); + if (StringUtils.isBlank(xlsFilePath)) { + xlsFilePath = "/tmp/xls"; + } + + alertTemplate = new DefaultHTMLTemplate(); + } + + /** + * send mail to receivers + * + * @param title title + * @param content content + * @return + */ + public AlertResult sendMails(String title, String content) { + return sendMails(this.receivers, this.receiverCcs, title, content); + } + + /** + * send mail to receivers + * + * @param title email title + * @param content email content + * @return + */ + public AlertResult sendMailsToReceiverOnly(String title, String content) { + return sendMails(this.receivers, null, title, content); + } + + /** + * send mail + * + * @param receivers receivers + * @param receiverCcs receiverCcs + * @param title title + * @param content content + * @return + */ + public AlertResult sendMails(List receivers, List receiverCcs, String title, String content) { + AlertResult alertResult = new AlertResult(); + alertResult.setStatus("false"); + + // if there is no receivers && no receiversCc, no need to process + if (CollectionUtils.isEmpty(receivers) && CollectionUtils.isEmpty(receiverCcs)) { + return alertResult; + } + + receivers.removeIf(StringUtils::isEmpty); + + if (showType.equals(ShowType.TABLE.getDescp()) || showType.equals(ShowType.TEXT.getDescp())) { + // send email + HtmlEmail email = new HtmlEmail(); + + try { + Session session = getSession(); + email.setMailSession(session); + email.setFrom(mailSender); + email.setCharset(EmailConstants.UTF_8); + if (CollectionUtils.isNotEmpty(receivers)) { + // receivers mail + for (String receiver : receivers) { + email.addTo(receiver); + } + } + + if (CollectionUtils.isNotEmpty(receiverCcs)) { + //cc + for (String receiverCc : receiverCcs) { + email.addCc(receiverCc); + } + } + // sender mail + return getStringObjectMap(title, content, alertResult, email); + } catch (Exception e) { + handleException(alertResult, e); + } + } else if (showType.equals(ShowType.ATTACHMENT.getDescp()) || showType.equals(ShowType.TABLEATTACHMENT.getDescp())) { + try { + + String partContent = (showType.equals(ShowType.ATTACHMENT.getDescp()) ? "Please see the attachment " + title + EmailConstants.EXCEL_SUFFIX_XLS : htmlTable(content, false)); + + attachment(title, content, partContent); + + alertResult.setStatus("true"); + return alertResult; + } catch (Exception e) { + handleException(alertResult, e); + return alertResult; + } + } + return alertResult; + + } + + /** + * html table content + * + * @param content the content + * @param showAll if show the whole content + * @return the html table form + */ + private String htmlTable(String content, boolean showAll) { + return alertTemplate.getMessageFromTemplate(content, ShowType.TABLE, showAll); + } + + /** + * html table content + * + * @param content the content + * @return the html table form + */ + private String htmlTable(String content) { + return htmlTable(content, true); + } + + /** + * html text content + * + * @param content the content + * @return text in html form + */ + private String htmlText(String content) { + return alertTemplate.getMessageFromTemplate(content, ShowType.TEXT); + } + + /** + * send mail as Excel attachment + * + * @param title + * @param content + * @param partContent + * @throws Exception + */ + private void attachment(String title, String content, String partContent) throws Exception { + MimeMessage msg = getMimeMessage(); + + attachContent(title, content, partContent, msg); + } + + /** + * get MimeMessage + * + * @return + * @throws MessagingException + */ + private MimeMessage getMimeMessage() throws MessagingException { + + // 1. The first step in creating mail: creating session + Session session = getSession(); + // Setting debug mode, can be turned off + session.setDebug(false); + + // 2. creating mail: Creating a MimeMessage + MimeMessage msg = new MimeMessage(session); + // 3. set sender + msg.setFrom(new InternetAddress(mailSender)); + // 4. set receivers + for (String receiver : receivers) { + msg.addRecipients(Message.RecipientType.TO, InternetAddress.parse(receiver)); + } + return msg; + } + + /** + * get session + * + * @return the new Session + */ + private Session getSession() { + Properties props = new Properties(); + props.setProperty(MailParamsConstants.MAIL_SMTP_HOST, mailSmtpHost); + props.setProperty(MailParamsConstants.MAIL_SMTP_PORT, mailSmtpPort); + props.setProperty(MailParamsConstants.MAIL_SMTP_AUTH, enableSmtpAuth); + props.setProperty(EmailConstants.MAIL_TRANSPORT_PROTOCOL, mailProtocol); + props.setProperty(MailParamsConstants.MAIL_SMTP_STARTTLS_ENABLE, mailUseStartTLS); + props.setProperty(MailParamsConstants.MAIL_SMTP_SSL_ENABLE, mailUseSSL); + props.setProperty(MailParamsConstants.MAIL_SMTP_SSL_TRUST, sslTrust); + + Authenticator auth = new Authenticator() { + @Override + protected PasswordAuthentication getPasswordAuthentication() { + // mail username and password + return new PasswordAuthentication(mailUser, mailPasswd); + } + }; + + Session session = Session.getInstance(props, auth); + session.addProvider(new SMTPProvider()); + return session; + } + + /** + * attach content + * + * @param title + * @param content + * @param partContent + * @param msg + * @throws MessagingException + * @throws IOException + */ + private void attachContent(String title, String content, String partContent, MimeMessage msg) throws MessagingException, IOException { + /** + * set receiverCc + */ + if (CollectionUtils.isNotEmpty(receiverCcs)) { + for (String receiverCc : receiverCcs) { + msg.addRecipients(Message.RecipientType.CC, InternetAddress.parse(receiverCc)); + } + } + + // set subject + msg.setSubject(title); + MimeMultipart partList = new MimeMultipart(); + // set signature + MimeBodyPart part1 = new MimeBodyPart(); + part1.setContent(partContent, EmailConstants.TEXT_HTML_CHARSET_UTF_8); + // set attach file + MimeBodyPart part2 = new MimeBodyPart(); + File file = new File(xlsFilePath + EmailConstants.SINGLE_SLASH + title + EmailConstants.EXCEL_SUFFIX_XLS); + if (!file.getParentFile().exists()) { + file.getParentFile().mkdirs(); + } + // make excel file + + ExcelUtils.genExcelFile(content, title, xlsFilePath); + + part2.attachFile(file); + part2.setFileName(MimeUtility.encodeText(title + EmailConstants.EXCEL_SUFFIX_XLS, EmailConstants.UTF_8, "B")); + // add components to collection + partList.addBodyPart(part1); + partList.addBodyPart(part2); + msg.setContent(partList); + // 5. send Transport + Transport.send(msg); + // 6. delete saved file + deleteFile(file); + } + + /** + * the string object map + * + * @param title + * @param content + * @param alertResult + * @param email + * @return + * @throws EmailException + */ + private AlertResult getStringObjectMap(String title, String content, AlertResult alertResult, HtmlEmail email) throws EmailException { + + /** + * the subject of the message to be sent + */ + email.setSubject(title); + /** + * to send information, you can use HTML tags in mail content because of the use of HtmlEmail + */ + if (showType.equals(ShowType.TABLE.getDescp())) { + email.setMsg(htmlTable(content)); + } else if (showType.equals(ShowType.TEXT.getDescp())) { + email.setMsg(htmlText(content)); + } + + // send + email.setDebug(true); + Thread.currentThread().setContextClassLoader(getClass().getClassLoader()); + email.send(); + + alertResult.setStatus("true"); + + return alertResult; + } + + /** + * file delete + * + * @param file the file to delete + */ + public void deleteFile(File file) { + if (file.exists()) { + if (file.delete()) { + logger.info("delete success: {}", file.getAbsolutePath() + file.getName()); + } else { + logger.info("delete fail: {}", file.getAbsolutePath() + file.getName()); + } + } else { + logger.info("file not exists: {}", file.getAbsolutePath() + file.getName()); + } + } + + /** + * handle exception + * + * @param alertResult + * @param e + */ + private void handleException(AlertResult alertResult, Exception e) { + logger.error("Send email to {} failed", receivers, e); + alertResult.setMessage("Send email to {" + String.join(",", receivers) + "} failed," + e.toString()); + } + +} diff --git a/dolphinscheduler-alert/src/main/java/org/apache/dolphinscheduler/alert/template/AlertTemplate.java b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-email/src/main/java/org/apache/dolphinscheduler/plugin/alert/email/template/AlertTemplate.java similarity index 72% rename from dolphinscheduler-alert/src/main/java/org/apache/dolphinscheduler/alert/template/AlertTemplate.java rename to dolphinscheduler-alert-plugin/dolphinscheduler-alert-email/src/main/java/org/apache/dolphinscheduler/plugin/alert/email/template/AlertTemplate.java index 81b5e65f27..dec993d4d0 100644 --- a/dolphinscheduler-alert/src/main/java/org/apache/dolphinscheduler/alert/template/AlertTemplate.java +++ b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-email/src/main/java/org/apache/dolphinscheduler/plugin/alert/email/template/AlertTemplate.java @@ -14,9 +14,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.dolphinscheduler.alert.template; -import org.apache.dolphinscheduler.common.enums.ShowType; +package org.apache.dolphinscheduler.plugin.alert.email.template; + +import org.apache.dolphinscheduler.spi.alert.ShowType; /** * alert message template @@ -25,20 +26,22 @@ public interface AlertTemplate { /** * get a message from a specified alert template - * @param content alert message content - * @param showType show type - * @param showAll whether to show all + * + * @param content alert message content + * @param showType show type + * @param showAll whether to show all * @return a message from a specified alert template */ - String getMessageFromTemplate(String content, ShowType showType,boolean showAll); + String getMessageFromTemplate(String content, ShowType showType, boolean showAll); /** * default showAll is true - * @param content alert message content + * + * @param content alert message content * @param showType show type * @return a message from a specified alert template */ - default String getMessageFromTemplate(String content,ShowType showType){ - return getMessageFromTemplate(content,showType,true); + default String getMessageFromTemplate(String content, ShowType showType) { + return getMessageFromTemplate(content, showType, true); } } diff --git a/dolphinscheduler-alert/src/main/java/org/apache/dolphinscheduler/alert/template/impl/DefaultHTMLTemplate.java b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-email/src/main/java/org/apache/dolphinscheduler/plugin/alert/email/template/DefaultHTMLTemplate.java similarity index 52% rename from dolphinscheduler-alert/src/main/java/org/apache/dolphinscheduler/alert/template/impl/DefaultHTMLTemplate.java rename to dolphinscheduler-alert-plugin/dolphinscheduler-alert-email/src/main/java/org/apache/dolphinscheduler/plugin/alert/email/template/DefaultHTMLTemplate.java index a01f301a24..06decd6ffc 100644 --- a/dolphinscheduler-alert/src/main/java/org/apache/dolphinscheduler/alert/template/impl/DefaultHTMLTemplate.java +++ b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-email/src/main/java/org/apache/dolphinscheduler/plugin/alert/email/template/DefaultHTMLTemplate.java @@ -14,21 +14,27 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.dolphinscheduler.alert.template.impl; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.node.ArrayNode; -import org.apache.dolphinscheduler.alert.template.AlertTemplate; -import org.apache.dolphinscheduler.alert.utils.Constants; -import org.apache.dolphinscheduler.common.enums.ShowType; -import org.apache.dolphinscheduler.common.utils.StringUtils; +package org.apache.dolphinscheduler.plugin.alert.email.template; + +import static java.util.Objects.requireNonNull; + +import org.apache.dolphinscheduler.plugin.alert.email.EmailConstants; +import org.apache.dolphinscheduler.spi.alert.ShowType; +import org.apache.dolphinscheduler.spi.utils.JSONUtils; +import org.apache.dolphinscheduler.spi.utils.StringUtils; + +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.apache.dolphinscheduler.common.utils.*; -import java.util.*; - -import static org.apache.dolphinscheduler.common.utils.Preconditions.*; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.ArrayNode; /** * the default html alert message template @@ -37,33 +43,33 @@ public class DefaultHTMLTemplate implements AlertTemplate { public static final Logger logger = LoggerFactory.getLogger(DefaultHTMLTemplate.class); - @Override - public String getMessageFromTemplate(String content, ShowType showType,boolean showAll) { + public String getMessageFromTemplate(String content, ShowType showType, boolean showAll) { - switch (showType){ + switch (showType) { case TABLE: - return getTableTypeMessage(content,showAll); + return getTableTypeMessage(content, showAll); case TEXT: - return getTextTypeMessage(content,showAll); + return getTextTypeMessage(content, showAll); default: - throw new IllegalArgumentException(String.format("not support showType: %s in DefaultHTMLTemplate",showType)); + throw new IllegalArgumentException(String.format("not support showType: %s in DefaultHTMLTemplate", showType)); } } /** * get alert message which type is TABLE + * * @param content message content * @param showAll weather to show all * @return alert message */ - private String getTableTypeMessage(String content,boolean showAll){ + private String getTableTypeMessage(String content, boolean showAll) { - if (StringUtils.isNotEmpty(content)){ + if (StringUtils.isNotEmpty(content)) { List mapItemsList = JSONUtils.toList(content, LinkedHashMap.class); - if(!showAll && mapItemsList.size() > Constants.NUMBER_1000){ - mapItemsList = mapItemsList.subList(0,Constants.NUMBER_1000); + if (!showAll && mapItemsList.size() > EmailConstants.NUMBER_1000) { + mapItemsList = mapItemsList.subList(0, EmailConstants.NUMBER_1000); } StringBuilder contents = new StringBuilder(200); @@ -71,31 +77,31 @@ public class DefaultHTMLTemplate implements AlertTemplate { boolean flag = true; String title = ""; - for (LinkedHashMap mapItems : mapItemsList){ + for (LinkedHashMap mapItems : mapItemsList) { Set> entries = mapItems.entrySet(); Iterator> iterator = entries.iterator(); - StringBuilder t = new StringBuilder(Constants.TR); - StringBuilder cs = new StringBuilder(Constants.TR); - while (iterator.hasNext()){ + StringBuilder t = new StringBuilder(EmailConstants.TR); + StringBuilder cs = new StringBuilder(EmailConstants.TR); + while (iterator.hasNext()) { Map.Entry entry = iterator.next(); - t.append(Constants.TH).append(entry.getKey()).append(Constants.TH_END); - cs.append(Constants.TD).append(String.valueOf(entry.getValue())).append(Constants.TD_END); + t.append(EmailConstants.TH).append(entry.getKey()).append(EmailConstants.TH_END); + cs.append(EmailConstants.TD).append(String.valueOf(entry.getValue())).append(EmailConstants.TD_END); } - t.append(Constants.TR_END); - cs.append(Constants.TR_END); - if (flag){ + t.append(EmailConstants.TR_END); + cs.append(EmailConstants.TR_END); + if (flag) { title = t.toString(); } flag = false; contents.append(cs); } - return getMessageFromHtmlTemplate(title,contents.toString()); + return getMessageFromHtmlTemplate(title, contents.toString()); } return content; @@ -103,22 +109,23 @@ public class DefaultHTMLTemplate implements AlertTemplate { /** * get alert message which type is TEXT + * * @param content message content * @param showAll weather to show all * @return alert message */ - private String getTextTypeMessage(String content,boolean showAll){ + private String getTextTypeMessage(String content, boolean showAll) { - if (StringUtils.isNotEmpty(content)){ + if (StringUtils.isNotEmpty(content)) { ArrayNode list = JSONUtils.parseArray(content); StringBuilder contents = new StringBuilder(100); - for (JsonNode jsonNode : list){ - contents.append(Constants.TR); - contents.append(Constants.TD).append(jsonNode.toString()).append(Constants.TD_END); - contents.append(Constants.TR_END); + for (JsonNode jsonNode : list) { + contents.append(EmailConstants.TR); + contents.append(EmailConstants.TD).append(jsonNode.toString()).append(EmailConstants.TD_END); + contents.append(EmailConstants.TR_END); } - return getMessageFromHtmlTemplate(null,contents.toString()); + return getMessageFromHtmlTemplate(null, contents.toString()); } @@ -127,16 +134,17 @@ public class DefaultHTMLTemplate implements AlertTemplate { /** * get alert message from a html template - * @param title message title - * @param content message content + * + * @param title message title + * @param content message content * @return alert message which use html template */ - private String getMessageFromHtmlTemplate(String title,String content){ + private String getMessageFromHtmlTemplate(String title, String content) { - checkNotNull(content); - String htmlTableThead = StringUtils.isEmpty(title) ? "" : String.format("%s\n",title); + requireNonNull(content, "content must not null"); + String htmlTableThead = StringUtils.isEmpty(title) ? "" : String.format("%s\n", title); - return Constants.HTML_HEADER_PREFIX +htmlTableThead + content + Constants.TABLE_BODY_HTML_TAIL; + return EmailConstants.HTML_HEADER_PREFIX + htmlTableThead + content + EmailConstants.TABLE_BODY_HTML_TAIL; } } diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-email/src/test/java/org/apache/dolphinscheduler/plugin/alert/email/EmailAlertChannelFactoryTest.java b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-email/src/test/java/org/apache/dolphinscheduler/plugin/alert/email/EmailAlertChannelFactoryTest.java new file mode 100644 index 0000000000..977cd8fefc --- /dev/null +++ b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-email/src/test/java/org/apache/dolphinscheduler/plugin/alert/email/EmailAlertChannelFactoryTest.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.email; + +import org.apache.dolphinscheduler.spi.alert.AlertChannel; +import org.apache.dolphinscheduler.spi.params.base.PluginParams; +import org.apache.dolphinscheduler.spi.utils.JSONUtils; + +import java.util.List; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +/** + * EmailAlertChannelFactory Tester. + * + * @version 1.0 + * @since
Aug 20, 2020
+ */ +public class EmailAlertChannelFactoryTest { + + @Before + public void before() throws Exception { + } + + @After + public void after() throws Exception { + } + + /** + * Method: getName() + */ + @Test + public void testGetName() throws Exception { + } + + /** + * Method: getParams() + */ + @Test + public void testGetParams() throws Exception { + EmailAlertChannelFactory emailAlertChannelFactory = new EmailAlertChannelFactory(); + List params = emailAlertChannelFactory.getParams(); + System.out.println(JSONUtils.toJsonString(params)); + Assert.assertEquals(12, params.size()); + } + + /** + * Method: create() + */ + @Test + public void testCreate() throws Exception { + EmailAlertChannelFactory emailAlertChannelFactory = new EmailAlertChannelFactory(); + AlertChannel alertChannel = emailAlertChannelFactory.create(); + Assert.assertNotNull(alertChannel); + } + +} diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-email/src/test/java/org/apache/dolphinscheduler/plugin/alert/email/EmailAlertChannelTest.java b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-email/src/test/java/org/apache/dolphinscheduler/plugin/alert/email/EmailAlertChannelTest.java new file mode 100644 index 0000000000..97a1013399 --- /dev/null +++ b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-email/src/test/java/org/apache/dolphinscheduler/plugin/alert/email/EmailAlertChannelTest.java @@ -0,0 +1,161 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.dolphinscheduler.plugin.alert.email; + +import org.apache.dolphinscheduler.spi.alert.AlertConstants; +import org.apache.dolphinscheduler.spi.alert.AlertData; +import org.apache.dolphinscheduler.spi.alert.AlertInfo; +import org.apache.dolphinscheduler.spi.alert.AlertResult; +import org.apache.dolphinscheduler.spi.alert.ShowType; +import org.apache.dolphinscheduler.spi.params.InputParam; +import org.apache.dolphinscheduler.spi.params.PasswordParam; +import org.apache.dolphinscheduler.spi.params.RadioParam; +import org.apache.dolphinscheduler.spi.params.base.DataType; +import org.apache.dolphinscheduler.spi.params.base.ParamsOptions; +import org.apache.dolphinscheduler.spi.params.base.PluginParams; +import org.apache.dolphinscheduler.spi.params.base.Validate; +import org.apache.dolphinscheduler.spi.utils.JSONUtils; + +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; + +import org.junit.Assert; +import org.junit.Test; + +/** + * EmailAlertChannel Tester. + */ +public class EmailAlertChannelTest { + + /** + * Method: process(AlertInfo info) + */ + @Test + public void testProcess() { + EmailAlertChannel emailAlertChannel = new EmailAlertChannel(); + AlertData alertData = new AlertData(); + LinkedHashMap map1 = new LinkedHashMap<>(); + map1.put("mysql service name", "mysql200"); + map1.put("mysql address", "192.168.xx.xx"); + map1.put("port", "3306"); + map1.put("no index of number", "80"); + map1.put("database client connections", "190"); + List> maps = new ArrayList<>(); + maps.add(0, map1); + String mapjson = JSONUtils.toJsonString(maps); + + alertData.setId(10) + .setContent(mapjson) + .setLog("10") + .setTitle("test"); + AlertInfo alertInfo = new AlertInfo(); + alertInfo.setAlertData(alertData); + alertInfo.setAlertParams(getEmailAlertParams()); + AlertResult alertResult = emailAlertChannel.process(alertInfo); + Assert.assertNotNull(alertResult); + Assert.assertEquals("false", alertResult.getStatus()); + } + + public String getEmailAlertParams() { + List paramsList = new ArrayList<>(); + InputParam receivesParam = InputParam.newBuilder("receivers", "receivers") + .setValue("540957506@qq.com") + .addValidate(Validate.newBuilder().setRequired(true).build()) + .build(); + + InputParam mailSmtpHost = InputParam.newBuilder("serverHost", "smtp.host") + .addValidate(Validate.newBuilder().setRequired(true).build()) + .setValue("smtp.126.com") + .build(); + + InputParam mailSmtpPort = InputParam.newBuilder("serverPort", "smtp.port") + .addValidate(Validate.newBuilder() + .setRequired(true) + .setType(DataType.NUMBER.getDataType()) + .build()) + .setValue(25) + .build(); + + InputParam mailSender = InputParam.newBuilder("sender", "sender") + .addValidate(Validate.newBuilder().setRequired(true).build()) + .setValue("dolphinscheduler@126.com") + .build(); + + RadioParam enableSmtpAuth = RadioParam.newBuilder("enableSmtpAuth", "smtp.auth") + .addParamsOptions(new ParamsOptions("YES", true, false)) + .addParamsOptions(new ParamsOptions("NO", false, false)) + .addValidate(Validate.newBuilder().setRequired(true).build()) + .setValue(false) + .build(); + + InputParam mailUser = InputParam.newBuilder("user", "user") + .setPlaceholder("if enable use authentication, you need input user") + .setValue("dolphinscheduler@126.com") + .build(); + + PasswordParam mailPassword = PasswordParam.newBuilder("passwd", "passwd") + .setPlaceholder("if enable use authentication, you need input password") + .setValue("escheduler123") + .build(); + + RadioParam enableTls = RadioParam.newBuilder("starttlsEnable", "starttls.enable") + .addParamsOptions(new ParamsOptions("YES", true, false)) + .addParamsOptions(new ParamsOptions("NO", false, false)) + .addValidate(Validate.newBuilder().setRequired(true).build()) + .setValue(true) + .build(); + + RadioParam enableSsl = RadioParam.newBuilder("sslEnable", "smtp.ssl.enable") + .addParamsOptions(new ParamsOptions("YES", true, false)) + .addParamsOptions(new ParamsOptions("NO", false, false)) + .addValidate(Validate.newBuilder().setRequired(true).build()) + .setValue(true) + .build(); + + InputParam sslTrust = InputParam.newBuilder("smtpSslTrust", "smtp.ssl.trust") + .addValidate(Validate.newBuilder().setRequired(true).build()) + .setValue("smtp.126.com") + .build(); + + List emailShowTypeList = new ArrayList<>(); + emailShowTypeList.add(new ParamsOptions(ShowType.TABLE.getDescp(), ShowType.TABLE.getDescp(), false)); + emailShowTypeList.add(new ParamsOptions(ShowType.TEXT.getDescp(), ShowType.TEXT.getDescp(), false)); + emailShowTypeList.add(new ParamsOptions(ShowType.ATTACHMENT.getDescp(), ShowType.ATTACHMENT.getDescp(), false)); + emailShowTypeList.add(new ParamsOptions(ShowType.TABLEATTACHMENT.getDescp(), ShowType.TABLEATTACHMENT.getDescp(), false)); + RadioParam showType = RadioParam.newBuilder(AlertConstants.SHOW_TYPE, "showType") + .setParamsOptionsList(emailShowTypeList) + .setValue(ShowType.TABLE.getDescp()) + .addValidate(Validate.newBuilder().setRequired(true).build()) + .build(); + + paramsList.add(receivesParam); + paramsList.add(mailSmtpHost); + paramsList.add(mailSmtpPort); + paramsList.add(mailSender); + paramsList.add(enableSmtpAuth); + paramsList.add(mailUser); + paramsList.add(mailPassword); + paramsList.add(enableTls); + paramsList.add(enableSsl); + paramsList.add(sslTrust); + paramsList.add(showType); + + return JSONUtils.toJsonString(paramsList); + } +} diff --git a/dolphinscheduler-alert/src/test/java/org/apache/dolphinscheduler/alert/utils/ExcelUtilsTest.java b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-email/src/test/java/org/apache/dolphinscheduler/plugin/alert/email/ExcelUtilsTest.java similarity index 89% rename from dolphinscheduler-alert/src/test/java/org/apache/dolphinscheduler/alert/utils/ExcelUtilsTest.java rename to dolphinscheduler-alert-plugin/dolphinscheduler-alert-email/src/test/java/org/apache/dolphinscheduler/plugin/alert/email/ExcelUtilsTest.java index 8ee62358dd..5c8b195176 100644 --- a/dolphinscheduler-alert/src/test/java/org/apache/dolphinscheduler/alert/utils/ExcelUtilsTest.java +++ b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-email/src/test/java/org/apache/dolphinscheduler/plugin/alert/email/ExcelUtilsTest.java @@ -15,7 +15,11 @@ * limitations under the License. */ -package org.apache.dolphinscheduler.alert.utils; +package org.apache.dolphinscheduler.plugin.alert.email; + +import static org.junit.Assert.assertTrue; + +import java.io.File; import org.junit.After; import org.junit.Before; @@ -25,8 +29,6 @@ import org.junit.rules.ExpectedException; import org.junit.rules.TemporaryFolder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.io.File; -import static org.junit.Assert.assertTrue; public class ExcelUtilsTest { @@ -61,7 +63,7 @@ public class ExcelUtilsTest { //Define dest file path String xlsFilePath = rootPath + System.getProperty("file.separator"); - logger.info("xlsFilePath: "+xlsFilePath); + logger.info("xlsFilePath: " + xlsFilePath); //Define correctContent String correctContent = "[{\"name\":\"ds name\",\"value\":\"ds value\"}]"; @@ -76,7 +78,7 @@ public class ExcelUtilsTest { ExcelUtils.genExcelFile(correctContent, title, xlsFilePath); //Test file exists - File xlsFile = new File(xlsFilePath + Constants.SINGLE_SLASH + title + Constants.EXCEL_SUFFIX_XLS); + File xlsFile = new File(xlsFilePath + EmailConstants.SINGLE_SLASH + title + EmailConstants.EXCEL_SUFFIX_XLS); assertTrue(xlsFile.exists()); //Expected RuntimeException @@ -96,7 +98,7 @@ public class ExcelUtilsTest { @Test public void testGenExcelFileByCheckDir() { ExcelUtils.genExcelFile("[{\"a\": \"a\"},{\"a\": \"a\"}]", "t", "/tmp/xls"); - File file = new File("/tmp/xls" + Constants.SINGLE_SLASH + "t" + Constants.EXCEL_SUFFIX_XLS); + File file = new File("/tmp/xls" + EmailConstants.SINGLE_SLASH + "t" + EmailConstants.EXCEL_SUFFIX_XLS); file.delete(); } } \ No newline at end of file diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-email/src/test/java/org/apache/dolphinscheduler/plugin/alert/email/MailUtilsTest.java b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-email/src/test/java/org/apache/dolphinscheduler/plugin/alert/email/MailUtilsTest.java new file mode 100644 index 0000000000..e19c819dae --- /dev/null +++ b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-email/src/test/java/org/apache/dolphinscheduler/plugin/alert/email/MailUtilsTest.java @@ -0,0 +1,136 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.dolphinscheduler.plugin.alert.email; + +import org.apache.dolphinscheduler.plugin.alert.email.template.AlertTemplate; +import org.apache.dolphinscheduler.plugin.alert.email.template.DefaultHTMLTemplate; +import org.apache.dolphinscheduler.spi.alert.AlertConstants; +import org.apache.dolphinscheduler.spi.alert.ShowType; +import org.apache.dolphinscheduler.spi.utils.JSONUtils; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +import org.junit.BeforeClass; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + */ +public class MailUtilsTest { + private static final Logger logger = LoggerFactory.getLogger(MailUtilsTest.class); + + private static Map emailConfig = new HashMap<>(); + + private static AlertTemplate alertTemplate; + + static MailSender mailSender; + + @BeforeClass + public static void initEmailConfig() { + emailConfig.put(MailParamsConstants.NAME_MAIL_PROTOCOL, "smtp"); + emailConfig.put(MailParamsConstants.NAME_MAIL_SMTP_HOST, "xxx.xxx.com"); + emailConfig.put(MailParamsConstants.NAME_MAIL_SMTP_PORT, "25"); + emailConfig.put(MailParamsConstants.NAME_MAIL_SENDER, "xxx1.xxx.com"); + emailConfig.put(MailParamsConstants.NAME_MAIL_USER, "xxx2.xxx.com"); + emailConfig.put(MailParamsConstants.NAME_MAIL_PASSWD, "111111"); + emailConfig.put(MailParamsConstants.NAME_MAIL_SMTP_STARTTLS_ENABLE, "true"); + emailConfig.put(MailParamsConstants.NAME_MAIL_SMTP_SSL_ENABLE, "false"); + emailConfig.put(MailParamsConstants.NAME_MAIL_SMTP_SSL_TRUST, "false"); + emailConfig.put(MailParamsConstants.NAME_PLUGIN_DEFAULT_EMAIL_RECEIVERS, "347801120@qq.com"); + emailConfig.put(MailParamsConstants.NAME_PLUGIN_DEFAULT_EMAIL_RECEIVERCCS, "347801120@qq.com"); + emailConfig.put(AlertConstants.SHOW_TYPE, ShowType.TEXT.getDescp()); + alertTemplate = new DefaultHTMLTemplate(); + mailSender = new MailSender(emailConfig); + } + + @Test + public void testSendMails() { + + String content = "[\"id:69\"," + + "\"name:UserBehavior-0--1193959466\"," + + "\"Job name: Start workflow\"," + + "\"State: SUCCESS\"," + + "\"Recovery:NO\"," + + "\"Run time: 1\"," + + "\"Start time: 2018-08-06 10:31:34.0\"," + + "\"End time: 2018-08-06 10:31:49.0\"," + + "\"Host: 192.168.xx.xx\"," + + "\"Notify group :4\"]"; + + mailSender.sendMails( + "Mysql Exception", + content); + } + + public String list2String() { + + LinkedHashMap map1 = new LinkedHashMap<>(); + map1.put("mysql service name", "mysql200"); + map1.put("mysql address", "192.168.xx.xx"); + map1.put("port", "3306"); + map1.put("no index of number", "80"); + map1.put("database client connections", "190"); + + LinkedHashMap map2 = new LinkedHashMap<>(); + map2.put("mysql service name", "mysql210"); + map2.put("mysql address", "192.168.xx.xx"); + map2.put("port", "3306"); + map2.put("no index of number", "10"); + map2.put("database client connections", "90"); + + List> maps = new ArrayList<>(); + maps.add(0, map1); + maps.add(1, map2); + String mapjson = JSONUtils.toJsonString(maps); + logger.info(mapjson); + + return mapjson; + + } + + @Test + public void testSendTableMail() { + String title = "Mysql Exception"; + String content = list2String(); + emailConfig.put(AlertConstants.SHOW_TYPE, ShowType.TABLE.getDescp()); + mailSender = new MailSender(emailConfig); + mailSender.sendMails(title, content); + } + + @Test + public void testAttachmentFile() throws Exception { + String content = list2String(); + emailConfig.put(AlertConstants.SHOW_TYPE, ShowType.ATTACHMENT.getDescp()); + mailSender = new MailSender(emailConfig); + mailSender.sendMails("gaojing", content); + } + + @Test + public void testTableAttachmentFile() throws Exception { + String content = list2String(); + emailConfig.put(AlertConstants.SHOW_TYPE, ShowType.TABLEATTACHMENT.getDescp()); + mailSender = new MailSender(emailConfig); + mailSender.sendMails("gaojing", content); + } + +} diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-email/src/test/java/org/apache/dolphinscheduler/plugin/alert/email/template/DefaultHTMLTemplateTest.java b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-email/src/test/java/org/apache/dolphinscheduler/plugin/alert/email/template/DefaultHTMLTemplateTest.java new file mode 100644 index 0000000000..3d941962d9 --- /dev/null +++ b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-email/src/test/java/org/apache/dolphinscheduler/plugin/alert/email/template/DefaultHTMLTemplateTest.java @@ -0,0 +1,105 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.dolphinscheduler.plugin.alert.email.template; + +import static org.junit.Assert.assertEquals; + +import org.apache.dolphinscheduler.plugin.alert.email.EmailConstants; +import org.apache.dolphinscheduler.spi.alert.ShowType; +import org.apache.dolphinscheduler.spi.utils.JSONUtils; + +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; + +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * test class for DefaultHTMLTemplate + */ +public class DefaultHTMLTemplateTest { + + private static final Logger logger = LoggerFactory.getLogger(DefaultHTMLTemplateTest.class); + + /** + * only need test method GetMessageFromTemplate + */ + @Test + public void testGetMessageFromTemplate() { + + DefaultHTMLTemplate template = new DefaultHTMLTemplate(); + + String tableTypeMessage = template.getMessageFromTemplate(list2String(), ShowType.TABLE, true); + + assertEquals(tableTypeMessage, generateMockTableTypeResultByHand()); + + String textTypeMessage = template.getMessageFromTemplate(list2String(), ShowType.TEXT, true); + + assertEquals(textTypeMessage, generateMockTextTypeResultByHand()); + } + + /** + * generate some simulation data + */ + private String list2String() { + + LinkedHashMap map1 = new LinkedHashMap<>(); + map1.put("mysql service name", "mysql200"); + map1.put("mysql address", "192.168.xx.xx"); + map1.put("database client connections", "190"); + map1.put("port", "3306"); + map1.put("no index of number", "80"); + + LinkedHashMap map2 = new LinkedHashMap<>(); + map2.put("mysql service name", "mysql210"); + map2.put("mysql address", "192.168.xx.xx"); + map2.put("database client connections", "90"); + map2.put("port", "3306"); + map2.put("no index of number", "10"); + + List> maps = new ArrayList<>(); + maps.add(0, map1); + maps.add(1, map2); + String mapjson = JSONUtils.toJsonString(maps); + logger.info(mapjson); + + return mapjson; + } + + private String generateMockTableTypeResultByHand() { + + return EmailConstants.HTML_HEADER_PREFIX + + "" + + "mysql service namemysql addressdatabase client connectionsportno index of number" + + "\n" + + "mysql200192.168.xx.xx190330680" + + "mysql210192.168.xx.xx90330610" + + EmailConstants.TABLE_BODY_HTML_TAIL; + + } + + private String generateMockTextTypeResultByHand() { + + return EmailConstants.HTML_HEADER_PREFIX + + "{\"mysql service name\":\"mysql200\",\"mysql address\":\"192.168.xx.xx\",\"database client connections\":\"190\",\"port\":\"3306\",\"no index of number\":\"80\"}" + + "{\"mysql service name\":\"mysql210\",\"mysql address\":\"192.168.xx.xx\",\"database client connections\":\"90\",\"port\":\"3306\",\"no index of number\":\"10\"}" + + EmailConstants.TABLE_BODY_HTML_TAIL; + } +} diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-http/pom.xml b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-http/pom.xml new file mode 100644 index 0000000000..5223730e3e --- /dev/null +++ b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-http/pom.xml @@ -0,0 +1,76 @@ + + + + + dolphinscheduler-alert-plugin + org.apache.dolphinscheduler + 1.3.4-SNAPSHOT + + 4.0.0 + + dolphinscheduler-alert-http + dolphinscheduler-plugin + + + org.apache.dolphinscheduler + dolphinscheduler-spi + provided + + + + com.google.guava + guava + + + + ch.qos.logback + logback-classic + + + + org.apache.httpcomponents + httpclient + + + + com.fasterxml.jackson.core + jackson-databind + provided + + + + junit + junit + test + + + + org.mockito + mockito-core + jar + test + + + + + dolphinscheduler-alert-http-${project.version} + + + \ No newline at end of file diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-http/src/main/java/org/apache/dolphinscheduler/plugin/alert/http/HttpAlertChannel.java b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-http/src/main/java/org/apache/dolphinscheduler/plugin/alert/http/HttpAlertChannel.java new file mode 100644 index 0000000000..27bc1903d8 --- /dev/null +++ b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-http/src/main/java/org/apache/dolphinscheduler/plugin/alert/http/HttpAlertChannel.java @@ -0,0 +1,41 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.dolphinscheduler.plugin.alert.http; + +import org.apache.dolphinscheduler.spi.alert.AlertChannel; +import org.apache.dolphinscheduler.spi.alert.AlertData; +import org.apache.dolphinscheduler.spi.alert.AlertInfo; +import org.apache.dolphinscheduler.spi.alert.AlertResult; +import org.apache.dolphinscheduler.spi.params.PluginParamsTransfer; + +import java.util.Map; + +/** + * http alert channel,use sms message to seed the alertInfo + */ +public class HttpAlertChannel implements AlertChannel { + @Override + public AlertResult process(AlertInfo alertInfo) { + + AlertData alertData = alertInfo.getAlertData(); + String alertParams = alertInfo.getAlertParams(); + Map paramsMap = PluginParamsTransfer.getPluginParamsMap(alertParams); + + return new HttpSender(paramsMap).send(alertData.getContent()); + } +} diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-http/src/main/java/org/apache/dolphinscheduler/plugin/alert/http/HttpAlertChannelFactory.java b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-http/src/main/java/org/apache/dolphinscheduler/plugin/alert/http/HttpAlertChannelFactory.java new file mode 100644 index 0000000000..6b8dd305fd --- /dev/null +++ b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-http/src/main/java/org/apache/dolphinscheduler/plugin/alert/http/HttpAlertChannelFactory.java @@ -0,0 +1,78 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.dolphinscheduler.plugin.alert.http; + +import org.apache.dolphinscheduler.spi.alert.AlertChannel; +import org.apache.dolphinscheduler.spi.alert.AlertChannelFactory; +import org.apache.dolphinscheduler.spi.params.InputParam; +import org.apache.dolphinscheduler.spi.params.base.PluginParams; +import org.apache.dolphinscheduler.spi.params.base.Validate; + +import java.util.Arrays; +import java.util.List; + +/** + * http alert factory + */ +public class HttpAlertChannelFactory implements AlertChannelFactory { + @Override + public String getName() { + return "Http"; + } + + @Override + public List getParams() { + + InputParam url = InputParam.newBuilder(HttpAlertConstants.URL, HttpAlertConstants.URL) + .addValidate(Validate.newBuilder() + .setRequired(true) + .build()) + .build(); + + InputParam headerParams = InputParam.newBuilder(HttpAlertConstants.HEADER_PARAMS, HttpAlertConstants.HEADER_PARAMS) + .addValidate(Validate.newBuilder() + .setRequired(true) + .build()) + .build(); + + InputParam bodyParams = InputParam.newBuilder(HttpAlertConstants.BODY_PARAMS, HttpAlertConstants.BODY_PARAMS) + .addValidate(Validate.newBuilder() + .setRequired(true) + .build()) + .build(); + + InputParam contentField = InputParam.newBuilder(HttpAlertConstants.CONTENT_FIELD, HttpAlertConstants.CONTENT_FIELD) + .addValidate(Validate.newBuilder() + .setRequired(true) + .build()) + .build(); + + InputParam requestType = InputParam.newBuilder(HttpAlertConstants.REQUEST_TYPE, HttpAlertConstants.REQUEST_TYPE) + .addValidate(Validate.newBuilder() + .setRequired(true) + .build()) + .build(); + + return Arrays.asList(url, requestType, headerParams, bodyParams, contentField); + } + + @Override + public AlertChannel create() { + return new HttpAlertChannel(); + } +} diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-http/src/main/java/org/apache/dolphinscheduler/plugin/alert/http/HttpAlertConstants.java b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-http/src/main/java/org/apache/dolphinscheduler/plugin/alert/http/HttpAlertConstants.java new file mode 100644 index 0000000000..965860d868 --- /dev/null +++ b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-http/src/main/java/org/apache/dolphinscheduler/plugin/alert/http/HttpAlertConstants.java @@ -0,0 +1,35 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.dolphinscheduler.plugin.alert.http; + +public class HttpAlertConstants { + + private HttpAlertConstants() { + } + + public static final String URL = "url"; + + public static final String HEADER_PARAMS = "headerParams"; + + public static final String BODY_PARAMS = "bodyParams"; + + public static final String CONTENT_FIELD = "contentField"; + + public static final String REQUEST_TYPE = "requestType"; + +} diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-http/src/main/java/org/apache/dolphinscheduler/plugin/alert/http/HttpAlertPlugin.java b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-http/src/main/java/org/apache/dolphinscheduler/plugin/alert/http/HttpAlertPlugin.java new file mode 100644 index 0000000000..973f1617a6 --- /dev/null +++ b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-http/src/main/java/org/apache/dolphinscheduler/plugin/alert/http/HttpAlertPlugin.java @@ -0,0 +1,34 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.dolphinscheduler.plugin.alert.http; + +import org.apache.dolphinscheduler.spi.DolphinSchedulerPlugin; +import org.apache.dolphinscheduler.spi.alert.AlertChannelFactory; + +import com.google.common.collect.ImmutableList; + +/** + * http alertPlugins + */ +public class HttpAlertPlugin implements DolphinSchedulerPlugin { + + @Override + public Iterable getAlertChannelFactorys() { + return ImmutableList.of(new HttpAlertChannelFactory()); + } +} diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-http/src/main/java/org/apache/dolphinscheduler/plugin/alert/http/HttpSender.java b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-http/src/main/java/org/apache/dolphinscheduler/plugin/alert/http/HttpSender.java new file mode 100644 index 0000000000..32d3cdb52f --- /dev/null +++ b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-http/src/main/java/org/apache/dolphinscheduler/plugin/alert/http/HttpSender.java @@ -0,0 +1,166 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.dolphinscheduler.plugin.alert.http; + +import org.apache.dolphinscheduler.spi.alert.AlertResult; +import org.apache.dolphinscheduler.spi.utils.JSONUtils; +import org.apache.dolphinscheduler.spi.utils.StringUtils; + +import org.apache.http.HttpEntity; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.client.methods.HttpRequestBase; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClientBuilder; +import org.apache.http.util.EntityUtils; + +import java.util.HashMap; +import java.util.Map; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.fasterxml.jackson.databind.node.ObjectNode; + +/** + * http send message + */ +public class HttpSender { + + public static final Logger logger = LoggerFactory.getLogger(HttpSender.class); + + private String url; + + private final String headerParams; + + private final String bodyParams; + + private final String contentField; + + private final String requestType; + + private HttpRequestBase httpRequest; + + + private static final String URL_SPLICE_CHAR = "?"; + + /** + * request type post + */ + private static final String REQUEST_TYPE_POST = "POST"; + + /** + * request type get + */ + private static final String REQUEST_TYPE_GET = "GET"; + + private static final String DEFAULT_CHARSET = "utf-8"; + + public HttpSender(Map paramsMap) { + + url = paramsMap.get(HttpAlertConstants.URL); + headerParams = paramsMap.get(HttpAlertConstants.HEADER_PARAMS); + bodyParams = paramsMap.get(HttpAlertConstants.BODY_PARAMS); + contentField = paramsMap.get(HttpAlertConstants.CONTENT_FIELD); + requestType = paramsMap.get(HttpAlertConstants.REQUEST_TYPE); + } + + public AlertResult send(String msg) { + + AlertResult alertResult = new AlertResult(); + + createHttpRequest(msg); + + if (httpRequest == null) { + alertResult.setStatus("false"); + alertResult.setMessage("Request types are not supported"); + return alertResult; + } + + try { + CloseableHttpClient httpClient = HttpClientBuilder.create().build(); + CloseableHttpResponse response = httpClient.execute(httpRequest); + HttpEntity entity = response.getEntity(); + String resp = EntityUtils.toString(entity, DEFAULT_CHARSET); + alertResult.setStatus("true"); + alertResult.setMessage(resp); + } catch (Exception e) { + logger.error("send http alert msg exception : {}", e.getMessage()); + alertResult.setStatus("false"); + alertResult.setMessage("send http request alert fail."); + } + + return alertResult; + } + + private void createHttpRequest(String msg) { + + if (REQUEST_TYPE_POST.equals(requestType)) { + httpRequest = new HttpPost(url); + //POST request add param in request body + setMsgInRequestBody(msg); + } else if (REQUEST_TYPE_GET.equals(requestType)) { + //GET request add param in url + setMsgInUrl(msg); + httpRequest = new HttpGet(url); + } + setHeader(); + } + + /** + * add msg param in url + */ + private void setMsgInUrl(String msg) { + + if (StringUtils.isNotBlank(contentField)) { + String type = "&"; + //check splice char is & or ? + if (!url.contains(URL_SPLICE_CHAR)) { + type = URL_SPLICE_CHAR; + } + url = String.format("%s%s%s=%s", url, type, contentField, msg); + } + } + + /** + * set header params + */ + private void setHeader() { + + if (httpRequest == null) { + return; + } + + HashMap map = JSONUtils.parseObject(headerParams, HashMap.class); + for (Map.Entry entry : map.entrySet()) { + httpRequest.setHeader(entry.getKey(), String.valueOf(entry.getValue())); + } + } + + /** + * set body params + */ + private String setMsgInRequestBody(String msg) { + ObjectNode objectNode = JSONUtils.parseObject(bodyParams); + //set msg content field + objectNode.put(contentField, msg); + return objectNode.toString(); + } + +} diff --git a/dolphinscheduler-plugin-api/src/test/java/org/apache/dolphinscheduler/plugin/model/AlertInfoTest.java b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-http/src/test/java/org/apache/dolphinscheduler/plugin/alert/http/HttpAlertChannelFactoryTest.java similarity index 53% rename from dolphinscheduler-plugin-api/src/test/java/org/apache/dolphinscheduler/plugin/model/AlertInfoTest.java rename to dolphinscheduler-alert-plugin/dolphinscheduler-alert-http/src/test/java/org/apache/dolphinscheduler/plugin/alert/http/HttpAlertChannelFactoryTest.java index 13eb595ac3..25181ebd26 100644 --- a/dolphinscheduler-plugin-api/src/test/java/org/apache/dolphinscheduler/plugin/model/AlertInfoTest.java +++ b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-http/src/test/java/org/apache/dolphinscheduler/plugin/alert/http/HttpAlertChannelFactoryTest.java @@ -14,41 +14,41 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.dolphinscheduler.plugin.model; -import org.junit.Before; -import org.junit.Test; +package org.apache.dolphinscheduler.plugin.alert.http; -import java.util.HashMap; -import java.util.Map; +import org.apache.dolphinscheduler.spi.alert.AlertChannel; +import org.apache.dolphinscheduler.spi.params.base.PluginParams; -import static org.junit.Assert.*; +import java.util.List; -public class AlertInfoTest { +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; - private AlertInfo alertInfo; +/** + * HttpAlertChannelFactory UT + */ +public class HttpAlertChannelFactoryTest { + + private HttpAlertChannelFactory httpAlertChannelFactory; @Before - public void before() { - alertInfo = new AlertInfo(); + public void init() { + httpAlertChannelFactory = new HttpAlertChannelFactory(); } @Test - public void getAlertProps() { - Map map = new HashMap<>(); - alertInfo.setAlertProps(map); - assertNotNull(alertInfo.getAlertProps()); - } + public void getParamsTest() { - @Test - public void getProp() { - alertInfo.addProp("k", "v"); - assertEquals("v", alertInfo.getProp("k")); + List pluginParamsList = httpAlertChannelFactory.getParams(); + Assert.assertEquals(5, pluginParamsList.size()); } @Test - public void getAlertData() { - alertInfo.setAlertData(new AlertData()); - assertNotNull(alertInfo.getAlertData()); + public void createTest() { + AlertChannel alertChannel = httpAlertChannelFactory.create(); + Assert.assertNotNull(alertChannel); } -} \ No newline at end of file + +} diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-http/src/test/java/org/apache/dolphinscheduler/plugin/alert/http/HttpAlertChannelTest.java b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-http/src/test/java/org/apache/dolphinscheduler/plugin/alert/http/HttpAlertChannelTest.java new file mode 100644 index 0000000000..31a438b4fc --- /dev/null +++ b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-http/src/test/java/org/apache/dolphinscheduler/plugin/alert/http/HttpAlertChannelTest.java @@ -0,0 +1,104 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.dolphinscheduler.plugin.alert.http; + +import org.apache.dolphinscheduler.spi.alert.AlertData; +import org.apache.dolphinscheduler.spi.alert.AlertInfo; +import org.apache.dolphinscheduler.spi.alert.AlertResult; +import org.apache.dolphinscheduler.spi.params.InputParam; +import org.apache.dolphinscheduler.spi.params.base.PluginParams; +import org.apache.dolphinscheduler.spi.params.base.Validate; +import org.apache.dolphinscheduler.spi.utils.JSONUtils; + +import java.util.ArrayList; +import java.util.List; + +import org.junit.Assert; +import org.junit.Test; + +/** + * HttpAlertChannel UT + */ +public class HttpAlertChannelTest { + + @Test + public void processTest() { + + HttpAlertChannel alertChannel = new HttpAlertChannel(); + AlertInfo alertInfo = new AlertInfo(); + AlertData alertData = new AlertData(); + alertData.setContent("Fault tolerance warning"); + alertInfo.setAlertData(alertData); + AlertResult alertResult = alertChannel.process(alertInfo); + Assert.assertEquals("Request types are not supported", alertResult.getMessage()); + } + + @Test + public void processTest2() { + + HttpAlertChannel alertChannel = new HttpAlertChannel(); + AlertInfo alertInfo = new AlertInfo(); + AlertData alertData = new AlertData(); + alertData.setContent("Fault tolerance warning"); + alertInfo.setAlertData(alertData); + alertInfo.setAlertParams(getParams()); + AlertResult alertResult = alertChannel.process(alertInfo); + Assert.assertEquals("true", alertResult.getStatus()); + } + + /** + * create params + */ + private String getParams() { + + List paramsList = new ArrayList<>(); + InputParam urlParam = InputParam.newBuilder("url", "url") + .setValue("http://www.baidu.com") + .addValidate(Validate.newBuilder().setRequired(true).build()) + .build(); + + InputParam headerParams = InputParam.newBuilder("headerParams", "headerParams") + .addValidate(Validate.newBuilder().setRequired(true).build()) + .setValue("{\"Content-Type\":\"application/json\"}") + .build(); + + InputParam bodyParams = InputParam.newBuilder("bodyParams", "bodyParams") + .addValidate(Validate.newBuilder().setRequired(true).build()) + .setValue("{\"number\":\"13457654323\"}") + .build(); + + InputParam content = InputParam.newBuilder("contentField", "contentField") + .setValue("content") + .addValidate(Validate.newBuilder().setRequired(true).build()) + .build(); + + InputParam requestType = InputParam.newBuilder("requestType", "requestType") + .setValue("POST") + .addValidate(Validate.newBuilder().setRequired(true).build()) + .build(); + + paramsList.add(urlParam); + paramsList.add(headerParams); + paramsList.add(bodyParams); + paramsList.add(content); + paramsList.add(requestType); + + return JSONUtils.toJsonString(paramsList); + } + +} diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-http/src/test/java/org/apache/dolphinscheduler/plugin/alert/http/HttpAlertPluginTest.java b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-http/src/test/java/org/apache/dolphinscheduler/plugin/alert/http/HttpAlertPluginTest.java new file mode 100644 index 0000000000..7dac686e88 --- /dev/null +++ b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-http/src/test/java/org/apache/dolphinscheduler/plugin/alert/http/HttpAlertPluginTest.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.http; + +import org.apache.dolphinscheduler.spi.alert.AlertChannelFactory; + +import org.junit.Assert; +import org.junit.Test; + +/** + * HttpAlertPlugin UT + */ +public class HttpAlertPluginTest { + + @Test + public void getAlertChannelFactorysTest() { + + HttpAlertPlugin httpAlertPlugin = new HttpAlertPlugin(); + Iterable alertChannelFactorys = httpAlertPlugin.getAlertChannelFactorys(); + Assert.assertNotNull(alertChannelFactorys); + + } +} diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-http/src/test/java/org/apache/dolphinscheduler/plugin/alert/http/HttpSenderTest.java b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-http/src/test/java/org/apache/dolphinscheduler/plugin/alert/http/HttpSenderTest.java new file mode 100644 index 0000000000..d59c4d47bb --- /dev/null +++ b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-http/src/test/java/org/apache/dolphinscheduler/plugin/alert/http/HttpSenderTest.java @@ -0,0 +1,46 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.dolphinscheduler.plugin.alert.http; + +import org.apache.dolphinscheduler.spi.alert.AlertResult; + +import java.util.HashMap; +import java.util.Map; + +import org.junit.Assert; +import org.junit.Test; + +/** + * HttpSender UT + */ +public class HttpSenderTest { + + @Test + public void sendTest() { + + Map paramsMap = new HashMap<>(); + paramsMap.put(HttpAlertConstants.URL, "http://www.baidu.com"); + paramsMap.put(HttpAlertConstants.REQUEST_TYPE, "POST"); + paramsMap.put(HttpAlertConstants.HEADER_PARAMS, "{\"Content-Type\":\"application/json\"}"); + paramsMap.put(HttpAlertConstants.BODY_PARAMS, "{\"number\":\"13457654323\"}"); + paramsMap.put(HttpAlertConstants.CONTENT_FIELD, "content"); + HttpSender httpSender = new HttpSender(paramsMap); + AlertResult alertResult = httpSender.send("Fault tolerance warning"); + Assert.assertEquals("true", alertResult.getStatus()); + } +} diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-script/pom.xml b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-script/pom.xml new file mode 100644 index 0000000000..8c35b3cbf6 --- /dev/null +++ b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-script/pom.xml @@ -0,0 +1,79 @@ + + + + + dolphinscheduler-alert-plugin + org.apache.dolphinscheduler + 1.3.4-SNAPSHOT + + 4.0.0 + + org.apache.dolphinscheduler + dolphinscheduler-alert-script + dolphinscheduler-plugin + + + + + org.apache.dolphinscheduler + dolphinscheduler-spi + provided + + + + com.google.guava + guava + + + + ch.qos.logback + logback-classic + + + + org.slf4j + slf4j-api + + + + com.fasterxml.jackson.core + jackson-annotations + provided + + + + junit + junit + test + + + + org.mockito + mockito-core + jar + test + + + + + dolphinscheduler-alert-script-${project.version} + + + \ No newline at end of file diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-script/src/main/java/org/apache/dolphinscheduler/plugin/alert/script/OSUtils.java b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-script/src/main/java/org/apache/dolphinscheduler/plugin/alert/script/OSUtils.java new file mode 100644 index 0000000000..acf3e310cc --- /dev/null +++ b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-script/src/main/java/org/apache/dolphinscheduler/plugin/alert/script/OSUtils.java @@ -0,0 +1,32 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.dolphinscheduler.plugin.alert.script; + +/** + * OSUtils + */ +public class OSUtils { + + public OSUtils() { + throw new UnsupportedOperationException("Construct OSUtils"); + } + + static Boolean isWindows() { + return System.getProperty("os.name").startsWith("Windows"); + } +} diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-script/src/main/java/org/apache/dolphinscheduler/plugin/alert/script/ProcessUtils.java b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-script/src/main/java/org/apache/dolphinscheduler/plugin/alert/script/ProcessUtils.java new file mode 100644 index 0000000000..d63a350051 --- /dev/null +++ b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-script/src/main/java/org/apache/dolphinscheduler/plugin/alert/script/ProcessUtils.java @@ -0,0 +1,62 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.dolphinscheduler.plugin.alert.script; + +import java.io.IOException; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * ProcessUtils + */ +public class ProcessUtils { + + private static final Logger logger = LoggerFactory.getLogger(ProcessUtils.class); + + private ProcessUtils() { + throw new IllegalStateException("Utility class"); + } + + /** + * executeScript + * + * @param cmd cmd params + * @return exit code + */ + static Integer executeScript(String... cmd) { + + int exitCode = -1; + + ProcessBuilder processBuilder = new ProcessBuilder(cmd); + try { + Process process = processBuilder.start(); + StreamGobbler inputStreamGobbler = new StreamGobbler(process.getInputStream()); + StreamGobbler errorStreamGobbler = new StreamGobbler(process.getErrorStream()); + + inputStreamGobbler.start(); + errorStreamGobbler.start(); + return process.waitFor(); + } catch (IOException | InterruptedException e) { + logger.error("execute alert script error {}", e.getMessage()); + Thread.currentThread().interrupt(); + } + + return exitCode; + } +} diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-script/src/main/java/org/apache/dolphinscheduler/plugin/alert/script/ScriptAlertChannel.java b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-script/src/main/java/org/apache/dolphinscheduler/plugin/alert/script/ScriptAlertChannel.java new file mode 100644 index 0000000000..2a0021277d --- /dev/null +++ b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-script/src/main/java/org/apache/dolphinscheduler/plugin/alert/script/ScriptAlertChannel.java @@ -0,0 +1,40 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.dolphinscheduler.plugin.alert.script; + +import org.apache.dolphinscheduler.spi.alert.AlertChannel; +import org.apache.dolphinscheduler.spi.alert.AlertData; +import org.apache.dolphinscheduler.spi.alert.AlertInfo; +import org.apache.dolphinscheduler.spi.alert.AlertResult; +import org.apache.dolphinscheduler.spi.params.PluginParamsTransfer; + +import java.util.Map; + +/** + * ScriptAlertChannel + */ +public class ScriptAlertChannel implements AlertChannel { + + @Override + public AlertResult process(AlertInfo alertinfo) { + AlertData alertData = alertinfo.getAlertData(); + String alertParams = alertinfo.getAlertParams(); + Map paramsMap = PluginParamsTransfer.getPluginParamsMap(alertParams); + return new ScriptSender(paramsMap).sendScriptAlert(alertData.getTitle()); + } +} diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-script/src/main/java/org/apache/dolphinscheduler/plugin/alert/script/ScriptAlertChannelFactory.java b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-script/src/main/java/org/apache/dolphinscheduler/plugin/alert/script/ScriptAlertChannelFactory.java new file mode 100644 index 0000000000..70ab76381a --- /dev/null +++ b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-script/src/main/java/org/apache/dolphinscheduler/plugin/alert/script/ScriptAlertChannelFactory.java @@ -0,0 +1,71 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.dolphinscheduler.plugin.alert.script; + +import org.apache.dolphinscheduler.spi.alert.AlertChannel; +import org.apache.dolphinscheduler.spi.alert.AlertChannelFactory; +import org.apache.dolphinscheduler.spi.params.InputParam; +import org.apache.dolphinscheduler.spi.params.RadioParam; +import org.apache.dolphinscheduler.spi.params.base.ParamsOptions; +import org.apache.dolphinscheduler.spi.params.base.PluginParams; +import org.apache.dolphinscheduler.spi.params.base.Validate; + +import java.util.Arrays; +import java.util.List; + +/** + * ScriptAlertChannelFactory + */ +public class ScriptAlertChannelFactory implements AlertChannelFactory { + + @Override + public String getName() { + return "Script"; + } + + @Override + public List getParams() { + + InputParam scriptUserParam = InputParam.newBuilder(ScriptParamsConstants.NAME_SCRIPT_USER_PARAMS, ScriptParamsConstants.SCRIPT_USER_PARAMS) + .addValidate(Validate.newBuilder() + .setRequired(false) + .build()) + .setPlaceholder("please enter your custom parameters, which will be passed to you when calling your script") + .build(); + // need check file type and file exist + InputParam scriptPathParam = InputParam.newBuilder(ScriptParamsConstants.NAME_SCRIPT_PATH, ScriptParamsConstants.SCRIPT_PATH) + .addValidate(Validate.newBuilder() + .setRequired(true) + .build()) + .setPlaceholder("please upload the file to the disk directory of the alert server, and ensure that the path is absolute and has the corresponding access rights") + .build(); + + RadioParam scriptTypeParams = RadioParam.newBuilder(ScriptParamsConstants.NAME_SCRIPT_TYPE, ScriptParamsConstants.SCRIPT_TYPE) + .addParamsOptions(new ParamsOptions(ScriptType.SHELL.getDescp(), ScriptType.SHELL.getCode(), false)) + .setValue(ScriptType.SHELL.getCode()) + .addValidate(Validate.newBuilder().setRequired(true).build()) + .build(); + + return Arrays.asList(scriptUserParam, scriptPathParam, scriptTypeParams); + } + + @Override + public AlertChannel create() { + return new ScriptAlertChannel(); + } +} diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-script/src/main/java/org/apache/dolphinscheduler/plugin/alert/script/ScriptAlertPlugin.java b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-script/src/main/java/org/apache/dolphinscheduler/plugin/alert/script/ScriptAlertPlugin.java new file mode 100644 index 0000000000..f2ba0e87d0 --- /dev/null +++ b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-script/src/main/java/org/apache/dolphinscheduler/plugin/alert/script/ScriptAlertPlugin.java @@ -0,0 +1,35 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.dolphinscheduler.plugin.alert.script; + +import org.apache.dolphinscheduler.spi.DolphinSchedulerPlugin; +import org.apache.dolphinscheduler.spi.alert.AlertChannelFactory; + +import com.google.common.collect.ImmutableList; + +/** + * ScriptAlertPlugin + */ +public class ScriptAlertPlugin implements DolphinSchedulerPlugin { + + @Override + public Iterable getAlertChannelFactorys() { + return ImmutableList.of(new ScriptAlertChannelFactory()); + } + +} diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-script/src/main/java/org/apache/dolphinscheduler/plugin/alert/script/ScriptParamsConstants.java b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-script/src/main/java/org/apache/dolphinscheduler/plugin/alert/script/ScriptParamsConstants.java new file mode 100644 index 0000000000..98e4eee788 --- /dev/null +++ b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-script/src/main/java/org/apache/dolphinscheduler/plugin/alert/script/ScriptParamsConstants.java @@ -0,0 +1,40 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.dolphinscheduler.plugin.alert.script; + +/** + * ScriptParamsConstants + */ +public class ScriptParamsConstants { + + public ScriptParamsConstants() { + throw new IllegalStateException("Utility class"); + } + + static final String SCRIPT_TYPE = "type"; + + static final String NAME_SCRIPT_TYPE = "type"; + + static final String SCRIPT_PATH = "path"; + + static final String NAME_SCRIPT_PATH = "path"; + + static final String SCRIPT_USER_PARAMS = "user.params"; + + static final String NAME_SCRIPT_USER_PARAMS = "userParams"; +} diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-script/src/main/java/org/apache/dolphinscheduler/plugin/alert/script/ScriptSender.java b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-script/src/main/java/org/apache/dolphinscheduler/plugin/alert/script/ScriptSender.java new file mode 100644 index 0000000000..377c318b8e --- /dev/null +++ b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-script/src/main/java/org/apache/dolphinscheduler/plugin/alert/script/ScriptSender.java @@ -0,0 +1,74 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.dolphinscheduler.plugin.alert.script; + +import org.apache.dolphinscheduler.spi.alert.AlertResult; + +import java.util.Map; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * ScriptSender + */ +public class ScriptSender { + + private static final Logger logger = LoggerFactory.getLogger(ScriptSender.class); + + private String scriptPath; + + private Integer scriptType; + + private String userParams; + + ScriptSender(Map config) { + scriptPath = config.get(ScriptParamsConstants.NAME_SCRIPT_PATH); + scriptType = Integer.parseInt(config.get(ScriptParamsConstants.NAME_SCRIPT_TYPE)); + userParams = config.get(ScriptParamsConstants.NAME_SCRIPT_USER_PARAMS); + } + + AlertResult sendScriptAlert(String msg) { + AlertResult alertResult = new AlertResult(); + if (ScriptType.of(scriptType).equals(ScriptType.SHELL)) { + return executeShellScript(msg); + } + return alertResult; + } + + private AlertResult executeShellScript(String msg) { + AlertResult alertResult = new AlertResult(); + alertResult.setStatus("false"); + if (Boolean.TRUE.equals(OSUtils.isWindows())) { + alertResult.setMessage("shell script not support windows os"); + return alertResult; + } + String[] cmd = {"/bin/sh", "-c", scriptPath + " " + msg + " " + userParams}; + int exitCode = ProcessUtils.executeScript(cmd); + + if (exitCode == 0) { + alertResult.setStatus("true"); + alertResult.setMessage("send script alert msg success"); + return alertResult; + } + alertResult.setMessage("send script alert msg error,exitCode is " + exitCode); + logger.info("send script alert msg error,exitCode is {}", exitCode); + return alertResult; + } + +} diff --git a/dolphinscheduler-plugin-api/src/main/java/org/apache/dolphinscheduler/plugin/model/AlertInfo.java b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-script/src/main/java/org/apache/dolphinscheduler/plugin/alert/script/ScriptType.java similarity index 51% rename from dolphinscheduler-plugin-api/src/main/java/org/apache/dolphinscheduler/plugin/model/AlertInfo.java rename to dolphinscheduler-alert-plugin/dolphinscheduler-alert-script/src/main/java/org/apache/dolphinscheduler/plugin/alert/script/ScriptType.java index 1d71ed7d8a..59b17d0a58 100644 --- a/dolphinscheduler-plugin-api/src/main/java/org/apache/dolphinscheduler/plugin/model/AlertInfo.java +++ b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-script/src/main/java/org/apache/dolphinscheduler/plugin/alert/script/ScriptType.java @@ -14,48 +14,49 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.dolphinscheduler.plugin.model; + +package org.apache.dolphinscheduler.plugin.alert.script; import java.util.HashMap; import java.util.Map; /** - * AlertInfo + * ScriptType */ -public class AlertInfo { +public enum ScriptType { - private Map alertProps; - private AlertData alertData; + SHELL(0, "SHELL"), + ; - public AlertInfo() { - this.alertProps = new HashMap<>(); + ScriptType(int code, String descp) { + this.code = code; + this.descp = descp; } - public Map getAlertProps() { - return alertProps; - } + private final int code; + private final String descp; - public AlertInfo setAlertProps(Map alertProps) { - this.alertProps = alertProps; - return this; + public int getCode() { + return code; } - public AlertInfo addProp(String key, Object value) { - this.alertProps.put(key, value); - return this; + public String getDescp() { + return descp; } - public Object getProp(String key) { - return this.alertProps.get(key); - } + private static final Map SCRIPT_TYPE_MAP = new HashMap<>(); - public AlertData getAlertData() { - return alertData; + static { + for (ScriptType scriptType : ScriptType.values()) { + SCRIPT_TYPE_MAP.put(scriptType.code, scriptType); + } } - public AlertInfo setAlertData(AlertData alertData) { - this.alertData = alertData; - return this; + public static ScriptType of(Integer code) { + if (SCRIPT_TYPE_MAP.containsKey(code)) { + return SCRIPT_TYPE_MAP.get(code); + } + throw new IllegalArgumentException("invalid code : " + code); } } diff --git a/dolphinscheduler-alert/src/main/java/org/apache/dolphinscheduler/alert/manager/DingTalkManager.java b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-script/src/main/java/org/apache/dolphinscheduler/plugin/alert/script/StreamGobbler.java similarity index 50% rename from dolphinscheduler-alert/src/main/java/org/apache/dolphinscheduler/alert/manager/DingTalkManager.java rename to dolphinscheduler-alert-plugin/dolphinscheduler-alert-script/src/main/java/org/apache/dolphinscheduler/plugin/alert/script/StreamGobbler.java index 6840794026..2ec25280b4 100644 --- a/dolphinscheduler-alert/src/main/java/org/apache/dolphinscheduler/alert/manager/DingTalkManager.java +++ b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-script/src/main/java/org/apache/dolphinscheduler/plugin/alert/script/StreamGobbler.java @@ -14,40 +14,48 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.dolphinscheduler.alert.manager; -import org.apache.dolphinscheduler.alert.utils.Constants; -import org.apache.dolphinscheduler.alert.utils.DingTalkUtils; -import org.apache.dolphinscheduler.plugin.model.AlertInfo; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +package org.apache.dolphinscheduler.plugin.alert.script; +import java.io.BufferedReader; import java.io.IOException; -import java.util.HashMap; -import java.util.Map; +import java.io.InputStream; +import java.io.InputStreamReader; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** - * Ding Talk Manager + * StreamGobbler */ -public class DingTalkManager { - private static final Logger logger = LoggerFactory.getLogger(EnterpriseWeChatManager.class); +public class StreamGobbler extends Thread { + + private static final Logger logger = LoggerFactory.getLogger(StreamGobbler.class); + + private InputStream inputStream; + + StreamGobbler(InputStream inputStream) { + this.inputStream = inputStream; + } + + @Override + public void run() { + InputStreamReader inputStreamReader = new InputStreamReader(inputStream); + BufferedReader inputBufferReader = new BufferedReader(inputStreamReader); - public Map send(AlertInfo alert) { - Map retMap = new HashMap<>(); - retMap.put(Constants.STATUS, false); - logger.info("send message {}", alert.getAlertData().getTitle()); try { - String msg = buildMessage(alert); - DingTalkUtils.sendDingTalkMsg(msg, Constants.UTF_8); + String line; + StringBuilder output = new StringBuilder(); + while ((line = inputBufferReader.readLine()) != null) { + output.append(line); + output.append(System.getProperty("line.separator")); + } + if (output.length() > 0) { + logger.info("out put msg is{}",output.toString()); + } } catch (IOException e) { - logger.error(e.getMessage(),e); + logger.error("I/O error occurs {}", e.getMessage()); } - retMap.put(Constants.STATUS, true); - return retMap; } - private String buildMessage(AlertInfo alert) { - String msg = alert.getAlertData().getContent(); - return msg; - } -} +} \ No newline at end of file diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-script/src/test/java/org/apache/dolphinscheduler/plugin/alert/script/ProcessUtilsTest.java b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-script/src/test/java/org/apache/dolphinscheduler/plugin/alert/script/ProcessUtilsTest.java new file mode 100644 index 0000000000..1bf98d2019 --- /dev/null +++ b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-script/src/test/java/org/apache/dolphinscheduler/plugin/alert/script/ProcessUtilsTest.java @@ -0,0 +1,37 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.dolphinscheduler.plugin.alert.script; + +import org.junit.Test; + +/** + * ProcessUtilsTest + */ +public class ProcessUtilsTest { + + private static final String rootPath = System.getProperty("user.dir"); + + private static final String shellFilPath = rootPath + "/dolphinscheduler-alert-plugin/dolphinscheduler-alert-script/src/test/script/shell/example.sh"; + + private String[] cmd = {"/bin/sh", "-c", shellFilPath + " " + "testMsg" + " " + "userParams"}; + + @Test + public void testExecuteScript() { + ProcessUtils.executeScript(cmd); + } +} diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-script/src/test/java/org/apache/dolphinscheduler/plugin/alert/script/ScriptAlertChannelFactoryTest.java b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-script/src/test/java/org/apache/dolphinscheduler/plugin/alert/script/ScriptAlertChannelFactoryTest.java new file mode 100644 index 0000000000..72f2197315 --- /dev/null +++ b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-script/src/test/java/org/apache/dolphinscheduler/plugin/alert/script/ScriptAlertChannelFactoryTest.java @@ -0,0 +1,48 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.dolphinscheduler.plugin.alert.script; + +import org.apache.dolphinscheduler.spi.alert.AlertChannel; +import org.apache.dolphinscheduler.spi.params.base.PluginParams; +import org.apache.dolphinscheduler.spi.utils.JSONUtils; + +import java.util.List; + +import org.junit.Assert; +import org.junit.Test; + +/** + * ScriptAlertChannelFactoryTest + */ +public class ScriptAlertChannelFactoryTest { + + @Test + public void testGetParams() { + ScriptAlertChannelFactory scriptAlertChannelFactory = new ScriptAlertChannelFactory(); + List params = scriptAlertChannelFactory.getParams(); + JSONUtils.toJsonString(params); + Assert.assertEquals(3, params.size()); + } + + @Test + public void testCreate() { + ScriptAlertChannelFactory scriptAlertChannelFactory = new ScriptAlertChannelFactory(); + AlertChannel alertChannel = scriptAlertChannelFactory.create(); + Assert.assertNotNull(alertChannel); + } +} diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-script/src/test/java/org/apache/dolphinscheduler/plugin/alert/script/ScriptSenderTest.java b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-script/src/test/java/org/apache/dolphinscheduler/plugin/alert/script/ScriptSenderTest.java new file mode 100644 index 0000000000..1cd74cfaba --- /dev/null +++ b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-script/src/test/java/org/apache/dolphinscheduler/plugin/alert/script/ScriptSenderTest.java @@ -0,0 +1,58 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.dolphinscheduler.plugin.alert.script; + +import org.apache.dolphinscheduler.spi.alert.AlertResult; + +import java.util.HashMap; +import java.util.Map; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +/** + * ScriptSenderTest + */ +public class ScriptSenderTest { + + private static Map scriptConfig = new HashMap<>(); + + private static final String rootPath = System.getProperty("user.dir"); + + private static final String shellFilPath = rootPath + "/src/test/script/shell/scriptTest.sh"; + + @Before + public void initScriptConfig() { + + scriptConfig.put(ScriptParamsConstants.NAME_SCRIPT_TYPE, String.valueOf(ScriptType.SHELL.getCode())); + scriptConfig.put(ScriptParamsConstants.NAME_SCRIPT_USER_PARAMS, "userParams"); + scriptConfig.put(ScriptParamsConstants.NAME_SCRIPT_PATH, shellFilPath); + } + + @Test + public void testScriptSenderTest() { + ScriptSender scriptSender = new ScriptSender(scriptConfig); + AlertResult alertResult; + alertResult = scriptSender.sendScriptAlert("success"); + Assert.assertEquals("true", alertResult.getStatus()); + alertResult = scriptSender.sendScriptAlert("errorMsg"); + Assert.assertEquals("false", alertResult.getStatus()); + } + +} diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-script/src/test/script/shell/example.sh b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-script/src/test/script/shell/example.sh new file mode 100755 index 0000000000..708dcd004b --- /dev/null +++ b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-script/src/test/script/shell/example.sh @@ -0,0 +1,25 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + + +msg=$1 +content=$2 + +# Write your specific logic here + +# Set the exit code according to your execution result, and alert needs to use it to judge the status of this alarm result +exit 0 diff --git a/dolphinscheduler-plugin-api/src/test/resources/plugin.properties b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-script/src/test/script/shell/scriptTest.sh old mode 100644 new mode 100755 similarity index 91% rename from dolphinscheduler-plugin-api/src/test/resources/plugin.properties rename to dolphinscheduler-alert-plugin/dolphinscheduler-alert-script/src/test/script/shell/scriptTest.sh index d2ea3831be..02eba48a81 --- a/dolphinscheduler-plugin-api/src/test/resources/plugin.properties +++ b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-script/src/test/script/shell/scriptTest.sh @@ -15,8 +15,11 @@ # limitations under the License. # -test.string=teststring -test.false=false -test.true=true -cba=3.1 -test.long=100 \ No newline at end of file +msg=$1 +content=$2 + +if [ $msg = errorMsg ] + then + exit 12 +fi +exit 0 \ No newline at end of file diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-wechat/pom.xml b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-wechat/pom.xml new file mode 100644 index 0000000000..123cebc5c5 --- /dev/null +++ b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-wechat/pom.xml @@ -0,0 +1,78 @@ + + + + + dolphinscheduler-alert-plugin + org.apache.dolphinscheduler + 1.3.4-SNAPSHOT + + 4.0.0 + + org.apache.dolphinscheduler + dolphinscheduler-alert-wechat + dolphinscheduler-plugin + + + + org.apache.dolphinscheduler + dolphinscheduler-spi + provided + + + + com.google.guava + guava + + + + ch.qos.logback + logback-classic + + + + org.apache.httpcomponents + httpclient + + + + com.fasterxml.jackson.core + jackson-databind + provided + + + + junit + junit + test + + + + org.mockito + mockito-core + jar + test + + + + + + dolphinscheduler-alert-wechat-${project.version} + + \ No newline at end of file diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-wechat/src/main/java/org/apache/dolphinscheduler/plugin/alert/wechat/WeChatAlertChannel.java b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-wechat/src/main/java/org/apache/dolphinscheduler/plugin/alert/wechat/WeChatAlertChannel.java new file mode 100644 index 0000000000..4cdd4d375c --- /dev/null +++ b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-wechat/src/main/java/org/apache/dolphinscheduler/plugin/alert/wechat/WeChatAlertChannel.java @@ -0,0 +1,41 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.dolphinscheduler.plugin.alert.wechat; + +import org.apache.dolphinscheduler.spi.alert.AlertChannel; +import org.apache.dolphinscheduler.spi.alert.AlertData; +import org.apache.dolphinscheduler.spi.alert.AlertInfo; +import org.apache.dolphinscheduler.spi.alert.AlertResult; +import org.apache.dolphinscheduler.spi.params.PluginParamsTransfer; + +import java.util.Map; + +/** + * WeChatAlertChannel + */ +public class WeChatAlertChannel implements AlertChannel { + + @Override + public AlertResult process(AlertInfo info) { + AlertData alertData = info.getAlertData(); + String alertParams = info.getAlertParams(); + Map paramsMap = PluginParamsTransfer.getPluginParamsMap(alertParams); + return new WeChatSender(paramsMap).sendEnterpriseWeChat(alertData.getTitle(), alertData.getContent()); + + } +} diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-wechat/src/main/java/org/apache/dolphinscheduler/plugin/alert/wechat/WeChatAlertChannelFactory.java b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-wechat/src/main/java/org/apache/dolphinscheduler/plugin/alert/wechat/WeChatAlertChannelFactory.java new file mode 100644 index 0000000000..636c571322 --- /dev/null +++ b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-wechat/src/main/java/org/apache/dolphinscheduler/plugin/alert/wechat/WeChatAlertChannelFactory.java @@ -0,0 +1,94 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.dolphinscheduler.plugin.alert.wechat; + +import org.apache.dolphinscheduler.spi.alert.AlertChannel; +import org.apache.dolphinscheduler.spi.alert.AlertChannelFactory; +import org.apache.dolphinscheduler.spi.alert.AlertConstants; +import org.apache.dolphinscheduler.spi.alert.ShowType; +import org.apache.dolphinscheduler.spi.params.InputParam; +import org.apache.dolphinscheduler.spi.params.RadioParam; +import org.apache.dolphinscheduler.spi.params.base.ParamsOptions; +import org.apache.dolphinscheduler.spi.params.base.PluginParams; +import org.apache.dolphinscheduler.spi.params.base.Validate; + +import java.util.Arrays; +import java.util.List; + +/** + * WeChatAlertChannelFactory + */ +public class WeChatAlertChannelFactory implements AlertChannelFactory { + + @Override + public String getName() { + return "WeChat"; + } + + @Override + public List getParams() { + InputParam corpIdParam = InputParam.newBuilder(WeChatAlertParamsConstants.NAME_ENTERPRISE_WE_CHAT_CORP_ID, WeChatAlertParamsConstants.ENTERPRISE_WE_CHAT_CORP_ID) + .setPlaceholder("please input corp id ") + .addValidate(Validate.newBuilder() + .setRequired(true) + .build()) + .build(); + + InputParam secretParam = InputParam.newBuilder(WeChatAlertParamsConstants.NAME_ENTERPRISE_WE_CHAT_SECRET, WeChatAlertParamsConstants.ENTERPRISE_WE_CHAT_SECRET) + .setPlaceholder("please input secret ") + .addValidate(Validate.newBuilder() + .setRequired(true) + .build()) + .build(); + + InputParam usersParam = InputParam.newBuilder(WeChatAlertParamsConstants.NAME_ENTERPRISE_WE_CHAT_USERS, WeChatAlertParamsConstants.ENTERPRISE_WE_CHAT_USERS) + .setPlaceholder("please input users ") + .addValidate(Validate.newBuilder() + .setRequired(true) + .build()) + .build(); + + InputParam userSendMsgParam = InputParam.newBuilder(WeChatAlertParamsConstants.NAME_ENTERPRISE_WE_CHAT_USER_SEND_MSG, WeChatAlertParamsConstants.ENTERPRISE_WE_CHAT_USER_SEND_MSG) + .setPlaceholder("please input corp id ") + .addValidate(Validate.newBuilder() + .setRequired(true) + .build()) + .build(); + + InputParam agentIdParam = InputParam.newBuilder(WeChatAlertParamsConstants.NAME_ENTERPRISE_WE_CHAT_AGENT_ID, WeChatAlertParamsConstants.ENTERPRISE_WE_CHAT_AGENT_ID) + .setPlaceholder("please input agent id ") + .addValidate(Validate.newBuilder() + .setRequired(true) + .build()) + .build(); + + RadioParam showType = RadioParam.newBuilder(AlertConstants.SHOW_TYPE, AlertConstants.SHOW_TYPE) + .addParamsOptions(new ParamsOptions(ShowType.TABLE.getDescp(), ShowType.TABLE.getDescp(), false)) + .addParamsOptions(new ParamsOptions(ShowType.TEXT.getDescp(), ShowType.TEXT.getDescp(), false)) + .setValue(ShowType.TABLE.getDescp()) + .addValidate(Validate.newBuilder().setRequired(true).build()) + .build(); + + return Arrays.asList(corpIdParam, secretParam, usersParam, userSendMsgParam, agentIdParam, showType); + } + + @Override + public AlertChannel create() { + return new WeChatAlertChannel(); + } +} diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-wechat/src/main/java/org/apache/dolphinscheduler/plugin/alert/wechat/WeChatAlertConstants.java b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-wechat/src/main/java/org/apache/dolphinscheduler/plugin/alert/wechat/WeChatAlertConstants.java new file mode 100644 index 0000000000..904060c3e0 --- /dev/null +++ b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-wechat/src/main/java/org/apache/dolphinscheduler/plugin/alert/wechat/WeChatAlertConstants.java @@ -0,0 +1,34 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.dolphinscheduler.plugin.alert.wechat; + +/** + * WeChatAlertConstants + */ +public class WeChatAlertConstants { + + static final String MARKDOWN_QUOTE = ">"; + + static final String MARKDOWN_ENTER = "\n"; + + static final String CHARSET = "UTF-8"; + + static final String WE_CHAT_PUSH_URL = "https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token={token}"; + + static final String WE_CHAT_TOKEN_URL = "https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid={corpId}&corpsecret={secret}"; +} diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-wechat/src/main/java/org/apache/dolphinscheduler/plugin/alert/wechat/WeChatAlertParamsConstants.java b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-wechat/src/main/java/org/apache/dolphinscheduler/plugin/alert/wechat/WeChatAlertParamsConstants.java new file mode 100644 index 0000000000..138bd83b3a --- /dev/null +++ b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-wechat/src/main/java/org/apache/dolphinscheduler/plugin/alert/wechat/WeChatAlertParamsConstants.java @@ -0,0 +1,56 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.dolphinscheduler.plugin.alert.wechat; + +/** + * WeChatAlertParamsConstants + */ +public class WeChatAlertParamsConstants { + + + static final String ENTERPRISE_WE_CHAT_CORP_ID = "corp.id"; + + static final String NAME_ENTERPRISE_WE_CHAT_CORP_ID = "corpId"; + + + static final String ENTERPRISE_WE_CHAT_SECRET = "secret"; + + static final String NAME_ENTERPRISE_WE_CHAT_SECRET = "secret"; + + static final String ENTERPRISE_WE_CHAT_TEAM_SEND_MSG = "team.send.msg"; + + static final String NAME_ENTERPRISE_WE_CHAT_TEAM_SEND_MSG = "teamSendMsg"; + + + static final String ENTERPRISE_WE_CHAT_USER_SEND_MSG = "user.send.msg"; + + static final String NAME_ENTERPRISE_WE_CHAT_USER_SEND_MSG = "userSendMsg"; + + + static final String ENTERPRISE_WE_CHAT_AGENT_ID = "agent.id"; + + static final String NAME_ENTERPRISE_WE_CHAT_AGENT_ID = "agentId"; + + + static final String ENTERPRISE_WE_CHAT_USERS = "users"; + + + static final String NAME_ENTERPRISE_WE_CHAT_USERS = "users"; + + +} diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-wechat/src/main/java/org/apache/dolphinscheduler/plugin/alert/wechat/WeChatAlertPlugin.java b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-wechat/src/main/java/org/apache/dolphinscheduler/plugin/alert/wechat/WeChatAlertPlugin.java new file mode 100644 index 0000000000..56c3c01f20 --- /dev/null +++ b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-wechat/src/main/java/org/apache/dolphinscheduler/plugin/alert/wechat/WeChatAlertPlugin.java @@ -0,0 +1,34 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.dolphinscheduler.plugin.alert.wechat; + +import org.apache.dolphinscheduler.spi.DolphinSchedulerPlugin; +import org.apache.dolphinscheduler.spi.alert.AlertChannelFactory; + +import com.google.common.collect.ImmutableList; + +/** + * WeChatAlertPlugin + */ +public class WeChatAlertPlugin implements DolphinSchedulerPlugin { + + @Override + public Iterable getAlertChannelFactorys() { + return ImmutableList.of(new WeChatAlertChannelFactory()); + } +} diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-wechat/src/main/java/org/apache/dolphinscheduler/plugin/alert/wechat/WeChatSender.java b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-wechat/src/main/java/org/apache/dolphinscheduler/plugin/alert/wechat/WeChatSender.java new file mode 100644 index 0000000000..f4fd090744 --- /dev/null +++ b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-wechat/src/main/java/org/apache/dolphinscheduler/plugin/alert/wechat/WeChatSender.java @@ -0,0 +1,335 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.dolphinscheduler.plugin.alert.wechat; + +import static java.util.Objects.requireNonNull; + +import org.apache.dolphinscheduler.spi.alert.AlertConstants; +import org.apache.dolphinscheduler.spi.alert.AlertResult; +import org.apache.dolphinscheduler.spi.alert.ShowType; +import org.apache.dolphinscheduler.spi.utils.JSONUtils; +import org.apache.dolphinscheduler.spi.utils.StringUtils; + +import org.apache.http.HttpEntity; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.entity.StringEntity; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.util.EntityUtils; + +import java.io.IOException; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * WeChatSender + */ +public class WeChatSender { + + private static Logger logger = LoggerFactory.getLogger(WeChatSender.class); + + private String weChatAgentId; + + private String weChatUsers; + + private String weChatTeamSendMsg; + + private String weChatUserSendMsg; + + private String weChatTokenUrlReplace; + + private String weChatToken; + + private String showType; + + + private static final String agentIdRegExp = "{agentId}"; + private static final String msgRegExp = "{msg}"; + private static final String userRegExp = "{toUser}"; + private static final String corpIdRegex = "{corpId}"; + private static final String secretRegex = "{secret}"; + private static final String toPartyRegex = "{toParty}"; + private static final String toUserRegex = "{toUser}"; + private static final String tokenRegex = "{token}"; + + WeChatSender(Map config) { + weChatAgentId = config.get(WeChatAlertParamsConstants.NAME_ENTERPRISE_WE_CHAT_AGENT_ID); + weChatUsers = config.get(WeChatAlertParamsConstants.NAME_ENTERPRISE_WE_CHAT_USERS); + String weChatCorpId = config.get(WeChatAlertParamsConstants.NAME_ENTERPRISE_WE_CHAT_CORP_ID); + String weChatSecret = config.get(WeChatAlertParamsConstants.NAME_ENTERPRISE_WE_CHAT_SECRET); + String weChatTokenUrl = WeChatAlertConstants.WE_CHAT_TOKEN_URL; + weChatTeamSendMsg = config.get(WeChatAlertParamsConstants.NAME_ENTERPRISE_WE_CHAT_TEAM_SEND_MSG); + weChatUserSendMsg = config.get(WeChatAlertParamsConstants.NAME_ENTERPRISE_WE_CHAT_USER_SEND_MSG); + showType = config.get(AlertConstants.SHOW_TYPE); + requireNonNull(showType, AlertConstants.SHOW_TYPE + " must not null"); + weChatTokenUrlReplace = weChatTokenUrl + .replace(corpIdRegex, weChatCorpId) + .replace(secretRegex, weChatSecret); + weChatToken = getToken(); + } + + /** + * make user multi user message + * + * @param toUser the toUser + * @param agentId the agentId + * @param msg the msg + * @return Enterprise WeChat send message + */ + private String makeUserSendMsg(Collection toUser, String agentId, String msg) { + String listUser = mkString(toUser); + return weChatUserSendMsg.replace(userRegExp, listUser) + .replace(agentIdRegExp, agentId) + .replace(msgRegExp, msg); + } + + /** + * send Enterprise WeChat + * + * @return Enterprise WeChat resp, demo: {"errcode":0,"errmsg":"ok","invaliduser":""} + * @throws Exception the Exception + */ + public AlertResult sendEnterpriseWeChat(String title, String content) { + AlertResult alertResult; + List userList = Arrays.asList(weChatUsers.split(",")); + String data = markdownByAlert(title, content); + String msg = makeUserSendMsg(userList, weChatAgentId, data); + if (null == weChatToken) { + alertResult = new AlertResult(); + alertResult.setMessage("send we chat alert fail,get weChat token error"); + alertResult.setStatus("false"); + return alertResult; + } + String enterpriseWeChatPushUrlReplace = WeChatAlertConstants.WE_CHAT_PUSH_URL.replace(tokenRegex, weChatToken); + + try { + return checkWeChatSendMsgResult(post(enterpriseWeChatPushUrlReplace, msg)); + } catch (Exception e) { + logger.info("send we chat alert msg exception : {}", e.getMessage()); + alertResult = new AlertResult(); + alertResult.setMessage("send we chat alert fail"); + alertResult.setStatus("false"); + } + return alertResult; + } + + private static String post(String url, String data) throws IOException { + try (CloseableHttpClient httpClient = HttpClients.createDefault()) { + HttpPost httpPost = new HttpPost(url); + httpPost.setEntity(new StringEntity(data, WeChatAlertConstants.CHARSET)); + CloseableHttpResponse response = httpClient.execute(httpPost); + String resp; + try { + HttpEntity entity = response.getEntity(); + resp = EntityUtils.toString(entity, WeChatAlertConstants.CHARSET); + EntityUtils.consume(entity); + } finally { + response.close(); + } + logger.info("Enterprise WeChat send [{}], param:{}, resp:{}", + url, data, resp); + return resp; + } + } + + /** + * convert table to markdown style + * + * @param title the title + * @param content the content + * @return markdown table content + */ + private static String markdownTable(String title, String content) { + List mapItemsList = JSONUtils.toList(content, LinkedHashMap.class); + if (null == mapItemsList || mapItemsList.isEmpty()) { + logger.error("itemsList is null"); + throw new RuntimeException("itemsList is null"); + } + StringBuilder contents = new StringBuilder(200); + for (LinkedHashMap mapItems : mapItemsList) { + Set> entries = mapItems.entrySet(); + Iterator> iterator = entries.iterator(); + StringBuilder t = new StringBuilder(String.format("`%s`%s", title, WeChatAlertConstants.MARKDOWN_ENTER)); + + while (iterator.hasNext()) { + + Map.Entry entry = iterator.next(); + t.append(WeChatAlertConstants.MARKDOWN_QUOTE); + t.append(entry.getKey()).append(":").append(entry.getValue()); + t.append(WeChatAlertConstants.MARKDOWN_ENTER); + } + contents.append(t); + } + + return contents.toString(); + } + + /** + * convert text to markdown style + * + * @param title the title + * @param content the content + * @return markdown text + */ + private static String markdownText(String title, String content) { + if (StringUtils.isNotEmpty(content)) { + List mapItemsList = JSONUtils.toList(content, LinkedHashMap.class); + if (null == mapItemsList || mapItemsList.isEmpty()) { + logger.error("itemsList is null"); + throw new RuntimeException("itemsList is null"); + } + + StringBuilder contents = new StringBuilder(100); + contents.append(String.format("`%s`%n", title)); + for (LinkedHashMap mapItems : mapItemsList) { + + Set> entries = mapItems.entrySet(); + for (Entry entry : entries) { + contents.append(WeChatAlertConstants.MARKDOWN_QUOTE); + contents.append(entry.getKey()).append(":").append(entry.getValue()); + contents.append(WeChatAlertConstants.MARKDOWN_ENTER); + } + + } + return contents.toString(); + } + return null; + } + + /** + * Determine the mardown style based on the show type of the alert + * + * @return the markdown alert table/text + */ + private String markdownByAlert(String title, String content) { + String result = ""; + if (showType.equals(ShowType.TABLE.getDescp())) { + result = markdownTable(title, content); + } else if (showType.equals(ShowType.TEXT.getDescp())) { + result = markdownText(title, content); + } + return result; + + } + + private String getToken() { + try { + return get(weChatTokenUrlReplace); + } catch (IOException e) { + logger.info("we chat alert get token error{}", e.getMessage()); + } + return null; + } + + private static String get(String url) throws IOException { + String resp; + + try (CloseableHttpClient httpClient = HttpClients.createDefault()) { + HttpGet httpGet = new HttpGet(url); + try (CloseableHttpResponse response = httpClient.execute(httpGet)) { + HttpEntity entity = response.getEntity(); + resp = EntityUtils.toString(entity, WeChatAlertConstants.CHARSET); + EntityUtils.consume(entity); + } + + HashMap map = JSONUtils.parseObject(resp, HashMap.class); + if (map != null && null != map.get("access_token")) { + return map.get("access_token").toString(); + } else { + return null; + } + } + } + + private static String mkString(Iterable list) { + + if (null == list || StringUtils.isEmpty("|")) { + return null; + } + + StringBuilder sb = new StringBuilder(); + boolean first = true; + for (String item : list) { + if (first) { + first = false; + } else { + sb.append("|"); + } + sb.append(item); + } + return sb.toString(); + } + + public static class WeChatSendMsgResponse { + private Integer errcode; + private String errmsg; + + public Integer getErrcode() { + return errcode; + } + + public void setErrcode(Integer errcode) { + this.errcode = errcode; + } + + public String getErrmsg() { + return errmsg; + } + + public void setErrmsg(String errmsg) { + this.errmsg = errmsg; + } + } + + private static AlertResult checkWeChatSendMsgResult(String result) { + AlertResult alertResult = new AlertResult(); + alertResult.setStatus("false"); + + if (null == result) { + alertResult.setMessage("we chat send fail"); + logger.info("send we chat msg error,resp is null"); + return alertResult; + } + WeChatSendMsgResponse sendMsgResponse = JSONUtils.parseObject(result, WeChatSendMsgResponse.class); + if (null == sendMsgResponse) { + alertResult.setMessage("we chat send fail"); + logger.info("send we chat msg error,resp error"); + return alertResult; + } + if (sendMsgResponse.errcode == 0) { + alertResult.setStatus("true"); + alertResult.setMessage("we chat alert send success"); + return alertResult; + } + alertResult.setStatus("false"); + alertResult.setMessage(sendMsgResponse.getErrmsg()); + return alertResult; + } +} diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-wechat/src/test/java/org/apache/dolphinscheduler/plugin/alert/wechat/WeChatAlertChannelFactoryTest.java b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-wechat/src/test/java/org/apache/dolphinscheduler/plugin/alert/wechat/WeChatAlertChannelFactoryTest.java new file mode 100644 index 0000000000..cc62d5aabf --- /dev/null +++ b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-wechat/src/test/java/org/apache/dolphinscheduler/plugin/alert/wechat/WeChatAlertChannelFactoryTest.java @@ -0,0 +1,48 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.dolphinscheduler.plugin.alert.wechat; + +import org.apache.dolphinscheduler.spi.alert.AlertChannel; +import org.apache.dolphinscheduler.spi.params.base.PluginParams; +import org.apache.dolphinscheduler.spi.utils.JSONUtils; + +import java.util.List; + +import org.junit.Assert; +import org.junit.Test; + +/** + * WeChatAlertChannelFactoryTest + */ +public class WeChatAlertChannelFactoryTest { + + @Test + public void testGetParams() { + WeChatAlertChannelFactory weChatAlertChannelFactory = new WeChatAlertChannelFactory(); + List params = weChatAlertChannelFactory.getParams(); + JSONUtils.toJsonString(params); + Assert.assertEquals(6, params.size()); + } + + @Test + public void testCreate() { + WeChatAlertChannelFactory dingTalkAlertChannelFactory = new WeChatAlertChannelFactory(); + AlertChannel alertChannel = dingTalkAlertChannelFactory.create(); + Assert.assertNotNull(alertChannel); + } +} diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-wechat/src/test/java/org/apache/dolphinscheduler/plugin/alert/wechat/WeChatSenderTest.java b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-wechat/src/test/java/org/apache/dolphinscheduler/plugin/alert/wechat/WeChatSenderTest.java new file mode 100644 index 0000000000..61010ebe3a --- /dev/null +++ b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-wechat/src/test/java/org/apache/dolphinscheduler/plugin/alert/wechat/WeChatSenderTest.java @@ -0,0 +1,89 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.dolphinscheduler.plugin.alert.wechat; + +import org.apache.dolphinscheduler.spi.alert.AlertConstants; +import org.apache.dolphinscheduler.spi.alert.AlertResult; +import org.apache.dolphinscheduler.spi.alert.ShowType; + +import java.util.HashMap; +import java.util.Map; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +/** + * WeChatSenderTest + */ +public class WeChatSenderTest { + + private static Map weChatConfig = new HashMap<>(); + + private String content = "[{\"id\":\"69\"," + + + "\"name\":\"UserBehavior-0--1193959466\"," + + + "\"Job name\":\"Start workflow\"," + + + "\"State\":\"SUCCESS\"," + + + "\"Recovery\":\"NO\"," + + + "\"Run time\":\"1\"," + + + "\"Start time\": \"2018-08-06 10:31:34.0\"," + + + "\"End time\": \"2018-08-06 10:31:49.0\"," + + + "\"Host\": \"192.168.xx.xx\"," + + + "\"Notify group\" :\"4\"}]"; + + @Before + public void initDingTalkConfig() { + // Just for this test, I will delete these configurations before this PR is merged + weChatConfig.put(WeChatAlertParamsConstants.NAME_ENTERPRISE_WE_CHAT_AGENT_ID, "100000"); + weChatConfig.put(WeChatAlertParamsConstants.NAME_ENTERPRISE_WE_CHAT_CORP_ID, "NAME_ENTERPRISE_WE_CHAT_CORP_ID"); + weChatConfig.put(WeChatAlertParamsConstants.NAME_ENTERPRISE_WE_CHAT_SECRET, "NAME_ENTERPRISE_WE_CHAT_SECRET"); + weChatConfig.put(WeChatAlertParamsConstants.NAME_ENTERPRISE_WE_CHAT_USER_SEND_MSG, "{\"touser\":\"{toUser}\",\"agentid\":{agentId}" + + + ",\"msgtype\":\"markdown\",\"markdown\":{\"content\":\"{msg}\"}}" + ); + weChatConfig.put(WeChatAlertParamsConstants.NAME_ENTERPRISE_WE_CHAT_USERS, "Kris"); + weChatConfig.put(WeChatAlertParamsConstants.NAME_ENTERPRISE_WE_CHAT_TEAM_SEND_MSG, "msg"); + weChatConfig.put(AlertConstants.SHOW_TYPE, ShowType.TABLE.getDescp()); + } + + @Test + public void testSendWeChatTableMsg() { + WeChatSender weChatSender = new WeChatSender(weChatConfig); + + AlertResult alertResult = weChatSender.sendEnterpriseWeChat("test", content); + Assert.assertEquals("false", alertResult.getStatus()); + } + + @Test + public void testSendWeChatTextMsg() { + weChatConfig.put(AlertConstants.SHOW_TYPE, ShowType.TEXT.getDescp()); + WeChatSender weChatSender = new WeChatSender(weChatConfig); + AlertResult alertResult = weChatSender.sendEnterpriseWeChat("test", content); + Assert.assertEquals("false", alertResult.getStatus()); + } + +} diff --git a/dolphinscheduler-alert-plugin/pom.xml b/dolphinscheduler-alert-plugin/pom.xml new file mode 100644 index 0000000000..ede5051049 --- /dev/null +++ b/dolphinscheduler-alert-plugin/pom.xml @@ -0,0 +1,41 @@ + + + + + dolphinscheduler + org.apache.dolphinscheduler + 1.3.4-SNAPSHOT + + 4.0.0 + + org.apache.dolphinscheduler + dolphinscheduler-alert-plugin + pom + + + dolphinscheduler-alert-email + dolphinscheduler-alert-wechat + dolphinscheduler-alert-dingtalk + dolphinscheduler-alert-script + dolphinscheduler-alert-http + + + + \ No newline at end of file diff --git a/dolphinscheduler-alert/pom.xml b/dolphinscheduler-alert/pom.xml index a44d101ffe..cea763ccbd 100644 --- a/dolphinscheduler-alert/pom.xml +++ b/dolphinscheduler-alert/pom.xml @@ -32,38 +32,21 @@ - junit - junit - test + org.apache.dolphinscheduler + dolphinscheduler-spi - org.mockito - mockito-core - jar - test + org.apache.dolphinscheduler + dolphinscheduler-remote - - org.powermock - powermock-module-junit4 - test + org.apache.dolphinscheduler + dolphinscheduler-common - - org.powermock - powermock-api-mockito2 + junit + junit test - - - org.mockito - mockito-core - - - - - - org.apache.commons - commons-email @@ -108,6 +91,52 @@ + + org.sonatype.aether + aether-api + provided + + + + io.airlift.resolver + resolver + provided + + + + org.ow2.asm + asm + provided + + + + org.powermock + powermock-module-junit4 + test + + + + org.mockito + mockito-core + test + + + + mysql + mysql-connector-java + + + + org.powermock + powermock-api-mockito2 + test + + + org.mockito + mockito-core + + + diff --git a/dolphinscheduler-alert/src/main/java/org/apache/dolphinscheduler/alert/AlertServer.java b/dolphinscheduler-alert/src/main/java/org/apache/dolphinscheduler/alert/AlertServer.java index 347336cada..54afc93442 100644 --- a/dolphinscheduler-alert/src/main/java/org/apache/dolphinscheduler/alert/AlertServer.java +++ b/dolphinscheduler-alert/src/main/java/org/apache/dolphinscheduler/alert/AlertServer.java @@ -14,21 +14,34 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.dolphinscheduler.alert; -import org.apache.dolphinscheduler.alert.plugin.EmailAlertPlugin; +import static org.apache.dolphinscheduler.common.Constants.ALERT_RPC_PORT; + +import org.apache.dolphinscheduler.alert.plugin.AlertPluginManager; +import org.apache.dolphinscheduler.alert.plugin.DolphinPluginLoader; +import org.apache.dolphinscheduler.alert.plugin.DolphinPluginManagerConfig; +import org.apache.dolphinscheduler.alert.processor.AlertRequestProcessor; import org.apache.dolphinscheduler.alert.runner.AlertSender; import org.apache.dolphinscheduler.alert.utils.Constants; import org.apache.dolphinscheduler.alert.utils.PropertyUtils; -import org.apache.dolphinscheduler.common.plugin.FilePluginManager; import org.apache.dolphinscheduler.common.thread.Stopper; import org.apache.dolphinscheduler.dao.AlertDao; import org.apache.dolphinscheduler.dao.DaoFactory; +import org.apache.dolphinscheduler.dao.PluginDao; import org.apache.dolphinscheduler.dao.entity.Alert; +import org.apache.dolphinscheduler.remote.NettyRemotingServer; +import org.apache.dolphinscheduler.remote.command.CommandType; +import org.apache.dolphinscheduler.remote.config.NettyServerConfig; +import org.apache.dolphinscheduler.spi.utils.StringUtils; + +import java.util.List; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.util.List; +import com.google.common.collect.ImmutableList; /** * alert of start @@ -40,36 +53,75 @@ public class AlertServer { */ private AlertDao alertDao = DaoFactory.getDaoInstance(AlertDao.class); + private PluginDao pluginDao = DaoFactory.getDaoInstance(PluginDao.class); + private AlertSender alertSender; private static AlertServer instance; - private FilePluginManager alertPluginManager; + private AlertPluginManager alertPluginManager; + + private DolphinPluginManagerConfig alertPluginManagerConfig; + + public static final String ALERT_PLUGIN_BINDING = "alert.plugin.binding"; - private static final String[] whitePrefixes = new String[]{"org.apache.dolphinscheduler.plugin.utils."}; + public static final String ALERT_PLUGIN_DIR = "alert.plugin.dir"; - private static final String[] excludePrefixes = new String[]{ - "org.apache.dolphinscheduler.plugin.", - "ch.qos.logback.", - "org.slf4j." - }; + public static final String MAVEN_LOCAL_REPOSITORY = "maven.local.repository"; + + /** + * netty server + */ + private NettyRemotingServer server; + + private static class AlertServerHolder { + private static final AlertServer INSTANCE = new AlertServer(); + } + + public static final AlertServer getInstance() { + return AlertServerHolder.INSTANCE; + + } + + private AlertServer() { - public AlertServer() { - alertPluginManager = - new FilePluginManager(PropertyUtils.getString(Constants.PLUGIN_DIR), whitePrefixes, excludePrefixes); - // add default alert plugins - alertPluginManager.addPlugin(new EmailAlertPlugin()); } - public synchronized static AlertServer getInstance() { - if (null == instance) { - instance = new AlertServer(); + private void initPlugin() { + alertPluginManager = new AlertPluginManager(); + alertPluginManagerConfig = new DolphinPluginManagerConfig(); + alertPluginManagerConfig.setPlugins(PropertyUtils.getString(ALERT_PLUGIN_BINDING)); + if (StringUtils.isNotBlank(PropertyUtils.getString(ALERT_PLUGIN_DIR))) { + alertPluginManagerConfig.setInstalledPluginsDir(PropertyUtils.getString(ALERT_PLUGIN_DIR, Constants.ALERT_PLUGIN_PATH).trim()); + } + + if (StringUtils.isNotBlank(PropertyUtils.getString(MAVEN_LOCAL_REPOSITORY))) { + alertPluginManagerConfig.setMavenLocalRepository(PropertyUtils.getString(MAVEN_LOCAL_REPOSITORY).trim()); + } + + DolphinPluginLoader alertPluginLoader = new DolphinPluginLoader(alertPluginManagerConfig, ImmutableList.of(alertPluginManager)); + try { + alertPluginLoader.loadPlugins(); + } catch (Exception e) { + throw new RuntimeException("load Alert Plugin Failed !", e); } - return instance; } - public void start() { - logger.info("alert server ready start "); + /** + * init netty remoting server + */ + private void initRemoteServer() { + NettyServerConfig serverConfig = new NettyServerConfig(); + serverConfig.setListenPort(ALERT_RPC_PORT); + this.server = new NettyRemotingServer(serverConfig); + this.server.registerProcessor(CommandType.ALERT_SEND_REQUEST, new AlertRequestProcessor(alertDao, alertPluginManager, pluginDao)); + this.server.start(); + } + + /** + * Cyclic alert info sending alert + */ + private void runSender() { while (Stopper.isRunning()) { try { Thread.sleep(Constants.ALERT_SCAN_INTERVAL); @@ -77,16 +129,43 @@ public class AlertServer { logger.error(e.getMessage(), e); Thread.currentThread().interrupt(); } - List alerts = alertDao.listWaitExecutionAlert(); - alertSender = new AlertSender(alerts, alertDao, alertPluginManager); - alertSender.run(); + if (alertPluginManager == null || alertPluginManager.getAlertChannelMap().size() == 0) { + logger.warn("No Alert Plugin . Can not send alert info. "); + } else { + List alerts = alertDao.listWaitExecutionAlert(); + alertSender = new AlertSender(alerts, alertDao, alertPluginManager, pluginDao); + alertSender.run(); + } } } + /** + * start + */ + public void start() { + initPlugin(); + initRemoteServer(); + logger.info("alert server ready start "); + runSender(); + } + + /** + * stop + */ + public void stop() { + this.server.close(); + logger.info("alert server shut down"); + } public static void main(String[] args) { AlertServer alertServer = AlertServer.getInstance(); alertServer.start(); + Runtime.getRuntime().addShutdownHook(new Thread() { + @Override + public void run() { + alertServer.stop(); + } + }); } } diff --git a/dolphinscheduler-alert/src/main/java/org/apache/dolphinscheduler/alert/manager/EmailManager.java b/dolphinscheduler-alert/src/main/java/org/apache/dolphinscheduler/alert/manager/EmailManager.java index 22f4b7a27f..874b866759 100644 --- a/dolphinscheduler-alert/src/main/java/org/apache/dolphinscheduler/alert/manager/EmailManager.java +++ b/dolphinscheduler-alert/src/main/java/org/apache/dolphinscheduler/alert/manager/EmailManager.java @@ -1,55 +1,55 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.dolphinscheduler.alert.manager; - -import org.apache.dolphinscheduler.alert.utils.MailUtils; - -import java.util.List; -import java.util.Map; - -/** - * email send manager - */ -public class EmailManager { - /** - * email send - * @param receiversList the receiver list - * @param receiversCcList the cc List - * @param title the title - * @param content the content - * @param showType the showType - * @return the send result - */ - public Map send(List receiversList,List receiversCcList,String title,String content,String showType){ - - return MailUtils.sendMails(receiversList, receiversCcList, title, content, showType); - } - - /** - * msg send - * @param receiversList the receiver list - * @param title the title - * @param content the content - * @param showType the showType - * @return the send result - */ - public Map send(List receiversList,String title,String content,String showType){ - - return MailUtils.sendMails(receiversList,title, content, showType); - } - -} +///* +// * Licensed to the Apache Software Foundation (ASF) under one or more +// * contributor license agreements. See the NOTICE file distributed with +// * this work for additional information regarding copyright ownership. +// * The ASF licenses this file to You under the Apache License, Version 2.0 +// * (the "License"); you may not use this file except in compliance with +// * the License. You may obtain a copy of the License at +// * +// * http://www.apache.org/licenses/LICENSE-2.0 +// * +// * Unless required by applicable law or agreed to in writing, software +// * distributed under the License is distributed on an "AS IS" BASIS, +// * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// * See the License for the specific language governing permissions and +// * limitations under the License. +// */ +//package org.apache.dolphinscheduler.alert.manager; +// +//import org.apache.dolphinscheduler.alert.utils.MailUtils; +// +//import java.util.List; +//import java.util.Map; +// +///** +// * email send manager +// */ +//public class EmailManager { +// /** +// * email send +// * @param receiversList the receiver list +// * @param receiversCcList the cc List +// * @param title the title +// * @param content the content +// * @param showType the showType +// * @return the send result +// */ +// public Map send(List receiversList,List receiversCcList,String title,String content,String showType){ +// +// return MailUtils.sendMails(receiversList, receiversCcList, title, content, showType); +// } +// +// /** +// * msg send +// * @param receiversList the receiver list +// * @param title the title +// * @param content the content +// * @param showType the showType +// * @return the send result +// */ +// public Map send(List receiversList,String title,String content,String showType){ +// +// return MailUtils.sendMails(receiversList,title, content, showType); +// } +// +//} diff --git a/dolphinscheduler-alert/src/main/java/org/apache/dolphinscheduler/alert/manager/EnterpriseWeChatManager.java b/dolphinscheduler-alert/src/main/java/org/apache/dolphinscheduler/alert/manager/EnterpriseWeChatManager.java deleted file mode 100644 index 43649d6758..0000000000 --- a/dolphinscheduler-alert/src/main/java/org/apache/dolphinscheduler/alert/manager/EnterpriseWeChatManager.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.dolphinscheduler.alert.manager; - -import org.apache.dolphinscheduler.alert.utils.Constants; -import org.apache.dolphinscheduler.alert.utils.EnterpriseWeChatUtils; -import org.apache.dolphinscheduler.plugin.model.AlertInfo; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.IOException; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * Enterprise WeChat Manager - */ -public class EnterpriseWeChatManager { - private static final Logger logger = LoggerFactory.getLogger(EnterpriseWeChatManager.class); - /** - * Enterprise We Chat send - * @param alertInfo the alert info - * @param token the token - * @return the send result - */ - public Map send(AlertInfo alertInfo, String token){ - Map retMap = new HashMap<>(); - retMap.put(Constants.STATUS, false); - String agentId = EnterpriseWeChatUtils.ENTERPRISE_WE_CHAT_AGENT_ID; - String users = EnterpriseWeChatUtils.ENTERPRISE_WE_CHAT_USERS; - List userList = Arrays.asList(users.split(",")); - logger.info("send message {}", alertInfo.getAlertData().getTitle()); - String msg = EnterpriseWeChatUtils.makeUserSendMsg(userList, agentId,EnterpriseWeChatUtils.markdownByAlert(alertInfo.getAlertData())); - try { - EnterpriseWeChatUtils.sendEnterpriseWeChat(Constants.UTF_8, msg, token); - } catch (IOException e) { - logger.error(e.getMessage(),e); - } - retMap.put(Constants.STATUS, true); - return retMap; - } - -} diff --git a/dolphinscheduler-alert/src/main/java/org/apache/dolphinscheduler/alert/manager/MsgManager.java b/dolphinscheduler-alert/src/main/java/org/apache/dolphinscheduler/alert/manager/MsgManager.java index 359492699d..e7fb161162 100644 --- a/dolphinscheduler-alert/src/main/java/org/apache/dolphinscheduler/alert/manager/MsgManager.java +++ b/dolphinscheduler-alert/src/main/java/org/apache/dolphinscheduler/alert/manager/MsgManager.java @@ -14,23 +14,27 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.dolphinscheduler.alert.manager; import org.apache.dolphinscheduler.dao.entity.Alert; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * SMS send manager */ -public class MsgManager { +public class MsgManager { private static final Logger logger = LoggerFactory.getLogger(MsgManager.class); + /** * SMS send + * * @param alert the alert */ - public void send(Alert alert){ - logger.info("send message {}",alert); + public void send(Alert alert) { + logger.info("send message {}", alert); } } diff --git a/dolphinscheduler-alert/src/main/java/org/apache/dolphinscheduler/alert/plugin/AbstractDolphinPluginManager.java b/dolphinscheduler-alert/src/main/java/org/apache/dolphinscheduler/alert/plugin/AbstractDolphinPluginManager.java new file mode 100644 index 0000000000..9fd847d0e8 --- /dev/null +++ b/dolphinscheduler-alert/src/main/java/org/apache/dolphinscheduler/alert/plugin/AbstractDolphinPluginManager.java @@ -0,0 +1,29 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.dolphinscheduler.alert.plugin; + +import org.apache.dolphinscheduler.dao.DaoFactory; +import org.apache.dolphinscheduler.dao.PluginDao; +import org.apache.dolphinscheduler.spi.DolphinSchedulerPlugin; + +public abstract class AbstractDolphinPluginManager { + + protected PluginDao pluginDao = DaoFactory.getDaoInstance(PluginDao.class); + + public abstract void installPlugin(DolphinSchedulerPlugin dolphinSchedulerPlugin); +} diff --git a/dolphinscheduler-alert/src/main/java/org/apache/dolphinscheduler/alert/plugin/AlertPluginManager.java b/dolphinscheduler-alert/src/main/java/org/apache/dolphinscheduler/alert/plugin/AlertPluginManager.java new file mode 100644 index 0000000000..a660087c89 --- /dev/null +++ b/dolphinscheduler-alert/src/main/java/org/apache/dolphinscheduler/alert/plugin/AlertPluginManager.java @@ -0,0 +1,99 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.dolphinscheduler.alert.plugin; + +import static java.lang.String.format; +import static java.util.Objects.requireNonNull; + +import static com.google.common.base.Preconditions.checkState; + +import org.apache.dolphinscheduler.common.enums.PluginType; +import org.apache.dolphinscheduler.dao.entity.PluginDefine; +import org.apache.dolphinscheduler.spi.DolphinSchedulerPlugin; +import org.apache.dolphinscheduler.spi.alert.AlertChannel; +import org.apache.dolphinscheduler.spi.alert.AlertChannelFactory; +import org.apache.dolphinscheduler.spi.classloader.ThreadContextClassLoader; +import org.apache.dolphinscheduler.spi.params.PluginParamsTransfer; +import org.apache.dolphinscheduler.spi.params.base.PluginParams; + +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * load the configured alert plugin and manager them + */ +public class AlertPluginManager extends AbstractDolphinPluginManager { + private static final Logger logger = LoggerFactory.getLogger(AlertPluginManager.class); + + private final Map alertChannelFactoryMap = new ConcurrentHashMap<>(); + private final Map alertChannelMap = new ConcurrentHashMap<>(); + + public void addAlertChannelFactory(AlertChannelFactory alertChannelFactory) { + requireNonNull(alertChannelFactory, "alertChannelFactory is null"); + + if (alertChannelFactoryMap.putIfAbsent(alertChannelFactory.getName(), alertChannelFactory) != null) { + throw new IllegalArgumentException(format("Alert Plugin '{}' is already registered", alertChannelFactory.getName())); + } + + try { + loadAlertChannel(alertChannelFactory.getName()); + } catch (Exception e) { + throw new IllegalArgumentException(format("Alert Plugin '{}' is can not load .", alertChannelFactory.getName())); + } + } + + protected void loadAlertChannel(String name) { + requireNonNull(name, "name is null"); + + AlertChannelFactory alertChannelFactory = alertChannelFactoryMap.get(name); + checkState(alertChannelFactory != null, "Alert Plugin {} is not registered", name); + + try (ThreadContextClassLoader ignored = new ThreadContextClassLoader(alertChannelFactory.getClass().getClassLoader())) { + AlertChannel alertChannel = alertChannelFactory.create(); + this.alertChannelMap.put(name, alertChannel); + } + + logger.info("-- Loaded Alert Plugin {} --", name); + } + + public Map getAlertChannelFactoryMap() { + return alertChannelFactoryMap; + } + + public Map getAlertChannelMap() { + return alertChannelMap; + } + + @Override + public void installPlugin(DolphinSchedulerPlugin dolphinSchedulerPlugin) { + for (AlertChannelFactory alertChannelFactory : dolphinSchedulerPlugin.getAlertChannelFactorys()) { + logger.info("Registering Alert Plugin '{}'", alertChannelFactory.getName()); + this.addAlertChannelFactory(alertChannelFactory); + List params = alertChannelFactory.getParams(); + String nameEn = alertChannelFactory.getName(); + String paramsJson = PluginParamsTransfer.transferParamsToJson(params); + + PluginDefine pluginDefine = new PluginDefine(nameEn, PluginType.ALERT.getDesc(), paramsJson); + pluginDao.addOrUpdatePluginDefine(pluginDefine); + } + } +} diff --git a/dolphinscheduler-alert/src/main/java/org/apache/dolphinscheduler/alert/plugin/DolphinPluginClassLoader.java b/dolphinscheduler-alert/src/main/java/org/apache/dolphinscheduler/alert/plugin/DolphinPluginClassLoader.java new file mode 100644 index 0000000000..81dc4f3489 --- /dev/null +++ b/dolphinscheduler-alert/src/main/java/org/apache/dolphinscheduler/alert/plugin/DolphinPluginClassLoader.java @@ -0,0 +1,139 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.dolphinscheduler.alert.plugin; + +import static java.util.Objects.requireNonNull; + +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.Enumeration; +import java.util.List; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Iterables; + +class DolphinPluginClassLoader + extends URLClassLoader { + private static final ClassLoader PLATFORM_CLASS_LOADER = findPlatformClassLoader(); + + private final ClassLoader spiClassLoader; + private final List spiPackages; + private final List spiResources; + + public DolphinPluginClassLoader( + List urls, + ClassLoader spiClassLoader, + Iterable spiPackages) { + this(urls, + spiClassLoader, + spiPackages, + Iterables.transform(spiPackages, DolphinPluginClassLoader::classNameToResource)); + } + + private DolphinPluginClassLoader( + List urls, + ClassLoader spiClassLoader, + Iterable spiPackages, + Iterable spiResources) { + // plugins should not have access to the system (application) class loader + super(urls.toArray(new URL[urls.size()]), PLATFORM_CLASS_LOADER); + this.spiClassLoader = requireNonNull(spiClassLoader, "spiClassLoader is null"); + this.spiPackages = ImmutableList.copyOf(spiPackages); + this.spiResources = ImmutableList.copyOf(spiResources); + } + + @Override + protected Class loadClass(String name, boolean resolve) + throws ClassNotFoundException { + // grab the magic lock + synchronized (getClassLoadingLock(name)) { + // Check if class is in the loaded classes cache + Class cachedClass = findLoadedClass(name); + if (cachedClass != null) { + return resolveClass(cachedClass, resolve); + } + + // If this is an SPI class, only check SPI class loader + if (isSpiClass(name)) { + return resolveClass(spiClassLoader.loadClass(name), resolve); + } + + // Look for class locally + return super.loadClass(name, resolve); + } + } + + private Class resolveClass(Class clazz, boolean resolve) { + if (resolve) { + resolveClass(clazz); + } + return clazz; + } + + @Override + public URL getResource(String name) { + // If this is an SPI resource, only check SPI class loader + if (isSpiResource(name)) { + return spiClassLoader.getResource(name); + } + + // Look for resource locally + return super.getResource(name); + } + + @Override + public Enumeration getResources(String name) + throws IOException { + // If this is an SPI resource, use SPI resources + if (isSpiClass(name)) { + return spiClassLoader.getResources(name); + } + + // Use local resources + return super.getResources(name); + } + + private boolean isSpiClass(String name) { + return spiPackages.stream().anyMatch(name::startsWith); + } + + private boolean isSpiResource(String name) { + return spiResources.stream().anyMatch(name::startsWith); + } + + private static String classNameToResource(String className) { + return className.replace('.', '/'); + } + + @SuppressWarnings("JavaReflectionMemberAccess") + private static ClassLoader findPlatformClassLoader() { + try { + // use platform class loader on Java 9 + Method method = ClassLoader.class.getMethod("getPlatformClassLoader"); + return (ClassLoader) method.invoke(null); + } catch (NoSuchMethodException ignored) { + // use null class loader on Java 8 + return null; + } catch (IllegalAccessException | InvocationTargetException e) { + throw new AssertionError(e); + } + } +} diff --git a/dolphinscheduler-alert/src/main/java/org/apache/dolphinscheduler/alert/plugin/DolphinPluginDiscovery.java b/dolphinscheduler-alert/src/main/java/org/apache/dolphinscheduler/alert/plugin/DolphinPluginDiscovery.java new file mode 100644 index 0000000000..7e5cb544ff --- /dev/null +++ b/dolphinscheduler-alert/src/main/java/org/apache/dolphinscheduler/alert/plugin/DolphinPluginDiscovery.java @@ -0,0 +1,139 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.dolphinscheduler.alert.plugin; + +import static java.nio.charset.StandardCharsets.UTF_8; +import static java.nio.file.Files.createDirectories; +import static java.nio.file.Files.walkFileTree; + +import static com.google.common.io.ByteStreams.toByteArray; + +import org.apache.dolphinscheduler.spi.DolphinSchedulerPlugin; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStreamWriter; +import java.io.UncheckedIOException; +import java.io.Writer; +import java.nio.file.FileVisitResult; +import java.nio.file.Path; +import java.nio.file.SimpleFileVisitor; +import java.nio.file.attribute.BasicFileAttributes; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +import org.objectweb.asm.ClassReader; +import org.sonatype.aether.artifact.Artifact; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; + +/** + * The role of this class is to load the plugin class during development + */ +final class DolphinPluginDiscovery { + private static final String JAVA_CLASS_FILE_SUFFIX = ".class"; + private static final String PLUGIN_SERVICES_FILE = "META-INF/services/" + DolphinSchedulerPlugin.class.getName(); + + private DolphinPluginDiscovery() { + } + + public static Set discoverPluginsFromArtifact(Artifact artifact, ClassLoader classLoader) + throws IOException { + if (!artifact.getExtension().equals("dolphinscheduler-plugin")) { + throw new RuntimeException("Unexpected extension for main artifact: " + artifact); + } + + File file = artifact.getFile(); + if (!file.getPath().endsWith("/target/classes")) { + throw new RuntimeException("Unexpected file for main artifact: " + file); + } + if (!file.isDirectory()) { + throw new RuntimeException("Main artifact file is not a directory: " + file); + } + + if (new File(file, PLUGIN_SERVICES_FILE).exists()) { + return ImmutableSet.of(); + } + + return listClasses(file.toPath()).stream() + .filter(name -> classInterfaces(name, classLoader).contains(DolphinSchedulerPlugin.class.getName())) + .collect(Collectors.toSet()); + } + + public static void writePluginServices(Iterable plugins, File root) + throws IOException { + Path path = root.toPath().resolve(PLUGIN_SERVICES_FILE); + createDirectories(path.getParent()); + try (Writer out = new OutputStreamWriter(new FileOutputStream(path.toFile()), UTF_8)) { + for (String plugin : plugins) { + out.write(plugin + "\n"); + } + } + } + + private static List listClasses(Path base) + throws IOException { + ImmutableList.Builder list = ImmutableList.builder(); + walkFileTree(base, new SimpleFileVisitor() { + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attributes) { + if (file.getFileName().toString().endsWith(JAVA_CLASS_FILE_SUFFIX)) { + String name = file.subpath(base.getNameCount(), file.getNameCount()).toString(); + list.add(javaName(name.substring(0, name.length() - JAVA_CLASS_FILE_SUFFIX.length()))); + } + return FileVisitResult.CONTINUE; + } + }); + return list.build(); + } + + private static List classInterfaces(String name, ClassLoader classLoader) { + ImmutableList.Builder list = ImmutableList.builder(); + ClassReader reader = readClass(name, classLoader); + for (String binaryName : reader.getInterfaces()) { + list.add(javaName(binaryName)); + } + if (reader.getSuperName() != null) { + list.addAll(classInterfaces(javaName(reader.getSuperName()), classLoader)); + } + return list.build(); + } + + private static ClassReader readClass(String name, ClassLoader classLoader) { + try (InputStream in = classLoader.getResourceAsStream(binaryName(name) + JAVA_CLASS_FILE_SUFFIX)) { + if (in == null) { + throw new RuntimeException("Failed to read class: " + name); + } + return new ClassReader(toByteArray(in)); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + private static String binaryName(String javaName) { + return javaName.replace('.', '/'); + } + + private static String javaName(String binaryName) { + return binaryName.replace('/', '.'); + } +} diff --git a/dolphinscheduler-alert/src/main/java/org/apache/dolphinscheduler/alert/plugin/DolphinPluginLoader.java b/dolphinscheduler-alert/src/main/java/org/apache/dolphinscheduler/alert/plugin/DolphinPluginLoader.java new file mode 100644 index 0000000000..7dffe1def8 --- /dev/null +++ b/dolphinscheduler-alert/src/main/java/org/apache/dolphinscheduler/alert/plugin/DolphinPluginLoader.java @@ -0,0 +1,194 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.dolphinscheduler.alert.plugin; + +import static java.lang.String.format; +import static java.util.Objects.requireNonNull; + +import static com.google.common.base.Preconditions.checkState; + +import org.apache.dolphinscheduler.spi.DolphinSchedulerPlugin; +import org.apache.dolphinscheduler.spi.classloader.ThreadContextClassLoader; + +import java.io.File; +import java.io.IOException; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.ServiceLoader; +import java.util.Set; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.sonatype.aether.artifact.Artifact; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Ordering; + +import io.airlift.resolver.ArtifactResolver; + +/** + * Plugin Loader + * Load Plugin from pom when development and run server in IDE + * Load Plugin from the plugin directory when running on the server + */ +public class DolphinPluginLoader { + private static final Logger logger = LoggerFactory.getLogger(DolphinPluginLoader.class); + + /** + * All third-party jar packages used in the classes which in spi package need to be add + */ + private static final ImmutableList DOLPHIN_SPI_PACKAGES = ImmutableList.builder() + .add("org.apache.dolphinscheduler.spi.") + .add("com.fasterxml.jackson.") + .build(); + + private final File installedPluginsDir; + private final List configPlugins; + private ArtifactResolver resolver = null; + private final List dolphinPluginManagerList; + + public DolphinPluginLoader(DolphinPluginManagerConfig config, List dolphinPluginManagerList) { + installedPluginsDir = config.getInstalledPluginsDir(); + if (config.getPlugins() == null) { + this.configPlugins = ImmutableList.of(); + } else { + this.configPlugins = ImmutableList.copyOf(config.getPlugins()); + } + + this.dolphinPluginManagerList = requireNonNull(dolphinPluginManagerList, "dolphinPluginManagerList is null"); + if (configPlugins != null && configPlugins.size() > 0) { + this.resolver = new ArtifactResolver(config.getMavenLocalRepository(), config.getMavenRemoteRepository()); + } + } + + public void loadPlugins() + throws Exception { + for (File file : listPluginDirs(installedPluginsDir)) { + if (file.isDirectory()) { + loadPlugin(file.getAbsolutePath()); + } + } + + for (String plugin : configPlugins) { + loadPlugin(plugin); + } + } + + private void loadPlugin(String plugin) + throws Exception { + logger.info("-- Loading Alert plugin {} --", plugin); + URLClassLoader pluginClassLoader = buildPluginClassLoader(plugin); + try (ThreadContextClassLoader ignored = new ThreadContextClassLoader(pluginClassLoader)) { + loadPlugin(pluginClassLoader); + } + logger.info("-- Finished loading Alert plugin {} --", plugin); + } + + private void loadPlugin(URLClassLoader pluginClassLoader) { + ServiceLoader serviceLoader = ServiceLoader.load(DolphinSchedulerPlugin.class, pluginClassLoader); + List plugins = ImmutableList.copyOf(serviceLoader); + checkState(!plugins.isEmpty(), "No service providers the plugin {}", DolphinSchedulerPlugin.class.getName()); + for (DolphinSchedulerPlugin plugin : plugins) { + logger.info("Installing {}", plugin.getClass().getName()); + for (AbstractDolphinPluginManager dolphinPluginManager : dolphinPluginManagerList) { + dolphinPluginManager.installPlugin(plugin); + } + } + } + + private URLClassLoader buildPluginClassLoader(String plugin) + throws Exception { + File file = new File(plugin); + + if (!file.isDirectory() && (file.getName().equals("pom.xml") || file.getName().endsWith(".pom"))) { + return buildPluginClassLoaderFromPom(file); + } + if (file.isDirectory()) { + return buildPluginClassLoaderFromDirectory(file); + } else { + throw new IllegalArgumentException(format("plugin must be a pom file or directory {} .", plugin)); + } + } + + private URLClassLoader buildPluginClassLoaderFromPom(File pomFile) + throws Exception { + List artifacts = resolver.resolvePom(pomFile); + URLClassLoader classLoader = createClassLoader(artifacts, pomFile.getPath()); + + Artifact artifact = artifacts.get(0); + Set plugins = DolphinPluginDiscovery.discoverPluginsFromArtifact(artifact, classLoader); + if (!plugins.isEmpty()) { + DolphinPluginDiscovery.writePluginServices(plugins, artifact.getFile()); + } + + return classLoader; + } + + private URLClassLoader buildPluginClassLoaderFromDirectory(File dir) + throws Exception { + logger.info("Classpath for {}:", dir.getName()); + List urls = new ArrayList<>(); + for (File file : listPluginDirs(dir)) { + logger.info(" {}", file); + urls.add(file.toURI().toURL()); + } + return createClassLoader(urls); + } + + private URLClassLoader createClassLoader(List artifacts, String name) + throws IOException { + logger.info("Classpath for {}:", name); + List urls = new ArrayList<>(); + for (Artifact artifact : sortArtifacts(artifacts)) { + if (artifact.getFile() == null) { + throw new RuntimeException("Could not resolve artifact: " + artifact); + } + File file = artifact.getFile().getCanonicalFile(); + logger.info(" {}", file); + urls.add(file.toURI().toURL()); + } + return createClassLoader(urls); + } + + private URLClassLoader createClassLoader(List urls) { + ClassLoader parent = getClass().getClassLoader(); + return new DolphinPluginClassLoader(urls, parent, DOLPHIN_SPI_PACKAGES); + } + + private static List listPluginDirs(File installedPluginsDir) { + if (installedPluginsDir != null && installedPluginsDir.isDirectory()) { + File[] files = installedPluginsDir.listFiles(); + if (files != null) { + Arrays.sort(files); + return ImmutableList.copyOf(files); + } + } + return ImmutableList.of(); + } + + private static List sortArtifacts(List artifacts) { + List list = new ArrayList<>(artifacts); + Collections.sort(list, Ordering.natural().nullsLast().onResultOf(Artifact::getFile)); + return list; + } + +} diff --git a/dolphinscheduler-alert/src/main/java/org/apache/dolphinscheduler/alert/plugin/DolphinPluginManagerConfig.java b/dolphinscheduler-alert/src/main/java/org/apache/dolphinscheduler/alert/plugin/DolphinPluginManagerConfig.java new file mode 100644 index 0000000000..195484db46 --- /dev/null +++ b/dolphinscheduler-alert/src/main/java/org/apache/dolphinscheduler/alert/plugin/DolphinPluginManagerConfig.java @@ -0,0 +1,121 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.dolphinscheduler.alert.plugin; + +import static java.lang.String.format; +import static java.util.Objects.requireNonNull; + +import java.io.File; +import java.util.List; + +import com.google.common.base.Splitter; +import com.google.common.collect.ImmutableList; + +/** + * Dolphin Scheduler Plugin Manager Config + */ +public class DolphinPluginManagerConfig { + + /** + * The dir of the Alert Plugin in. + * When AlertServer is running on the server, it will load the Alert Plugin from this directory. + */ + private File installedPluginsDir; + + /** + * The plugin should be load. + * The installedPluginsDir is empty when we development and run server in IDEA. Then we can config which plugin should be load by param name alert.plugin.binding in the alert.properties file + */ + private List plugins; + + /** + * Development, When AlertServer is running on IDE, AlertPluginLoad can load Alert Plugin from local Repository. + */ + private String mavenLocalRepository = System.getProperty("user.home") + "/.m2/repository"; + private List mavenRemoteRepository = ImmutableList.of("http://repo1.maven.org/maven2/"); + + public File getInstalledPluginsDir() { + return installedPluginsDir; + } + + /** + * @param pluginDir + */ + public DolphinPluginManagerConfig setInstalledPluginsDir(String pluginDir) { + requireNonNull(pluginDir, "pluginDir can not be null"); + File pluginDirFile = new File(pluginDir); + if (!pluginDirFile.exists()) { + throw new IllegalArgumentException(format("plugin dir not exists ! {}", pluginDirFile.getPath())); + } + this.installedPluginsDir = pluginDirFile; + return this; + } + + public List getPlugins() { + return plugins; + } + + public DolphinPluginManagerConfig setPlugins(List plugins) { + this.plugins = plugins; + return this; + } + + /** + * When development and run server in IDE, this method can set plugins in alert.properties . + * Then when you start AlertServer in IDE, the plugin can be load. + * eg: + * file: alert.properties + * alert.plugin=\ + * ../dolphinscheduler-alert-plugin/dolphinscheduler-alert-email/pom.xml, \ + * ../dolphinscheduler-alert-plugin/dolphinscheduler-alert-wechat/pom.xml + * + * @param plugins + * @return + */ + public DolphinPluginManagerConfig setPlugins(String plugins) { + if (plugins == null) { + this.plugins = null; + } else { + this.plugins = ImmutableList.copyOf(Splitter.on(',').omitEmptyStrings().trimResults().split(plugins)); + } + return this; + } + + public String getMavenLocalRepository() { + return mavenLocalRepository; + } + + public DolphinPluginManagerConfig setMavenLocalRepository(String mavenLocalRepository) { + this.mavenLocalRepository = mavenLocalRepository; + return this; + } + + public List getMavenRemoteRepository() { + return mavenRemoteRepository; + } + + public DolphinPluginManagerConfig setMavenRemoteRepository(List mavenRemoteRepository) { + this.mavenRemoteRepository = mavenRemoteRepository; + return this; + } + + public DolphinPluginManagerConfig setMavenRemoteRepository(String mavenRemoteRepository) { + this.mavenRemoteRepository = ImmutableList.copyOf(Splitter.on(',').omitEmptyStrings().trimResults().split(mavenRemoteRepository)); + return this; + } +} diff --git a/dolphinscheduler-alert/src/main/java/org/apache/dolphinscheduler/alert/plugin/EmailAlertPlugin.java b/dolphinscheduler-alert/src/main/java/org/apache/dolphinscheduler/alert/plugin/EmailAlertPlugin.java deleted file mode 100644 index fbc600f39e..0000000000 --- a/dolphinscheduler-alert/src/main/java/org/apache/dolphinscheduler/alert/plugin/EmailAlertPlugin.java +++ /dev/null @@ -1,141 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.dolphinscheduler.alert.plugin; - -import org.apache.dolphinscheduler.alert.manager.DingTalkManager; -import org.apache.dolphinscheduler.alert.manager.EmailManager; -import org.apache.dolphinscheduler.alert.manager.EnterpriseWeChatManager; -import org.apache.dolphinscheduler.alert.utils.Constants; -import org.apache.dolphinscheduler.alert.utils.DingTalkUtils; -import org.apache.dolphinscheduler.alert.utils.EnterpriseWeChatUtils; -import org.apache.dolphinscheduler.common.utils.CollectionUtils; -import org.apache.dolphinscheduler.common.utils.StringUtils; -import org.apache.dolphinscheduler.plugin.api.AlertPlugin; -import org.apache.dolphinscheduler.plugin.model.AlertData; -import org.apache.dolphinscheduler.plugin.model.AlertInfo; -import org.apache.dolphinscheduler.plugin.model.PluginName; -import 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(); - private static final DingTalkManager dingTalkManager = new DingTalkManager(); - - public EmailAlertPlugin() { - this.pluginName = new PluginName(); - this.pluginName.setEnglish(Constants.PLUGIN_DEFAULT_EMAIL_EN); - this.pluginName.setChinese(Constants.PLUGIN_DEFAULT_EMAIL_CH); - } - - @Override - public String getId() { - return Constants.PLUGIN_DEFAULT_EMAIL_ID; - } - - @Override - public PluginName getName() { - return pluginName; - } - - @Override - @SuppressWarnings("unchecked") - public Map process(AlertInfo info) { - Map retMaps = new HashMap<>(); - - AlertData alert = info.getAlertData(); - - List receiversList = (List) info.getProp(Constants.PLUGIN_DEFAULT_EMAIL_RECEIVERS); - - // receiving group list - // custom receiver - String receivers = alert.getReceivers(); - if (StringUtils.isNotEmpty(receivers)) { - String[] splits = receivers.split(","); - receiversList.addAll(Arrays.asList(splits)); - } - - List receiversCcList = new ArrayList<>(); - // Custom Copier - String receiversCc = alert.getReceiversCc(); - if (StringUtils.isNotEmpty(receiversCc)) { - String[] splits = receiversCc.split(","); - receiversCcList.addAll(Arrays.asList(splits)); - } - - if (CollectionUtils.isEmpty(receiversList) && CollectionUtils.isEmpty(receiversCcList)) { - logger.warn("alert send error : At least one receiver address required"); - retMaps.put(Constants.STATUS, "false"); - retMaps.put(Constants.MESSAGE, "execution failure,At least one receiver address required."); - return retMaps; - } - - retMaps = emailManager.send(receiversList, receiversCcList, alert.getTitle(), alert.getContent(), - alert.getShowType()); - - //send flag - boolean flag = false; - - if (retMaps == null) { - retMaps = new HashMap<>(); - retMaps.put(Constants.MESSAGE, "alert send error."); - retMaps.put(Constants.STATUS, "false"); - logger.info("alert send error : {}", retMaps.get(Constants.MESSAGE)); - return retMaps; - } - - flag = Boolean.parseBoolean(String.valueOf(retMaps.get(Constants.STATUS))); - - if (flag) { - logger.info("alert send success"); - retMaps.put(Constants.MESSAGE, "email send success."); - if (EnterpriseWeChatUtils.isEnable()) { - logger.info("Enterprise WeChat is enable!"); - try { - String token = EnterpriseWeChatUtils.getToken(); - weChatManager.send(info, token); - } catch (Exception e) { - logger.error(e.getMessage(), e); - } - } - - if (DingTalkUtils.isEnableDingTalk) { - logger.info("Ding Talk is enable."); - dingTalkManager.send(info); - } - - } else { - retMaps.put(Constants.MESSAGE, "alert send error."); - logger.info("alert send error : {}", retMaps.get(Constants.MESSAGE)); - } - - return retMaps; - } - -} diff --git a/dolphinscheduler-alert/src/main/java/org/apache/dolphinscheduler/alert/processor/AlertRequestProcessor.java b/dolphinscheduler-alert/src/main/java/org/apache/dolphinscheduler/alert/processor/AlertRequestProcessor.java new file mode 100644 index 0000000000..5e8a8f89d6 --- /dev/null +++ b/dolphinscheduler-alert/src/main/java/org/apache/dolphinscheduler/alert/processor/AlertRequestProcessor.java @@ -0,0 +1,67 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.dolphinscheduler.alert.processor; + +import org.apache.dolphinscheduler.alert.plugin.AlertPluginManager; +import org.apache.dolphinscheduler.alert.runner.AlertSender; +import org.apache.dolphinscheduler.common.utils.Preconditions; +import org.apache.dolphinscheduler.dao.AlertDao; +import org.apache.dolphinscheduler.dao.PluginDao; +import org.apache.dolphinscheduler.remote.command.Command; +import org.apache.dolphinscheduler.remote.command.CommandType; +import org.apache.dolphinscheduler.remote.command.alert.AlertSendRequestCommand; +import org.apache.dolphinscheduler.remote.command.alert.AlertSendResponseCommand; +import org.apache.dolphinscheduler.remote.processor.NettyRequestProcessor; +import org.apache.dolphinscheduler.remote.utils.JsonSerializer; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import io.netty.channel.Channel; + +/** + * alert request processor + */ +public class AlertRequestProcessor implements NettyRequestProcessor { + + private final Logger logger = LoggerFactory.getLogger(AlertRequestProcessor.class); + private AlertDao alertDao; + private PluginDao pluginDao; + private AlertPluginManager alertPluginManager; + + public AlertRequestProcessor(AlertDao alertDao, AlertPluginManager alertPluginManager, PluginDao pluginDao) { + this.alertDao = alertDao; + this.pluginDao = pluginDao; + this.alertPluginManager = alertPluginManager; + } + + @Override + public void process(Channel channel, Command command) { + Preconditions.checkArgument(CommandType.ALERT_SEND_REQUEST == command.getType(), + String.format("invalid command type : %s", command.getType())); + + AlertSendRequestCommand alertSendRequestCommand = JsonSerializer.deserialize( + command.getBody(), AlertSendRequestCommand.class); + logger.info("received command : {}", alertSendRequestCommand); + + AlertSender alertSender = new AlertSender(alertDao, alertPluginManager, pluginDao); + AlertSendResponseCommand alertSendResponseCommand = alertSender.syncHandler(alertSendRequestCommand.getGroupId(), alertSendRequestCommand.getTitle(), alertSendRequestCommand.getContent()); + channel.writeAndFlush(alertSendResponseCommand.convert2Command(command.getOpaque())); + + } +} diff --git a/dolphinscheduler-alert/src/main/java/org/apache/dolphinscheduler/alert/runner/AlertSender.java b/dolphinscheduler-alert/src/main/java/org/apache/dolphinscheduler/alert/runner/AlertSender.java index 1bae9c7724..d635574543 100644 --- a/dolphinscheduler-alert/src/main/java/org/apache/dolphinscheduler/alert/runner/AlertSender.java +++ b/dolphinscheduler-alert/src/main/java/org/apache/dolphinscheduler/alert/runner/AlertSender.java @@ -14,23 +14,28 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.dolphinscheduler.alert.runner; -import org.apache.dolphinscheduler.alert.utils.Constants; +import org.apache.dolphinscheduler.alert.plugin.AlertPluginManager; import org.apache.dolphinscheduler.common.enums.AlertStatus; -import org.apache.dolphinscheduler.common.plugin.PluginManager; +import org.apache.dolphinscheduler.common.utils.CollectionUtils; import org.apache.dolphinscheduler.dao.AlertDao; +import org.apache.dolphinscheduler.dao.PluginDao; import org.apache.dolphinscheduler.dao.entity.Alert; -import org.apache.dolphinscheduler.dao.entity.User; -import org.apache.dolphinscheduler.plugin.api.AlertPlugin; -import org.apache.dolphinscheduler.plugin.model.AlertData; -import org.apache.dolphinscheduler.plugin.model.AlertInfo; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import org.apache.dolphinscheduler.dao.entity.AlertPluginInstance; +import org.apache.dolphinscheduler.remote.command.alert.AlertSendResponseCommand; +import org.apache.dolphinscheduler.remote.command.alert.AlertSendResponseResult; +import org.apache.dolphinscheduler.spi.alert.AlertChannel; +import org.apache.dolphinscheduler.spi.alert.AlertData; +import org.apache.dolphinscheduler.spi.alert.AlertInfo; +import org.apache.dolphinscheduler.spi.alert.AlertResult; import java.util.ArrayList; import java.util.List; -import java.util.Map; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * alert sender @@ -41,60 +46,135 @@ public class AlertSender { private List alertList; private AlertDao alertDao; - private PluginManager pluginManager; + private PluginDao pluginDao; + private AlertPluginManager alertPluginManager; - public AlertSender() { + public AlertSender(AlertPluginManager alertPluginManager) { + this.alertPluginManager = alertPluginManager; } - public AlertSender(List alertList, AlertDao alertDao, PluginManager pluginManager) { + public AlertSender(AlertDao alertDao, AlertPluginManager alertPluginManager, PluginDao pluginDao) { + super(); + this.alertDao = alertDao; + this.pluginDao = pluginDao; + this.alertPluginManager = alertPluginManager; + } + + public AlertSender(List alertList, AlertDao alertDao, AlertPluginManager alertPluginManager, PluginDao pluginDao) { super(); this.alertList = alertList; this.alertDao = alertDao; - this.pluginManager = pluginManager; + this.pluginDao = pluginDao; + this.alertPluginManager = alertPluginManager; } public void run() { - List users; - Map retMaps = null; for (Alert alert : alertList) { - users = alertDao.listUserByAlertgroupId(alert.getAlertGroupId()); - - // receiving group list - List receiversList = new ArrayList<>(); - for (User user : users) { - receiversList.add(user.getEmail()); + //get alert group from alert + int alertGroupId = alert.getAlertGroupId(); + List alertInstanceList = alertDao.listInstanceByAlertGroupId(alertGroupId); + if (CollectionUtils.isEmpty(alertInstanceList)) { + logger.error("send alert msg fail,no bind plugin instance."); + return; } - AlertData alertData = new AlertData(); alertData.setId(alert.getId()) - .setAlertGroupId(alert.getAlertGroupId()) - .setContent(alert.getContent()) - .setLog(alert.getLog()) - .setReceivers(alert.getReceivers()) - .setReceiversCc(alert.getReceiversCc()) - .setShowType(alert.getShowType().getDescp()) - .setTitle(alert.getTitle()); - - AlertInfo alertInfo = new AlertInfo(); - alertInfo.setAlertData(alertData); - - alertInfo.addProp("receivers", receiversList); - - AlertPlugin emailPlugin = pluginManager.findOne(Constants.PLUGIN_DEFAULT_EMAIL_ID); - retMaps = emailPlugin.process(alertInfo); - - if (retMaps == null) { - alertDao.updateAlert(AlertStatus.EXECUTION_FAILURE, "alert send error", alert.getId()); - logger.error("alert send error : return value is null"); - } else if (!Boolean.parseBoolean(String.valueOf(retMaps.get(Constants.STATUS)))) { - alertDao.updateAlert(AlertStatus.EXECUTION_FAILURE, String.valueOf(retMaps.get(Constants.MESSAGE)), alert.getId()); - logger.error("alert send error : {}", retMaps.get(Constants.MESSAGE)); - } else { - alertDao.updateAlert(AlertStatus.EXECUTION_SUCCESS, (String) retMaps.get(Constants.MESSAGE), alert.getId()); - logger.info("alert send success"); + .setContent(alert.getContent()) + .setLog(alert.getLog()) + .setTitle(alert.getTitle()); + + for (AlertPluginInstance instance : alertInstanceList) { + + AlertResult alertResult = this.alertResultHandler(instance, alertData); + AlertStatus alertStatus = Boolean.parseBoolean(String.valueOf(alertResult.getStatus())) ? AlertStatus.EXECUTION_SUCCESS : AlertStatus.EXECUTION_FAILURE; + alertDao.updateAlert(alertStatus, alertResult.getMessage(), alert.getId()); + } } } + /** + * sync send alert handler + * + * @param alertGroupId alertGroupId + * @param title title + * @param content content + * @return AlertSendResponseCommand + */ + public AlertSendResponseCommand syncHandler(int alertGroupId, String title, String content) { + + List alertInstanceList = alertDao.listInstanceByAlertGroupId(alertGroupId); + AlertData alertData = new AlertData(); + alertData.setContent(title) + .setTitle(content); + + boolean sendResponseStatus = true; + List sendResponseResults = new ArrayList<>(); + + if (CollectionUtils.isEmpty(alertInstanceList)) { + sendResponseStatus = false; + AlertSendResponseResult alertSendResponseResult = new AlertSendResponseResult(); + String message = String.format("Alert GroupId %s send error : not found alert instance", alertGroupId); + alertSendResponseResult.setStatus(sendResponseStatus); + alertSendResponseResult.setMessage(message); + sendResponseResults.add(alertSendResponseResult); + logger.error("Alert GroupId {} send error : not found alert instance", alertGroupId); + return new AlertSendResponseCommand(sendResponseStatus, sendResponseResults); + } + + for (AlertPluginInstance instance : alertInstanceList) { + AlertResult alertResult = this.alertResultHandler(instance, alertData); + AlertSendResponseResult alertSendResponseResult = new AlertSendResponseResult( + Boolean.parseBoolean(String.valueOf(alertResult.getStatus())), alertResult.getMessage()); + sendResponseStatus = sendResponseStatus && alertSendResponseResult.getStatus(); + sendResponseResults.add(alertSendResponseResult); + } + + return new AlertSendResponseCommand(sendResponseStatus, sendResponseResults); + } + + /** + * alert result handler + * + * @param instance instance + * @param alertData alertData + * @return AlertResult + */ + private AlertResult alertResultHandler(AlertPluginInstance instance, AlertData alertData) { + String pluginName = pluginDao.getPluginDefineById(instance.getPluginDefineId()).getPluginName(); + AlertChannel alertChannel = alertPluginManager.getAlertChannelMap().get(pluginName); + AlertResult alertResultExtend = new AlertResult(); + String pluginInstanceName = instance.getInstanceName(); + if (alertChannel == null) { + String message = String.format("Alert Plugin %s send error : return value is null", pluginInstanceName); + alertResultExtend.setStatus(String.valueOf(false)); + alertResultExtend.setMessage(message); + logger.error("Alert Plugin {} send error : not found plugin {}", pluginInstanceName, pluginName); + return alertResultExtend; + } + + AlertInfo alertInfo = new AlertInfo(); + alertInfo.setAlertData(alertData); + alertInfo.setAlertParams(instance.getPluginInstanceParams()); + AlertResult alertResult = alertChannel.process(alertInfo); + + if (alertResult == null) { + String message = String.format("Alert Plugin %s send error : return alertResult value is null", pluginInstanceName); + alertResultExtend.setStatus(String.valueOf(false)); + alertResultExtend.setMessage(message); + logger.info("Alert Plugin {} send error : return alertResult value is null", pluginInstanceName); + } else if (!Boolean.parseBoolean(String.valueOf(alertResult.getStatus()))) { + alertResultExtend.setStatus(String.valueOf(false)); + alertResultExtend.setMessage(alertResult.getMessage()); + logger.info("Alert Plugin {} send error : {}", pluginInstanceName, alertResult.getMessage()); + } else { + String message = String.format("Alert Plugin %s send success", pluginInstanceName); + alertResultExtend.setStatus(String.valueOf(true)); + alertResultExtend.setMessage(message); + logger.info("Alert Plugin {} send success", pluginInstanceName); + } + return alertResultExtend; + } + } diff --git a/dolphinscheduler-alert/src/main/java/org/apache/dolphinscheduler/alert/utils/Constants.java b/dolphinscheduler-alert/src/main/java/org/apache/dolphinscheduler/alert/utils/Constants.java index 465d9bf895..8041fa565f 100644 --- a/dolphinscheduler-alert/src/main/java/org/apache/dolphinscheduler/alert/utils/Constants.java +++ b/dolphinscheduler-alert/src/main/java/org/apache/dolphinscheduler/alert/utils/Constants.java @@ -14,6 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.dolphinscheduler.alert.utils; /** @@ -23,176 +24,15 @@ public class Constants { private Constants() { throw new IllegalStateException("Constants class"); } + /** * alert properties path */ public static final String ALERT_PROPERTIES_PATH = "/alert.properties"; - public static final String DATA_SOURCE_PROPERTIES_PATH = "/dao/data_source.properties"; - - public static final String SINGLE_SLASH = "/"; - - /** - * UTF-8 - */ - public static final String UTF_8 = "UTF-8"; - - public static final String STATUS = "status"; - - public static final String MESSAGE = "message"; - - public static final String MAIL_PROTOCOL = "mail.protocol"; - - public static final String MAIL_SERVER_HOST = "mail.server.host"; - - public static final String MAIL_SERVER_PORT = "mail.server.port"; - - public static final String MAIL_SENDER = "mail.sender"; - - public static final String MAIL_USER = "mail.user"; - - public static final String MAIL_PASSWD = "mail.passwd"; - - public static final String XLS_FILE_PATH = "xls.file.path"; - - public static final String MAIL_HOST = "mail.smtp.host"; - - public static final String MAIL_PORT = "mail.smtp.port"; - - public static final String MAIL_SMTP_AUTH = "mail.smtp.auth"; - - public static final String MAIL_TRANSPORT_PROTOCOL = "mail.transport.protocol"; - - public static final String MAIL_SMTP_STARTTLS_ENABLE = "mail.smtp.starttls.enable"; - - public static final String MAIL_SMTP_SSL_ENABLE = "mail.smtp.ssl.enable"; - - public static final String MAIL_SMTP_SSL_TRUST="mail.smtp.ssl.trust"; - - public static final String TEXT_HTML_CHARSET_UTF_8 = "text/html;charset=utf-8"; - - public static final String STRING_TRUE = "true"; - - public static final String EXCEL_SUFFIX_XLS = ".xls"; - - public static final int NUMBER_1000 = 1000; - - public static final String SPRING_DATASOURCE_DRIVER_CLASS_NAME = "spring.datasource.driver-class-name"; - - public static final String SPRING_DATASOURCE_URL = "spring.datasource.url"; - - public static final String SPRING_DATASOURCE_USERNAME = "spring.datasource.username"; - - public static final String SPRING_DATASOURCE_PASSWORD = "spring.datasource.password"; - - public static final String SPRING_DATASOURCE_VALIDATION_QUERY_TIMEOUT = "spring.datasource.validationQueryTimeout"; - - public static final String SPRING_DATASOURCE_INITIAL_SIZE = "spring.datasource.initialSize"; - - public static final String SPRING_DATASOURCE_MIN_IDLE = "spring.datasource.minIdle"; - - public static final String SPRING_DATASOURCE_MAX_ACTIVE = "spring.datasource.maxActive"; - - public static final String SPRING_DATASOURCE_MAX_WAIT = "spring.datasource.maxWait"; - - public static final String SPRING_DATASOURCE_TIME_BETWEEN_EVICTION_RUNS_MILLIS = "spring.datasource.timeBetweenEvictionRunsMillis"; - - public static final String SPRING_DATASOURCE_MIN_EVICTABLE_IDLE_TIME_MILLIS = "spring.datasource.minEvictableIdleTimeMillis"; - - public static final String SPRING_DATASOURCE_VALIDATION_QUERY = "spring.datasource.validationQuery"; - - public static final String SPRING_DATASOURCE_TEST_WHILE_IDLE = "spring.datasource.testWhileIdle"; - - public static final String SPRING_DATASOURCE_TEST_ON_BORROW = "spring.datasource.testOnBorrow"; - - public static final String SPRING_DATASOURCE_TEST_ON_RETURN = "spring.datasource.testOnReturn"; - - public static final String SPRING_DATASOURCE_POOL_PREPARED_STATEMENTS = "spring.datasource.poolPreparedStatements"; - - public static final String SPRING_DATASOURCE_DEFAULT_AUTO_COMMIT = "spring.datasource.defaultAutoCommit"; - - public static final String SPRING_DATASOURCE_KEEP_ALIVE = "spring.datasource.keepAlive"; - - public static final String SPRING_DATASOURCE_MAX_POOL_PREPARED_STATEMENT_PER_CONNECTION_SIZE = "spring.datasource.maxPoolPreparedStatementPerConnectionSize"; - - public static final String DEVELOPMENT = "development"; - - public static final String TR = ""; - - public static final String TD = ""; - - public static final String TD_END = ""; - - public static final String TR_END = ""; - - public static final String TITLE = "title"; - - public static final String CONTENT = "content"; - - public static final String TH = ""; - - public static final String TH_END = ""; + /** default alert plugin dir **/ + public static final String ALERT_PLUGIN_PATH = "./lib/plugin/alert"; public static final int ALERT_SCAN_INTERVAL = 5000; - public static final String MARKDOWN_QUOTE = ">"; - - public static final String MARKDOWN_ENTER = "\n"; - - public static final String ENTERPRISE_WECHAT_ENABLE = "enterprise.wechat.enable"; - - public static final String ENTERPRISE_WECHAT_CORP_ID = "enterprise.wechat.corp.id"; - - public static final String ENTERPRISE_WECHAT_SECRET = "enterprise.wechat.secret"; - - public static final String ENTERPRISE_WECHAT_TOKEN_URL = "enterprise.wechat.token.url"; - - public static final String ENTERPRISE_WECHAT_PUSH_URL = "enterprise.wechat.push.url"; - - public static final String ENTERPRISE_WECHAT_TEAM_SEND_MSG = "enterprise.wechat.team.send.msg"; - - public static final String ENTERPRISE_WECHAT_USER_SEND_MSG = "enterprise.wechat.user.send.msg"; - - public static final String ENTERPRISE_WECHAT_AGENT_ID = "enterprise.wechat.agent.id"; - - public static final String ENTERPRISE_WECHAT_USERS = "enterprise.wechat.users"; - - - public static final String DINGTALK_WEBHOOK = "dingtalk.webhook"; - - public static final String DINGTALK_KEYWORD = "dingtalk.keyword"; - - public static final String DINGTALK_PROXY_ENABLE = "dingtalk.isEnableProxy"; - - public static final String DINGTALK_PROXY = "dingtalk.proxy"; - - public static final String DINGTALK_PORT = "dingtalk.port"; - - public static final String DINGTALK_USER = "dingtalk.user"; - - public static final String DINGTALK_PASSWORD = "dingtalk.password"; - - public static final String DINGTALK_ENABLE = "dingtalk.isEnable"; - - public static final String HTML_HEADER_PREFIX = "dolphinscheduler "; - - public static final String TABLE_BODY_HTML_TAIL = "
"; - - /** - * plugin config - */ - public static final String PLUGIN_DIR = "plugin.dir"; - - public static final String PLUGIN_DEFAULT_EMAIL_ID = "email"; - - public static final String PLUGIN_DEFAULT_EMAIL_CH = "邮件"; - - public static final String PLUGIN_DEFAULT_EMAIL_EN = "email"; - - public static final String PLUGIN_DEFAULT_EMAIL_RECEIVERS = "receivers"; - - public static final String PLUGIN_DEFAULT_EMAIL_RECEIVERCCS = "receiverCcs"; - - public static final String RETMAP_MSG = "msg"; - } diff --git a/dolphinscheduler-alert/src/main/java/org/apache/dolphinscheduler/alert/utils/DingTalkUtils.java b/dolphinscheduler-alert/src/main/java/org/apache/dolphinscheduler/alert/utils/DingTalkUtils.java deleted file mode 100644 index 455d5de834..0000000000 --- a/dolphinscheduler-alert/src/main/java/org/apache/dolphinscheduler/alert/utils/DingTalkUtils.java +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.dolphinscheduler.alert.utils; - - -import org.apache.dolphinscheduler.common.utils.*; -import org.apache.commons.codec.binary.StringUtils; -import org.apache.http.HttpEntity; -import org.apache.http.HttpHost; -import org.apache.http.auth.AuthScope; -import org.apache.http.auth.UsernamePasswordCredentials; -import org.apache.http.client.CredentialsProvider; -import org.apache.http.client.config.RequestConfig; -import org.apache.http.client.methods.CloseableHttpResponse; -import org.apache.http.client.methods.HttpPost; -import org.apache.http.entity.StringEntity; -import org.apache.http.impl.client.BasicCredentialsProvider; -import org.apache.http.impl.client.CloseableHttpClient; -import org.apache.http.impl.client.HttpClients; -import org.apache.http.util.EntityUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.IOException; -import java.util.HashMap; -import java.util.Map; - -/** - * DingTalkUtils utils - * support send msg to ding talk by robot message push function. - * support proxy setting - */ -public class DingTalkUtils { - public static final Logger logger = LoggerFactory.getLogger(DingTalkUtils.class); - - public static final boolean isEnableDingTalk = PropertyUtils.getBoolean(Constants.DINGTALK_ENABLE); - private static final String dingTaskUrl = PropertyUtils.getString(Constants.DINGTALK_WEBHOOK); - private static final String keyword = PropertyUtils.getString(Constants.DINGTALK_KEYWORD); - private static final Boolean isEnableProxy = PropertyUtils.getBoolean(Constants.DINGTALK_PROXY_ENABLE); - private static final String proxy = PropertyUtils.getString(Constants.DINGTALK_PROXY); - private static final String user = PropertyUtils.getString(Constants.DINGTALK_USER); - private static final String passwd = PropertyUtils.getString(Constants.DINGTALK_PASSWORD); - private static final Integer port = PropertyUtils.getInt(Constants.DINGTALK_PORT); - - /** - * send message interface - * only support text message format now. - * @param msg message context to send - * @param charset charset type - * @return result of sending msg - * @throws IOException the IOException - */ - public static String sendDingTalkMsg(String msg, String charset) throws IOException { - String msgToJson = textToJsonString(msg + "#" + keyword); - HttpPost httpPost = constructHttpPost(msgToJson, charset); - - CloseableHttpClient httpClient; - if (isEnableProxy) { - httpClient = getProxyClient(); - RequestConfig rcf = getProxyConfig(); - httpPost.setConfig(rcf); - } else { - httpClient = getDefaultClient(); - } - - try { - CloseableHttpResponse response = httpClient.execute(httpPost); - String resp; - try { - HttpEntity entity = response.getEntity(); - resp = EntityUtils.toString(entity, charset); - EntityUtils.consume(entity); - } finally { - response.close(); - } - logger.info("Ding Talk send [{}], resp:{%s}", msg, resp); - return resp; - } finally { - httpClient.close(); - } - } - - public static HttpPost constructHttpPost(String msg, String charset) { - HttpPost post = new HttpPost(dingTaskUrl); - StringEntity entity = new StringEntity(msg, charset); - post.setEntity(entity); - post.addHeader("Content-Type", "application/json; charset=utf-8"); - return post; - } - - - public static CloseableHttpClient getProxyClient() { - HttpHost httpProxy = new HttpHost(proxy, port); - CredentialsProvider provider = new BasicCredentialsProvider(); - provider.setCredentials(new AuthScope(httpProxy), new UsernamePasswordCredentials(user, passwd)); - CloseableHttpClient httpClient = HttpClients.custom().setDefaultCredentialsProvider(provider).build(); - return httpClient; - } - - public static CloseableHttpClient getDefaultClient() { - return HttpClients.createDefault(); - } - - public static RequestConfig getProxyConfig() { - HttpHost httpProxy = new HttpHost(proxy, port); - return RequestConfig.custom().setProxy(httpProxy).build(); - } - - public static String textToJsonString(String text) { - Map items = new HashMap(); - items.put("msgtype", "text"); - Map textContent = new HashMap(); - byte[] byt = StringUtils.getBytesUtf8(text); - String txt = StringUtils.newStringUtf8(byt); - textContent.put("content", txt); - items.put("text", textContent); - - return JSONUtils.toJsonString(items); - - } - -} diff --git a/dolphinscheduler-alert/src/main/java/org/apache/dolphinscheduler/alert/utils/EnterpriseWeChatUtils.java b/dolphinscheduler-alert/src/main/java/org/apache/dolphinscheduler/alert/utils/EnterpriseWeChatUtils.java deleted file mode 100644 index b3cb5f7c4e..0000000000 --- a/dolphinscheduler-alert/src/main/java/org/apache/dolphinscheduler/alert/utils/EnterpriseWeChatUtils.java +++ /dev/null @@ -1,282 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.dolphinscheduler.alert.utils; - -import org.apache.dolphinscheduler.common.enums.ShowType; -import org.apache.dolphinscheduler.common.utils.JSONUtils; -import org.apache.dolphinscheduler.common.utils.StringUtils; -import org.apache.dolphinscheduler.plugin.model.AlertData; - -import org.apache.http.HttpEntity; -import org.apache.http.client.methods.CloseableHttpResponse; -import org.apache.http.client.methods.HttpGet; -import org.apache.http.client.methods.HttpPost; -import org.apache.http.entity.StringEntity; -import org.apache.http.impl.client.CloseableHttpClient; -import org.apache.http.impl.client.HttpClients; -import org.apache.http.util.EntityUtils; - -import java.io.IOException; -import java.util.Collection; -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Enterprise WeChat utils - */ -public class EnterpriseWeChatUtils { - - public static final Logger logger = LoggerFactory.getLogger(EnterpriseWeChatUtils.class); - public static final String ENTERPRISE_WE_CHAT_AGENT_ID = PropertyUtils.getString(Constants.ENTERPRISE_WECHAT_AGENT_ID); - public static final String ENTERPRISE_WE_CHAT_USERS = PropertyUtils.getString(Constants.ENTERPRISE_WECHAT_USERS); - private static final String ENTERPRISE_WE_CHAT_CORP_ID = PropertyUtils.getString(Constants.ENTERPRISE_WECHAT_CORP_ID); - private static final String ENTERPRISE_WE_CHAT_SECRET = PropertyUtils.getString(Constants.ENTERPRISE_WECHAT_SECRET); - private static final String ENTERPRISE_WE_CHAT_TOKEN_URL = PropertyUtils.getString(Constants.ENTERPRISE_WECHAT_TOKEN_URL); - private static final String ENTERPRISE_WE_CHAT_TOKEN_URL_REPLACE = ENTERPRISE_WE_CHAT_TOKEN_URL == null ? null : ENTERPRISE_WE_CHAT_TOKEN_URL - .replaceAll("\\{corpId}", ENTERPRISE_WE_CHAT_CORP_ID) - .replaceAll("\\{secret}", ENTERPRISE_WE_CHAT_SECRET); - private static final String ENTERPRISE_WE_CHAT_PUSH_URL = PropertyUtils.getString(Constants.ENTERPRISE_WECHAT_PUSH_URL); - private static final String ENTERPRISE_WE_CHAT_TEAM_SEND_MSG = PropertyUtils.getString(Constants.ENTERPRISE_WECHAT_TEAM_SEND_MSG); - private static final String ENTERPRISE_WE_CHAT_USER_SEND_MSG = PropertyUtils.getString(Constants.ENTERPRISE_WECHAT_USER_SEND_MSG); - - private static final String agentIdRegExp = "\\{agentId}"; - private static final String msgRegExp = "\\{msg}"; - private static final String userRegExp = "\\{toUser}"; - - /** - * get Enterprise WeChat is enable - * - * @return isEnable - */ - public static boolean isEnable() { - Boolean isEnable = null; - try { - isEnable = PropertyUtils.getBoolean(Constants.ENTERPRISE_WECHAT_ENABLE); - } catch (Exception e) { - logger.error(e.getMessage(), e); - } - if (isEnable == null) { - return false; - } - return isEnable; - } - - /** - * get Enterprise WeChat token info - * - * @return token string info - * @throws IOException the IOException - */ - public static String getToken() throws IOException { - String resp; - - CloseableHttpClient httpClient = HttpClients.createDefault(); - try { - HttpGet httpGet = new HttpGet(ENTERPRISE_WE_CHAT_TOKEN_URL_REPLACE); - CloseableHttpResponse response = httpClient.execute(httpGet); - try { - HttpEntity entity = response.getEntity(); - resp = EntityUtils.toString(entity, Constants.UTF_8); - EntityUtils.consume(entity); - } finally { - response.close(); - } - - Map map = JSONUtils.toMap(resp); - return map == null ? null : map.get("access_token"); - } finally { - httpClient.close(); - } - } - - /** - * make team single Enterprise WeChat message - * - * @param toParty the toParty - * @param agentId the agentId - * @param msg the msg - * @return Enterprise WeChat send message - */ - public static String makeTeamSendMsg(String toParty, String agentId, String msg) { - return ENTERPRISE_WE_CHAT_TEAM_SEND_MSG.replaceAll("\\{toParty}", toParty) - .replaceAll(agentIdRegExp, agentId) - .replaceAll(msgRegExp, msg); - } - - /** - * make team multi Enterprise WeChat message - * - * @param toParty the toParty - * @param agentId the agentId - * @param msg the msg - * @return Enterprise WeChat send message - */ - public static String makeTeamSendMsg(Collection toParty, String agentId, String msg) { - String listParty = FuncUtils.mkString(toParty, "|"); - return ENTERPRISE_WE_CHAT_TEAM_SEND_MSG.replaceAll("\\{toParty}", listParty) - .replaceAll(agentIdRegExp, agentId) - .replaceAll(msgRegExp, msg); - } - - /** - * make team single user message - * - * @param toUser the toUser - * @param agentId the agentId - * @param msg the msg - * @return Enterprise WeChat send message - */ - public static String makeUserSendMsg(String toUser, String agentId, String msg) { - return ENTERPRISE_WE_CHAT_USER_SEND_MSG.replaceAll("\\{toUser}", toUser) - .replaceAll(agentIdRegExp, agentId) - .replaceAll(msgRegExp, msg); - } - - /** - * make team multi user message - * - * @param toUser the toUser - * @param agentId the agentId - * @param msg the msg - * @return Enterprise WeChat send message - */ - public static String makeUserSendMsg(Collection toUser, String agentId, String msg) { - String listUser = FuncUtils.mkString(toUser, "|"); - return ENTERPRISE_WE_CHAT_USER_SEND_MSG.replaceAll(userRegExp, listUser) - .replaceAll(agentIdRegExp, agentId) - .replaceAll(msgRegExp, msg); - } - - /** - * send Enterprise WeChat - * - * @param charset the charset - * @param data the data - * @param token the token - * @return Enterprise WeChat resp, demo: {"errcode":0,"errmsg":"ok","invaliduser":""} - * @throws IOException the IOException - */ - public static String sendEnterpriseWeChat(String charset, String data, String token) throws IOException { - String enterpriseWeChatPushUrlReplace = ENTERPRISE_WE_CHAT_PUSH_URL.replaceAll("\\{token}", token); - - CloseableHttpClient httpClient = HttpClients.createDefault(); - try { - HttpPost httpPost = new HttpPost(enterpriseWeChatPushUrlReplace); - httpPost.setEntity(new StringEntity(data, charset)); - CloseableHttpResponse response = httpClient.execute(httpPost); - String resp; - try { - HttpEntity entity = response.getEntity(); - resp = EntityUtils.toString(entity, charset); - EntityUtils.consume(entity); - } finally { - response.close(); - } - logger.info("Enterprise WeChat send [{}], param:{}, resp:{}", - ENTERPRISE_WE_CHAT_PUSH_URL, data, resp); - return resp; - } finally { - httpClient.close(); - } - } - - /** - * convert table to markdown style - * - * @param title the title - * @param content the content - * @return markdown table content - */ - public static String markdownTable(String title, String content) { - List mapItemsList = JSONUtils.toList(content, LinkedHashMap.class); - StringBuilder contents = new StringBuilder(200); - - if (null != mapItemsList) { - for (LinkedHashMap mapItems : mapItemsList) { - Set> entries = mapItems.entrySet(); - Iterator> iterator = entries.iterator(); - StringBuilder t = new StringBuilder(String.format("`%s`%s", title, Constants.MARKDOWN_ENTER)); - - while (iterator.hasNext()) { - - Map.Entry entry = iterator.next(); - t.append(Constants.MARKDOWN_QUOTE); - t.append(entry.getKey()).append(":").append(entry.getValue()); - t.append(Constants.MARKDOWN_ENTER); - } - contents.append(t); - } - } - return contents.toString(); - } - - /** - * convert text to markdown style - * - * @param title the title - * @param content the content - * @return markdown text - */ - public static String markdownText(String title, String content) { - if (StringUtils.isNotEmpty(content)) { - List mapItemsList = JSONUtils.toList(content, LinkedHashMap.class); - if (null != mapItemsList) { - StringBuilder contents = new StringBuilder(100); - contents.append(String.format("`%s`%n", title)); - for (LinkedHashMap mapItems : mapItemsList) { - - Set> entries = mapItems.entrySet(); - Iterator> iterator = entries.iterator(); - while (iterator.hasNext()) { - Map.Entry entry = iterator.next(); - contents.append(Constants.MARKDOWN_QUOTE); - contents.append(entry.getKey()).append(":").append(entry.getValue()); - contents.append(Constants.MARKDOWN_ENTER); - } - - } - return contents.toString(); - } - - } - return null; - } - - /** - * Determine the mardown style based on the show type of the alert - * - * @return the markdown alert table/text - */ - public static String markdownByAlert(AlertData alert) { - String result = ""; - if (alert.getShowType().equals(ShowType.TABLE.getDescp())) { - result = markdownTable(alert.getTitle(), alert.getContent()); - } else if (alert.getShowType().equals(ShowType.TEXT.getDescp())) { - result = markdownText(alert.getTitle(), alert.getContent()); - } - return result; - - } - -} diff --git a/dolphinscheduler-alert/src/main/java/org/apache/dolphinscheduler/alert/utils/ExcelUtils.java b/dolphinscheduler-alert/src/main/java/org/apache/dolphinscheduler/alert/utils/ExcelUtils.java deleted file mode 100644 index 08256860e2..0000000000 --- a/dolphinscheduler-alert/src/main/java/org/apache/dolphinscheduler/alert/utils/ExcelUtils.java +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.dolphinscheduler.alert.utils; - -import org.apache.dolphinscheduler.common.utils.CollectionUtils; -import org.apache.poi.hssf.usermodel.HSSFCell; -import org.apache.poi.hssf.usermodel.HSSFRow; -import org.apache.poi.hssf.usermodel.HSSFSheet; -import org.apache.poi.hssf.usermodel.HSSFWorkbook; -import org.apache.poi.ss.usermodel.CellStyle; -import org.apache.poi.ss.usermodel.HorizontalAlignment; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.util.*; -import org.apache.dolphinscheduler.common.utils.*; - -/** - * excel utils - */ -public class ExcelUtils { - - private static final Logger logger = LoggerFactory.getLogger(ExcelUtils.class); - /** - * generate excel file - * @param content the content - * @param title the title - * @param xlsFilePath the xls path - */ - public static void genExcelFile(String content,String title,String xlsFilePath){ - List itemsList; - - //The JSONUtils.toList has been try catch ex - itemsList = JSONUtils.toList(content, LinkedHashMap.class); - - if (CollectionUtils.isEmpty(itemsList)){ - logger.error("itemsList is null"); - throw new RuntimeException("itemsList is null"); - } - - LinkedHashMap headerMap = itemsList.get(0); - - List headerList = new ArrayList<>(); - - Iterator> iter = headerMap.entrySet().iterator(); - while (iter.hasNext()){ - Map.Entry en = iter.next(); - headerList.add(en.getKey()); - } - - HSSFWorkbook wb = null; - FileOutputStream fos = null; - try { - // declare a workbook - wb = new HSSFWorkbook(); - // generate a table - HSSFSheet sheet = wb.createSheet(); - HSSFRow row = sheet.createRow(0); - //set the height of the first line - row.setHeight((short)500); - - //set Horizontal right - CellStyle cellStyle = wb.createCellStyle(); - cellStyle.setAlignment(HorizontalAlignment.RIGHT); - - //setting excel headers - for (int i = 0; i < headerList.size(); i++) { - HSSFCell cell = row.createCell(i); - cell.setCellStyle(cellStyle); - cell.setCellValue(headerList.get(i)); - } - - //setting excel body - int rowIndex = 1; - for (LinkedHashMap itemsMap : itemsList){ - Object[] values = itemsMap.values().toArray(); - row = sheet.createRow(rowIndex); - //setting excel body height - row.setHeight((short)500); - rowIndex++; - for (int j = 0 ; j < values.length ; j++){ - HSSFCell cell1 = row.createCell(j); - cell1.setCellStyle(cellStyle); - cell1.setCellValue(String.valueOf(values[j])); - } - } - - for (int i = 0; i < headerList.size(); i++) { - sheet.setColumnWidth(i, headerList.get(i).length() * 800); - } - - File file = new File(xlsFilePath); - if (!file.exists()) { - file.mkdirs(); - } - - //setting file output - fos = new FileOutputStream(xlsFilePath + Constants.SINGLE_SLASH + title + Constants.EXCEL_SUFFIX_XLS); - - wb.write(fos); - - }catch (Exception e){ - logger.error("generate excel error",e); - throw new RuntimeException("generate excel error",e); - }finally { - if (wb != null){ - try { - wb.close(); - } catch (IOException e) { - logger.error(e.getMessage(),e); - } - } - if (fos != null){ - try { - fos.close(); - } catch (IOException e) { - logger.error(e.getMessage(),e); - } - } - } - } - -} diff --git a/dolphinscheduler-alert/src/main/java/org/apache/dolphinscheduler/alert/utils/FuncUtils.java b/dolphinscheduler-alert/src/main/java/org/apache/dolphinscheduler/alert/utils/FuncUtils.java index d68532a82b..e78b4ebec8 100644 --- a/dolphinscheduler-alert/src/main/java/org/apache/dolphinscheduler/alert/utils/FuncUtils.java +++ b/dolphinscheduler-alert/src/main/java/org/apache/dolphinscheduler/alert/utils/FuncUtils.java @@ -14,15 +14,20 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.dolphinscheduler.alert.utils; import org.apache.dolphinscheduler.common.utils.StringUtils; public class FuncUtils { + private FuncUtils() { + throw new IllegalStateException(FuncUtils.class.getName()); + } + public static String mkString(Iterable list, String split) { - if (null == list || StringUtils.isEmpty(split)){ + if (null == list || StringUtils.isEmpty(split)) { return null; } diff --git a/dolphinscheduler-alert/src/main/java/org/apache/dolphinscheduler/alert/utils/MailUtils.java b/dolphinscheduler-alert/src/main/java/org/apache/dolphinscheduler/alert/utils/MailUtils.java deleted file mode 100644 index 888c9dbb26..0000000000 --- a/dolphinscheduler-alert/src/main/java/org/apache/dolphinscheduler/alert/utils/MailUtils.java +++ /dev/null @@ -1,352 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.dolphinscheduler.alert.utils; - -import org.apache.dolphinscheduler.alert.template.AlertTemplate; -import org.apache.dolphinscheduler.alert.template.AlertTemplateFactory; -import org.apache.dolphinscheduler.common.enums.ShowType; -import org.apache.commons.mail.EmailException; -import org.apache.commons.mail.HtmlEmail; -import org.apache.dolphinscheduler.common.utils.CollectionUtils; -import org.apache.dolphinscheduler.common.utils.StringUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.mail.*; -import javax.mail.internet.*; -import java.io.*; -import java.util.*; - - -/** - * mail utils - */ -public class MailUtils { - - public static final Logger logger = LoggerFactory.getLogger(MailUtils.class); - - public static final String MAIL_PROTOCOL = PropertyUtils.getString(Constants.MAIL_PROTOCOL); - - public static final String MAIL_SERVER_HOST = PropertyUtils.getString(Constants.MAIL_SERVER_HOST); - - public static final Integer MAIL_SERVER_PORT = PropertyUtils.getInt(Constants.MAIL_SERVER_PORT); - - public static final String MAIL_SENDER = PropertyUtils.getString(Constants.MAIL_SENDER); - - public static final String MAIL_USER = PropertyUtils.getString(Constants.MAIL_USER); - - public static final String MAIL_PASSWD = PropertyUtils.getString(Constants.MAIL_PASSWD); - - public static final Boolean MAIL_USE_START_TLS = PropertyUtils.getBoolean(Constants.MAIL_SMTP_STARTTLS_ENABLE); - - public static final Boolean MAIL_USE_SSL = PropertyUtils.getBoolean(Constants.MAIL_SMTP_SSL_ENABLE); - - public static final String xlsFilePath = PropertyUtils.getString(Constants.XLS_FILE_PATH,"/tmp/xls"); - - public static final String STARTTLS_ENABLE = PropertyUtils.getString(Constants.MAIL_SMTP_STARTTLS_ENABLE); - - public static final Boolean SSL_ENABLE = PropertyUtils.getBoolean(Constants.MAIL_SMTP_SSL_ENABLE); - - public static final String SSL_TRUST = PropertyUtils.getString(Constants.MAIL_SMTP_SSL_TRUST); - - public static final AlertTemplate alertTemplate = AlertTemplateFactory.getMessageTemplate(); - - //Solve the problem of messy Chinese name in excel attachment - static { - System.setProperty("mail.mime.splitlongparameters","false"); - } - - /** - * send mail to receivers - * @param receivers the receiver list - * @param title the title - * @param content the content - * @param showType the show type - * @return the result map - */ - public static Map sendMails(Collection receivers, String title, String content,String showType) { - return sendMails(receivers, null, title, content, showType); - } - - /** - * send mail - * @param receivers the receiver list - * @param receiversCc cc list - * @param title the title - * @param content the content - * @param showType the show type - * @return the send result - */ - public static Map sendMails(Collection receivers, Collection receiversCc, String title, String content, String showType) { - Map retMap = new HashMap<>(); - retMap.put(Constants.STATUS, false); - - // if there is no receivers && no receiversCc, no need to process - if (CollectionUtils.isEmpty(receivers) && CollectionUtils.isEmpty(receiversCc)) { - return retMap; - } - - receivers.removeIf(StringUtils::isEmpty); - - if (showType.equals(ShowType.TABLE.getDescp()) || showType.equals(ShowType.TEXT.getDescp())) { - // send email - HtmlEmail email = new HtmlEmail(); - - try { - Session session = getSession(); - email.setMailSession(session); - email.setFrom(MAIL_SENDER); - email.setCharset(Constants.UTF_8); - if (CollectionUtils.isNotEmpty(receivers)){ - // receivers mail - for (String receiver : receivers) { - email.addTo(receiver); - } - } - - if (CollectionUtils.isNotEmpty(receiversCc)){ - //cc - for (String receiverCc : receiversCc) { - email.addCc(receiverCc); - } - } - // sender mail - return getStringObjectMap(title, content, showType, retMap, email); - } catch (Exception e) { - handleException(receivers, retMap, e); - } - }else if (showType.equals(ShowType.ATTACHMENT.getDescp()) || showType.equals(ShowType.TABLEATTACHMENT.getDescp())) { - try { - - String partContent = (showType.equals(ShowType.ATTACHMENT.getDescp()) ? "Please see the attachment " + title + Constants.EXCEL_SUFFIX_XLS : htmlTable(content,false)); - - attachment(receivers,receiversCc,title,content,partContent); - - retMap.put(Constants.STATUS, true); - return retMap; - }catch (Exception e){ - handleException(receivers, retMap, e); - return retMap; - } - } - return retMap; - - } - - /** - * html table content - * @param content the content - * @param showAll if show the whole content - * @return the html table form - */ - private static String htmlTable(String content, boolean showAll){ - return alertTemplate.getMessageFromTemplate(content,ShowType.TABLE,showAll); - } - - /** - * html table content - * @param content the content - * @return the html table form - */ - private static String htmlTable(String content){ - return htmlTable(content,true); - } - - /** - * html text content - * @param content the content - * @return text in html form - */ - private static String htmlText(String content){ - return alertTemplate.getMessageFromTemplate(content,ShowType.TEXT); - } - - /** - * send mail as Excel attachment - * @param receivers the receiver list - * @param title the title - * @throws Exception - */ - private static void attachment(Collection receivers,Collection receiversCc,String title,String content,String partContent)throws Exception{ - MimeMessage msg = getMimeMessage(receivers); - - attachContent(receiversCc, title, content,partContent, msg); - } - - /** - * get MimeMessage - * @param receivers receivers - * @return the MimeMessage - * @throws MessagingException - */ - private static MimeMessage getMimeMessage(Collection receivers) throws MessagingException { - - // 1. The first step in creating mail: creating session - Session session = getSession(); - // Setting debug mode, can be turned off - session.setDebug(false); - - // 2. creating mail: Creating a MimeMessage - MimeMessage msg = new MimeMessage(session); - // 3. set sender - msg.setFrom(new InternetAddress(MAIL_SENDER)); - // 4. set receivers - for (String receiver : receivers) { - msg.addRecipients(Message.RecipientType.TO, InternetAddress.parse(receiver)); - } - return msg; - } - - /** - * get session - * - * @return the new Session - */ - private static Session getSession() { - Properties props = new Properties(); - props.setProperty(Constants.MAIL_HOST, MAIL_SERVER_HOST); - props.setProperty(Constants.MAIL_PORT, String.valueOf(MAIL_SERVER_PORT)); - props.setProperty(Constants.MAIL_SMTP_AUTH, Constants.STRING_TRUE); - props.setProperty(Constants.MAIL_TRANSPORT_PROTOCOL, MAIL_PROTOCOL); - props.setProperty(Constants.MAIL_SMTP_STARTTLS_ENABLE, STARTTLS_ENABLE); - if (SSL_ENABLE) { - props.setProperty(Constants.MAIL_SMTP_SSL_ENABLE, "true"); - props.setProperty(Constants.MAIL_SMTP_SSL_TRUST, SSL_TRUST); - } - - Authenticator auth = new Authenticator() { - @Override - protected PasswordAuthentication getPasswordAuthentication() { - // mail username and password - return new PasswordAuthentication(MAIL_USER, MAIL_PASSWD); - } - }; - - return Session.getInstance(props, auth); - } - - /** - * attach content - * @param receiversCc the cc list - * @param title the title - * @param content the content - * @param partContent the partContent - * @param msg the message - * @throws MessagingException - * @throws IOException - */ - private static void attachContent(Collection receiversCc, String title, String content, String partContent,MimeMessage msg) throws MessagingException, IOException { - /** - * set receiverCc - */ - if(CollectionUtils.isNotEmpty(receiversCc)){ - for (String receiverCc : receiversCc){ - msg.addRecipients(Message.RecipientType.CC, InternetAddress.parse(receiverCc)); - } - } - - // set subject - msg.setSubject(title); - MimeMultipart partList = new MimeMultipart(); - // set signature - MimeBodyPart part1 = new MimeBodyPart(); - part1.setContent(partContent, Constants.TEXT_HTML_CHARSET_UTF_8); - // set attach file - MimeBodyPart part2 = new MimeBodyPart(); - File file = new File(xlsFilePath + Constants.SINGLE_SLASH + title + Constants.EXCEL_SUFFIX_XLS); - if (!file.getParentFile().exists()) { - file.getParentFile().mkdirs(); - } - // make excel file - - ExcelUtils.genExcelFile(content,title,xlsFilePath); - - part2.attachFile(file); - part2.setFileName(MimeUtility.encodeText(title + Constants.EXCEL_SUFFIX_XLS,Constants.UTF_8,"B")); - // add components to collection - partList.addBodyPart(part1); - partList.addBodyPart(part2); - msg.setContent(partList); - // 5. send Transport - Transport.send(msg); - // 6. delete saved file - deleteFile(file); - } - - /** - * the string object map - * @param title the title - * @param content the content - * @param showType the showType - * @param retMap the result map - * @param email the email - * @return the result map - * @throws EmailException - */ - private static Map getStringObjectMap(String title, String content, String showType, Map retMap, HtmlEmail email) throws EmailException { - - /** - * the subject of the message to be sent - */ - email.setSubject(title); - /** - * to send information, you can use HTML tags in mail content because of the use of HtmlEmail - */ - if (showType.equals(ShowType.TABLE.getDescp())) { - email.setMsg(htmlTable(content)); - } else if (showType.equals(ShowType.TEXT.getDescp())) { - email.setMsg(htmlText(content)); - } - - // send - email.send(); - - retMap.put(Constants.STATUS, true); - - return retMap; - } - - /** - * file delete - * @param file the file to delete - */ - public static void deleteFile(File file){ - if(file.exists()){ - if(file.delete()){ - logger.info("delete success: {}",file.getAbsolutePath() + file.getName()); - }else{ - logger.info("delete fail: {}", file.getAbsolutePath() + file.getName()); - } - }else{ - logger.info("file not exists: {}", file.getAbsolutePath() + file.getName()); - } - } - - - /** - * handle exception - * @param receivers the receiver list - * @param retMap the result map - * @param e the exception - */ - private static void handleException(Collection receivers, Map retMap, Exception e) { - logger.error("Send email to {} failed", receivers, e); - retMap.put(Constants.MESSAGE, "Send email to {" + String.join(",", receivers) + "} failed," + e.toString()); - } - - -} diff --git a/dolphinscheduler-alert/src/main/java/org/apache/dolphinscheduler/alert/utils/PropertyUtils.java b/dolphinscheduler-alert/src/main/java/org/apache/dolphinscheduler/alert/utils/PropertyUtils.java index 91f7261db2..16bcb6bd79 100644 --- a/dolphinscheduler-alert/src/main/java/org/apache/dolphinscheduler/alert/utils/PropertyUtils.java +++ b/dolphinscheduler-alert/src/main/java/org/apache/dolphinscheduler/alert/utils/PropertyUtils.java @@ -14,19 +14,21 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.dolphinscheduler.alert.utils; +import static org.apache.dolphinscheduler.alert.utils.Constants.ALERT_PROPERTIES_PATH; + import org.apache.dolphinscheduler.common.utils.IOUtils; import org.apache.dolphinscheduler.common.utils.StringUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import java.io.IOException; import java.io.InputStream; import java.util.Properties; import java.util.regex.PatternSyntaxException; -import static org.apache.dolphinscheduler.alert.utils.Constants.ALERT_PROPERTIES_PATH; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * property utils @@ -41,13 +43,16 @@ public class PropertyUtils { private static final Properties properties = new Properties(); + /** + * init properties + */ private static final PropertyUtils propertyUtils = new PropertyUtils(); - private PropertyUtils(){ + private PropertyUtils() { init(); } - private void init(){ + private void init() { String[] propertyFiles = new String[]{ALERT_PROPERTIES_PATH}; for (String fileName : propertyFiles) { InputStream fis = null; @@ -69,6 +74,7 @@ public class PropertyUtils { /** * get property value + * * @param key property name * @return the value */ @@ -82,7 +88,7 @@ public class PropertyUtils { /** * get property value * - * @param key property name + * @param key property name * @param defaultVal default value * @return property value */ @@ -95,7 +101,7 @@ public class PropertyUtils { * get property value * * @param key property name - * @return get property int value , if key == null, then return -1 + * @return get property int value , if key == null, then return -1 */ public static int getInt(String key) { @@ -104,6 +110,7 @@ public class PropertyUtils { /** * get int value + * * @param key the key * @param defaultValue the default value * @return the value related the key or the default value if the key not existed @@ -117,15 +124,16 @@ public class PropertyUtils { try { return Integer.parseInt(value); } catch (NumberFormatException e) { - logger.info(e.getMessage(),e); + logger.info(e.getMessage(), e); } return defaultValue; } /** * get property value + * * @param key property name - * @return the boolean result value + * @return the boolean result value */ public static Boolean getBoolean(String key) { @@ -134,7 +142,7 @@ public class PropertyUtils { } String value = properties.getProperty(key.trim()); - if(null != value){ + if (null != value) { return Boolean.parseBoolean(value); } @@ -143,15 +151,17 @@ public class PropertyUtils { /** * get long value + * * @param key the key * @return if the value not existed, return -1, or will return the related value */ public static long getLong(String key) { - return getLong(key,-1); + return getLong(key, -1); } /** * get long value + * * @param key the key * @param defaultVal the default value * @return the value related the key or the default value if the key not existed @@ -166,7 +176,7 @@ public class PropertyUtils { try { return Long.parseLong(val); } catch (NumberFormatException e) { - logger.info(e.getMessage(),e); + logger.info(e.getMessage(), e); } return defaultVal; @@ -174,16 +184,17 @@ public class PropertyUtils { /** * get double value + * * @param key the key * @return if the value not existed, return -1.0, or will return the related value */ public static double getDouble(String key) { - String val = getString(key); - return getDouble(key,-1.0); + return getDouble(key, -1.0); } /** * get double value + * * @param key the key * @param defaultVal the default value * @return the value related the key or the default value if the key not existed @@ -198,17 +209,17 @@ public class PropertyUtils { try { return Double.parseDouble(val); } catch (NumberFormatException e) { - logger.info(e.getMessage(),e); + logger.info(e.getMessage(), e); } return defaultVal; } - /** - * get array - * @param key property name - * @param splitStr separator + * get array + * + * @param key property name + * @param splitStr separator * @return the result array */ public static String[] getArray(String key, String splitStr) { @@ -219,21 +230,22 @@ public class PropertyUtils { try { return value.split(splitStr); } catch (PatternSyntaxException e) { - logger.info(e.getMessage(),e); + logger.info(e.getMessage(), e); } return null; } /** * get enum + * * @param key the key * @param type the class type * @param defaultValue the default value * @param the generic class type - * @return get enum value + * @return get enum value */ public static > T getEnum(String key, Class type, - T defaultValue) { + T defaultValue) { String val = getString(key); if (val == null) { return defaultValue; @@ -242,7 +254,7 @@ public class PropertyUtils { try { return Enum.valueOf(type, val); } catch (IllegalArgumentException e) { - logger.info(e.getMessage(),e); + logger.info(e.getMessage(), e); } return defaultValue; diff --git a/dolphinscheduler-alert/src/main/resources/alert.properties b/dolphinscheduler-alert/src/main/resources/alert.properties index 6eb701841c..1e26d27fec 100644 --- a/dolphinscheduler-alert/src/main/resources/alert.properties +++ b/dolphinscheduler-alert/src/main/resources/alert.properties @@ -15,46 +15,18 @@ # limitations under the License. # -#alert type is EMAIL/SMS -alert.type=EMAIL +#This configuration file configures the configuration parameters related to the AlertServer. +#These parameters are only related to the AlertServer, and it has nothing to do with the specific Alert Plugin. +#eg : max retry num. +#eg : Alert Server Listener port -# mail server configuration -mail.protocol=SMTP -mail.server.host=xxx.xxx.com -mail.server.port=25 -mail.sender=xxx@xxx.com -mail.user=xxx@xxx.com -mail.passwd=111111 -# TLS -mail.smtp.starttls.enable=true -# SSL -mail.smtp.ssl.enable=false -mail.smtp.ssl.trust=xxx.xxx.com +#alert.plugin.dir config the Alert Plugin dir . AlertServer while find and load the Alert Plugin Jar from this dir when deploy and start AlertServer on the server . +#eg :alert.plugin.dir=/opt/soft/spi/lib/plugin/alert -#xls file path,need create if not exist -#xls.file.path=/tmp/xls +#maven.local.repository=/Users/gaojun/Documents/jianguoyun/localRepository -# Enterprise WeChat configuration -enterprise.wechat.enable=false +#alert.plugin.binding config the Alert Plugin need be load when development and run in IDE +#alert.plugin.binding=\ +# ./dolphinscheduler-alert-plugin/dolphinscheduler-alert-email/pom.xml -#enterprise.wechat.corp.id=xxxxxxx -#enterprise.wechat.secret=xxxxxxx -#enterprise.wechat.agent.id=xxxxxxx -#enterprise.wechat.users=xxxxxxx -#enterprise.wechat.token.url=https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid={corpId}&corpsecret={secret} -#enterprise.wechat.push.url=https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token={token} -#enterprise.wechat.team.send.msg={\"toparty\":\"{toParty}\",\"agentid\":\"{agentId}\",\"msgtype\":\"text\",\"text\":{\"content\":\"{msg}\"},\"safe\":\"0\"} -#enterprise.wechat.user.send.msg={\"touser\":\"{toUser}\",\"agentid\":\"{agentId}\",\"msgtype\":\"markdown\",\"markdown\":{\"content\":\"{msg}\"}} - -plugin.dir=/Users/xx/your/path/to/plugin/dir - -#ding talk configuration -dingtalk.isEnable=flase -dingtalk.webhook=https://oapi.dingtalk.com/robot/send?access_token=xxxxx -dingtalk.keyword= -dingtalk.proxy= -dingtalk.port=80 -dingtalk.user= -dingtalk.password= -dingtalk.isEnableProxy=false diff --git a/dolphinscheduler-alert/src/test/java/org/apache/dolphinscheduler/alert/AlertServerTest.java b/dolphinscheduler-alert/src/test/java/org/apache/dolphinscheduler/alert/AlertServerTest.java new file mode 100644 index 0000000000..a8ead79be9 --- /dev/null +++ b/dolphinscheduler-alert/src/test/java/org/apache/dolphinscheduler/alert/AlertServerTest.java @@ -0,0 +1,91 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.dolphinscheduler.alert; + +import org.apache.dolphinscheduler.alert.plugin.AlertPluginManager; +import org.apache.dolphinscheduler.alert.plugin.DolphinPluginLoader; +import org.apache.dolphinscheduler.alert.plugin.DolphinPluginManagerConfig; +import org.apache.dolphinscheduler.alert.runner.AlertSender; +import org.apache.dolphinscheduler.alert.utils.Constants; +import org.apache.dolphinscheduler.dao.AlertDao; +import org.apache.dolphinscheduler.dao.DaoFactory; +import org.apache.dolphinscheduler.dao.PluginDao; +import org.apache.dolphinscheduler.remote.NettyRemotingServer; +import org.apache.dolphinscheduler.spi.alert.AlertChannel; + +import java.util.concurrent.ConcurrentHashMap; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.powermock.api.mockito.PowerMockito; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; + +@RunWith(PowerMockRunner.class) +@PrepareForTest({AlertServer.class,DaoFactory.class}) +public class AlertServerTest { + + @Before + public void before() { + + } + + @Test + public void testMain() throws Exception { + AlertDao alertDao = PowerMockito.mock(AlertDao.class); + PowerMockito.mockStatic(DaoFactory.class); + PowerMockito.when(DaoFactory.getDaoInstance(AlertDao.class)).thenReturn(alertDao); + + PluginDao pluginDao = PowerMockito.mock(PluginDao.class); + PowerMockito.when(DaoFactory.getDaoInstance(PluginDao.class)).thenReturn(pluginDao); + + AlertChannel alertChannelMock = PowerMockito.mock(AlertChannel.class); + + AlertPluginManager alertPluginManager = PowerMockito.mock(AlertPluginManager.class); + PowerMockito.whenNew(AlertPluginManager.class).withNoArguments().thenReturn(alertPluginManager); + ConcurrentHashMap alertChannelMap = new ConcurrentHashMap<>(); + alertChannelMap.put("pluginName",alertChannelMock); + PowerMockito.when(alertPluginManager.getAlertChannelMap()).thenReturn(alertChannelMap); + + DolphinPluginManagerConfig alertPluginManagerConfig = PowerMockito.mock(DolphinPluginManagerConfig.class); + PowerMockito.whenNew(DolphinPluginManagerConfig.class).withNoArguments().thenReturn(alertPluginManagerConfig); + + NettyRemotingServer nettyRemotingServer = PowerMockito.mock(NettyRemotingServer.class); + PowerMockito.whenNew(NettyRemotingServer.class).withAnyArguments().thenReturn(nettyRemotingServer); + AlertSender alertSender = PowerMockito.mock(AlertSender.class); + PowerMockito.whenNew(AlertSender.class).withAnyArguments().thenReturn(alertSender); + + DolphinPluginLoader dolphinPluginLoader = PowerMockito.mock(DolphinPluginLoader.class); + PowerMockito.whenNew(DolphinPluginLoader.class).withAnyArguments().thenReturn(dolphinPluginLoader); + + AlertServer alertServer = AlertServer.getInstance(); + Assert.assertNotNull(alertServer); + + new Thread(() -> { + alertServer.start(); }) + .start(); + + Thread.sleep(5 * Constants.ALERT_SCAN_INTERVAL); + + alertServer.stop(); + + } + +} diff --git a/dolphinscheduler-alert/src/test/java/org/apache/dolphinscheduler/alert/plugin/AlertPluginManagerTest.java b/dolphinscheduler-alert/src/test/java/org/apache/dolphinscheduler/alert/plugin/AlertPluginManagerTest.java new file mode 100644 index 0000000000..5ed25cc004 --- /dev/null +++ b/dolphinscheduler-alert/src/test/java/org/apache/dolphinscheduler/alert/plugin/AlertPluginManagerTest.java @@ -0,0 +1,65 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.dolphinscheduler.alert.plugin; + +import org.apache.dolphinscheduler.alert.AlertServer; +import org.apache.dolphinscheduler.alert.utils.Constants; +import org.apache.dolphinscheduler.alert.utils.PropertyUtils; +import org.apache.dolphinscheduler.spi.utils.StringUtils; + +import org.junit.Assert; +import org.junit.Ignore; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.collect.ImmutableList; + +/** + * AlertPluginManager Tester. + */ +@Ignore +public class AlertPluginManagerTest { + + private static final Logger logger = LoggerFactory.getLogger(AlertPluginManagerTest.class); + + @Test + public void testLoadPlugins() throws Exception { + logger.info("begin test AlertPluginManagerTest"); + AlertPluginManager alertPluginManager = new AlertPluginManager(); + DolphinPluginManagerConfig alertPluginManagerConfig = new DolphinPluginManagerConfig(); + String path = DolphinPluginLoader.class.getClassLoader().getResource("").getPath(); + alertPluginManagerConfig.setPlugins(path + "../../../dolphinscheduler-alert-plugin/dolphinscheduler-alert-email/pom.xml"); + if (StringUtils.isNotBlank(PropertyUtils.getString(AlertServer.ALERT_PLUGIN_DIR))) { + alertPluginManagerConfig.setInstalledPluginsDir(org.apache.dolphinscheduler.alert.utils.PropertyUtils.getString(AlertServer.ALERT_PLUGIN_DIR, Constants.ALERT_PLUGIN_PATH).trim()); + } + + if (StringUtils.isNotBlank(PropertyUtils.getString(AlertServer.MAVEN_LOCAL_REPOSITORY))) { + alertPluginManagerConfig.setMavenLocalRepository(PropertyUtils.getString(AlertServer.MAVEN_LOCAL_REPOSITORY).trim()); + } + + DolphinPluginLoader alertPluginLoader = new DolphinPluginLoader(alertPluginManagerConfig, ImmutableList.of(alertPluginManager)); + try { + alertPluginLoader.loadPlugins(); + } catch (Exception e) { + throw new RuntimeException("load Alert Plugin Failed !", e); + } + + Assert.assertNotNull(alertPluginManager.getAlertChannelFactoryMap().get("email alert")); + } +} diff --git a/dolphinscheduler-alert/src/test/java/org/apache/dolphinscheduler/alert/plugin/DolphinPluginLoaderTest.java b/dolphinscheduler-alert/src/test/java/org/apache/dolphinscheduler/alert/plugin/DolphinPluginLoaderTest.java new file mode 100644 index 0000000000..5c792db451 --- /dev/null +++ b/dolphinscheduler-alert/src/test/java/org/apache/dolphinscheduler/alert/plugin/DolphinPluginLoaderTest.java @@ -0,0 +1,60 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.dolphinscheduler.alert.plugin; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Ignore; +import org.junit.Test; + +import com.google.common.collect.ImmutableList; + +/** + * DolphinPluginLoader Tester. + */ +@Ignore +public class DolphinPluginLoaderTest { + + @Before + public void before() throws Exception { + } + + @After + public void after() throws Exception { + } + + /** + * Method: loadPlugins() + */ + @Test + public void testLoadPlugins() throws Exception { + AlertPluginManager alertPluginManager = new AlertPluginManager(); + DolphinPluginManagerConfig alertPluginManagerConfig = new DolphinPluginManagerConfig(); + String path = DolphinPluginLoader.class.getClassLoader().getResource("").getPath(); + alertPluginManagerConfig.setPlugins(path + "../../../dolphinscheduler-alert-plugin/dolphinscheduler-alert-email/pom.xml"); + DolphinPluginLoader alertPluginLoader = new DolphinPluginLoader(alertPluginManagerConfig, ImmutableList.of(alertPluginManager)); + try { + alertPluginLoader.loadPlugins(); + } catch (Exception e) { + throw new RuntimeException("load Alert Plugin Failed !", e); + } + + Assert.assertNotNull(alertPluginManager.getAlertChannelFactoryMap().get("email alert")); + } +} diff --git a/dolphinscheduler-alert/src/test/java/org/apache/dolphinscheduler/alert/plugin/EmailAlertPluginTest.java b/dolphinscheduler-alert/src/test/java/org/apache/dolphinscheduler/alert/plugin/EmailAlertPluginTest.java index cdbcf276d3..3983545140 100644 --- a/dolphinscheduler-alert/src/test/java/org/apache/dolphinscheduler/alert/plugin/EmailAlertPluginTest.java +++ b/dolphinscheduler-alert/src/test/java/org/apache/dolphinscheduler/alert/plugin/EmailAlertPluginTest.java @@ -14,67 +14,226 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.dolphinscheduler.alert.plugin; +import org.apache.dolphinscheduler.alert.AlertServer; +import org.apache.dolphinscheduler.alert.runner.AlertSender; import org.apache.dolphinscheduler.alert.utils.Constants; -import org.apache.dolphinscheduler.common.enums.ShowType; -import org.apache.dolphinscheduler.plugin.api.AlertPlugin; -import org.apache.dolphinscheduler.plugin.model.AlertData; -import org.apache.dolphinscheduler.plugin.model.AlertInfo; -import org.apache.dolphinscheduler.plugin.model.PluginName; -import org.junit.Before; -import org.junit.Test; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import org.apache.dolphinscheduler.alert.utils.PropertyUtils; +import org.apache.dolphinscheduler.common.enums.AlertStatus; +import org.apache.dolphinscheduler.common.utils.JSONUtils; +import org.apache.dolphinscheduler.dao.AlertDao; +import org.apache.dolphinscheduler.dao.DaoFactory; +import org.apache.dolphinscheduler.dao.PluginDao; +import org.apache.dolphinscheduler.dao.entity.Alert; +import org.apache.dolphinscheduler.dao.entity.AlertGroup; +import org.apache.dolphinscheduler.dao.entity.AlertPluginInstance; +import org.apache.dolphinscheduler.dao.entity.PluginDefine; +import org.apache.dolphinscheduler.spi.alert.AlertConstants; +import org.apache.dolphinscheduler.spi.alert.ShowType; +import org.apache.dolphinscheduler.spi.params.InputParam; +import org.apache.dolphinscheduler.spi.params.PasswordParam; +import org.apache.dolphinscheduler.spi.params.PluginParamsTransfer; +import org.apache.dolphinscheduler.spi.params.RadioParam; +import org.apache.dolphinscheduler.spi.params.base.DataType; +import org.apache.dolphinscheduler.spi.params.base.ParamsOptions; +import org.apache.dolphinscheduler.spi.params.base.PluginParams; +import org.apache.dolphinscheduler.spi.params.base.Validate; +import org.apache.dolphinscheduler.spi.utils.StringUtils; import java.util.ArrayList; +import java.util.Date; +import java.util.LinkedHashMap; import java.util.List; -import java.util.Map; -import static org.junit.Assert.*; +import org.junit.Assert; +import org.junit.Ignore; +import org.junit.Test; +import com.google.common.collect.ImmutableList; + +/** + * test load and use alert plugin + */ public class EmailAlertPluginTest { - private static final Logger logger = LoggerFactory.getLogger(EmailAlertPluginTest.class); + AlertDao alertDao = DaoFactory.getDaoInstance(AlertDao.class); + PluginDao pluginDao = DaoFactory.getDaoInstance(PluginDao.class); - private AlertPlugin plugin; + @Test + @Ignore + public void testRunSend() throws Exception { - @Before - public void before() { - plugin = new EmailAlertPlugin(); - } + //create alert group + AlertGroup alertGroup = new AlertGroup(); + alertGroup.setDescription("test alert group 1"); + alertGroup.setGroupName("testalertg1"); + alertDao.getAlertGroupMapper().insert(alertGroup); - @Test - public void getId() { - String id = plugin.getId(); - assertEquals(Constants.PLUGIN_DEFAULT_EMAIL_ID, id); - } + //add alert + Alert alert1 = new Alert(); + alert1.setTitle("test alert"); + LinkedHashMap map1 = new LinkedHashMap<>(); + map1.put("mysql service name", "mysql200"); + map1.put("mysql address", "192.168.xx.xx"); + map1.put("port", "3306"); + map1.put(AlertConstants.SHOW_TYPE, ShowType.TEXT.getDescp()); + map1.put("no index of number", "80"); + map1.put("database client connections", "190"); + + LinkedHashMap map2 = new LinkedHashMap<>(); + map2.put("mysql service name", "mysql210"); + map2.put("mysql address", "192.168.xx.xx"); + map2.put("port", "3306"); + map2.put("no index of number", "10"); + map1.put(AlertConstants.SHOW_TYPE, ShowType.TABLE.getDescp()); + map2.put("database client connections", "90"); + + List> maps = new ArrayList<>(); + maps.add(0, map1); + maps.add(1, map2); + String mapjson = JSONUtils.toJsonString(maps); + alert1.setContent(mapjson); + alert1.setLog("log log"); + alert1.setAlertGroupId(alertGroup.getId()); + alertDao.addAlert(alert1); + + List alertList = new ArrayList<>(); + alertList.add(alert1); + + //load email alert plugin + AlertPluginManager alertPluginManager = new AlertPluginManager(); + DolphinPluginManagerConfig alertPluginManagerConfig = new DolphinPluginManagerConfig(); + String path = DolphinPluginLoader.class.getClassLoader().getResource("").getPath(); + alertPluginManagerConfig.setPlugins(path + "../../../dolphinscheduler-alert-plugin/dolphinscheduler-alert-email/pom.xml"); + if (StringUtils.isNotBlank(PropertyUtils.getString(AlertServer.ALERT_PLUGIN_DIR))) { + alertPluginManagerConfig.setInstalledPluginsDir(PropertyUtils.getString(AlertServer.ALERT_PLUGIN_DIR, Constants.ALERT_PLUGIN_PATH).trim()); + } + + if (StringUtils.isNotBlank(PropertyUtils.getString(AlertServer.MAVEN_LOCAL_REPOSITORY))) { + alertPluginManagerConfig.setMavenLocalRepository(PropertyUtils.getString(AlertServer.MAVEN_LOCAL_REPOSITORY).trim()); + } + + DolphinPluginLoader alertPluginLoader = new DolphinPluginLoader(alertPluginManagerConfig, ImmutableList.of(alertPluginManager)); + try { + alertPluginLoader.loadPlugins(); + } catch (Exception e) { + throw new RuntimeException("load Alert Plugin Failed !", e); + } + + //create email alert plugin instance + AlertPluginInstance alertPluginInstance = new AlertPluginInstance(); + alertPluginInstance.setCreateTime(new Date()); + alertPluginInstance.setInstanceName("test email alert"); + + List pluginDefineList = pluginDao.getPluginDefineMapper().queryByNameAndType("email alert", "alert"); + if (pluginDefineList == null || pluginDefineList.size() == 0) { + throw new RuntimeException("no alert plugin be load"); + } + PluginDefine pluginDefine = pluginDefineList.get(0); + alertPluginInstance.setPluginDefineId(pluginDefine.getId()); + alertPluginInstance.setPluginInstanceParams(getEmailAlertParams()); + alertDao.getAlertPluginInstanceMapper().insert(alertPluginInstance); + + AlertSender alertSender = new AlertSender(alertList, alertDao, alertPluginManager, pluginDao); + alertSender.run(); + + Alert alertResult = alertDao.getAlertMapper().selectById(alert1.getId()); + Assert.assertNotNull(alertResult); + Assert.assertEquals(alertResult.getAlertStatus(), AlertStatus.EXECUTION_FAILURE); + + alertDao.getAlertGroupMapper().deleteById(alertGroup.getId()); + alertDao.getAlertPluginInstanceMapper().deleteById(alertPluginInstance.getId()); + alertDao.getAlertMapper().deleteById(alert1.getId()); - @Test - public void getName() { - PluginName pluginName = plugin.getName(); - assertEquals(Constants.PLUGIN_DEFAULT_EMAIL_CH, pluginName.getChinese()); - assertEquals(Constants.PLUGIN_DEFAULT_EMAIL_EN, pluginName.getEnglish()); } - @Test - public void process() { - AlertInfo alertInfo = new AlertInfo(); - AlertData alertData = new AlertData(); - alertData.setId(1) - .setAlertGroupId(1) - .setContent("[\"alarm time:2018-02-05\", \"service name:MYSQL_ALTER\", \"alarm name:MYSQL_ALTER_DUMP\", " + - "\"get the alarm exception.!,interface error,exception information:timed out\", \"request address:http://blog.csdn.net/dreamInTheWorld/article/details/78539286\"]") - .setLog("test log") - .setReceivers("xx@xx.com") - .setReceiversCc("xx@xx.com") - .setShowType(ShowType.TEXT.getDescp()) - .setTitle("test title"); - - alertInfo.setAlertData(alertData); - List list = new ArrayList(){{ add("xx@xx.com"); }}; - alertInfo.addProp("receivers", list); -// Map ret = plugin.process(alertInfo); -// assertFalse(Boolean.parseBoolean(String.valueOf(ret.get(Constants.STATUS)))); + public String getEmailAlertParams() { + + List paramsList = new ArrayList<>(); + InputParam receivesParam = InputParam.newBuilder("receivers", "receivers") + .setValue("540957506@qq.com") + .addValidate(Validate.newBuilder().setRequired(true).build()) + .build(); + + InputParam mailSmtpHost = InputParam.newBuilder("mailServerHost", "mail.smtp.host") + .addValidate(Validate.newBuilder().setRequired(true).build()) + .setValue("smtp.exmail.qq.com") + .build(); + + InputParam mailSmtpPort = InputParam.newBuilder("mailServerPort", "mail.smtp.port") + .addValidate(Validate.newBuilder() + .setRequired(true) + .setType(DataType.NUMBER.getDataType()) + .build()) + .setValue(25) + .build(); + + InputParam mailSender = InputParam.newBuilder("mailSender", "mail.sender") + .addValidate(Validate.newBuilder().setRequired(true).build()) + .setValue("easyscheduler@analysys.com.cn") + .build(); + + RadioParam enableSmtpAuth = RadioParam.newBuilder("enableSmtpAuth", "mail.smtp.auth") + .addParamsOptions(new ParamsOptions("YES", true, false)) + .addParamsOptions(new ParamsOptions("NO", false, false)) + .addValidate(Validate.newBuilder().setRequired(true).build()) + .setValue(true) + .build(); + + InputParam mailUser = InputParam.newBuilder("mailUser", "mail.user") + .setPlaceholder("if enable use authentication, you need input user") + .setValue("easyscheduler@analysys.com.cn") + .build(); + + PasswordParam mailPassword = PasswordParam.newBuilder("mailPasswd", "mail.passwd") + .setPlaceholder("if enable use authentication, you need input password") + .setValue("xxxxxxx") + .build(); + + RadioParam enableTls = RadioParam.newBuilder("starttlsEnable", "mail.smtp.starttls.enable") + .addParamsOptions(new ParamsOptions("YES", true, false)) + .addParamsOptions(new ParamsOptions("NO", false, false)) + .addValidate(Validate.newBuilder().setRequired(true).build()) + .setValue(true) + .build(); + + RadioParam enableSsl = RadioParam.newBuilder("sslEnable", "mail.smtp.ssl.enable") + .addParamsOptions(new ParamsOptions("YES", true, false)) + .addParamsOptions(new ParamsOptions("NO", false, false)) + .addValidate(Validate.newBuilder().setRequired(true).build()) + .setValue(false) + .build(); + + InputParam sslTrust = InputParam.newBuilder("mailSmtpSslTrust", "mail.smtp.ssl.trust") + .addValidate(Validate.newBuilder().setRequired(true).build()) + .setValue("smtp.exmail.qq.com") + .build(); + + List emailShowTypeList = new ArrayList<>(); + emailShowTypeList.add(new ParamsOptions(ShowType.TABLE.getDescp(), ShowType.TABLE.getDescp(), false)); + emailShowTypeList.add(new ParamsOptions(ShowType.TEXT.getDescp(), ShowType.TEXT.getDescp(), false)); + emailShowTypeList.add(new ParamsOptions(ShowType.ATTACHMENT.getDescp(), ShowType.ATTACHMENT.getDescp(), false)); + emailShowTypeList.add(new ParamsOptions(ShowType.TABLEATTACHMENT.getDescp(), ShowType.TABLEATTACHMENT.getDescp(), false)); + RadioParam showType = RadioParam.newBuilder(AlertConstants.SHOW_TYPE, "showType") + .setParamsOptionsList(emailShowTypeList) + .setValue(ShowType.TABLE.getDescp()) + .addValidate(Validate.newBuilder().setRequired(true).build()) + .build(); + + paramsList.add(receivesParam); + paramsList.add(mailSmtpHost); + paramsList.add(mailSmtpPort); + paramsList.add(mailSender); + paramsList.add(enableSmtpAuth); + paramsList.add(mailUser); + paramsList.add(mailPassword); + paramsList.add(enableTls); + paramsList.add(enableSsl); + paramsList.add(sslTrust); + paramsList.add(showType); + + return PluginParamsTransfer.transferParamsToJson(paramsList); } -} \ No newline at end of file +} diff --git a/dolphinscheduler-alert/src/test/java/org/apache/dolphinscheduler/alert/processor/AlertRequestProcessorTest.java b/dolphinscheduler-alert/src/test/java/org/apache/dolphinscheduler/alert/processor/AlertRequestProcessorTest.java new file mode 100644 index 0000000000..0126eb3dae --- /dev/null +++ b/dolphinscheduler-alert/src/test/java/org/apache/dolphinscheduler/alert/processor/AlertRequestProcessorTest.java @@ -0,0 +1,61 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.dolphinscheduler.alert.processor; + +import org.apache.dolphinscheduler.alert.plugin.AlertPluginManager; +import org.apache.dolphinscheduler.dao.AlertDao; +import org.apache.dolphinscheduler.dao.PluginDao; +import org.apache.dolphinscheduler.remote.command.Command; +import org.apache.dolphinscheduler.remote.command.CommandType; +import org.apache.dolphinscheduler.remote.command.alert.AlertSendRequestCommand; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.powermock.api.mockito.PowerMockito; + +import io.netty.channel.Channel; + +/** + * alert request processor test + */ +public class AlertRequestProcessorTest { + + private AlertDao alertDao; + private PluginDao pluginDao; + private AlertPluginManager alertPluginManager; + + private AlertRequestProcessor alertRequestProcessor; + + @Before + public void before() { + alertDao = PowerMockito.mock(AlertDao.class); + pluginDao = PowerMockito.mock(PluginDao.class); + alertPluginManager = PowerMockito.mock(AlertPluginManager.class); + alertRequestProcessor = new AlertRequestProcessor(alertDao,alertPluginManager,pluginDao); + } + + @Test + public void testProcess() { + Channel channel = PowerMockito.mock(Channel.class); + AlertSendRequestCommand alertSendRequestCommand = new AlertSendRequestCommand(1,"title","content"); + Command reqCommand = alertSendRequestCommand.convert2Command(); + Assert.assertEquals(CommandType.ALERT_SEND_REQUEST,reqCommand.getType()); + alertRequestProcessor.process(channel,reqCommand); + } +} diff --git a/dolphinscheduler-alert/src/test/java/org/apache/dolphinscheduler/alert/runner/AlertSenderTest.java b/dolphinscheduler-alert/src/test/java/org/apache/dolphinscheduler/alert/runner/AlertSenderTest.java new file mode 100644 index 0000000000..2664bdcd29 --- /dev/null +++ b/dolphinscheduler-alert/src/test/java/org/apache/dolphinscheduler/alert/runner/AlertSenderTest.java @@ -0,0 +1,181 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.dolphinscheduler.alert.runner; + +import org.apache.dolphinscheduler.alert.plugin.AlertPluginManager; +import org.apache.dolphinscheduler.dao.AlertDao; +import org.apache.dolphinscheduler.dao.PluginDao; +import org.apache.dolphinscheduler.dao.entity.Alert; +import org.apache.dolphinscheduler.dao.entity.AlertPluginInstance; +import org.apache.dolphinscheduler.dao.entity.PluginDefine; +import org.apache.dolphinscheduler.remote.command.alert.AlertSendResponseCommand; +import org.apache.dolphinscheduler.spi.alert.AlertChannel; +import org.apache.dolphinscheduler.spi.alert.AlertResult; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mockito; +import org.powermock.api.mockito.PowerMockito; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * alert sender test + */ +public class AlertSenderTest { + + private static final Logger logger = LoggerFactory.getLogger(AlertSenderTest.class); + + private AlertDao alertDao; + private PluginDao pluginDao; + private AlertPluginManager alertPluginManager; + + private AlertSender alertSender; + + @Before + public void before() { + alertDao = PowerMockito.mock(AlertDao.class); + pluginDao = PowerMockito.mock(PluginDao.class); + alertPluginManager = PowerMockito.mock(AlertPluginManager.class); + + } + + @Test + public void testSyncHandler() { + + int alertGroupId = 1; + String title = "alert mail test title"; + String content = "alert mail test content"; + alertSender = new AlertSender(alertDao,alertPluginManager,pluginDao); + + //1.alert instance does not exist + PowerMockito.when(alertDao.listInstanceByAlertGroupId(alertGroupId)).thenReturn(null); + + AlertSendResponseCommand alertSendResponseCommand = alertSender.syncHandler(alertGroupId, title, content); + Assert.assertFalse(alertSendResponseCommand.getResStatus()); + alertSendResponseCommand.getResResults().forEach(result -> + logger.info("alert send response result, status:{}, message:{}",result.getStatus(),result.getMessage())); + + //2.alert plugin does not exist + int pluginDefineId = 1; + String pluginInstanceParams = "alert-instance-mail-params"; + String pluginInstanceName = "alert-instance-mail"; + List alertInstanceList = new ArrayList<>(); + AlertPluginInstance alertPluginInstance = new AlertPluginInstance( + pluginDefineId,pluginInstanceParams,pluginInstanceName); + alertInstanceList.add(alertPluginInstance); + PowerMockito.when(alertDao.listInstanceByAlertGroupId(1)).thenReturn(alertInstanceList); + + String pluginName = "alert-plugin-mail"; + PluginDefine pluginDefine = new PluginDefine(pluginName,"1",null); + PowerMockito.when(pluginDao.getPluginDefineById(pluginDefineId)).thenReturn(pluginDefine); + + alertSendResponseCommand = alertSender.syncHandler(alertGroupId, title, content); + Assert.assertFalse(alertSendResponseCommand.getResStatus()); + alertSendResponseCommand.getResResults().forEach(result -> + logger.info("alert send response result, status:{}, message:{}",result.getStatus(),result.getMessage())); + + //3.alert result value is null + AlertChannel alertChannelMock = PowerMockito.mock(AlertChannel.class); + PowerMockito.when(alertChannelMock.process(Mockito.any())).thenReturn(null); + Map alertChannelMap = new ConcurrentHashMap<>(); + alertChannelMap.put(pluginName,alertChannelMock); + PowerMockito.when(alertPluginManager.getAlertChannelMap()).thenReturn(alertChannelMap); + + alertSendResponseCommand = alertSender.syncHandler(alertGroupId, title, content); + Assert.assertFalse(alertSendResponseCommand.getResStatus()); + alertSendResponseCommand.getResResults().forEach(result -> + logger.info("alert send response result, status:{}, message:{}",result.getStatus(),result.getMessage())); + + //4.abnormal information inside the alert plug-in code + AlertResult alertResult = new AlertResult(); + alertResult.setStatus(String.valueOf(false)); + alertResult.setMessage("Abnormal information inside the alert plug-in code"); + PowerMockito.when(alertChannelMock.process(Mockito.any())).thenReturn(alertResult); + alertChannelMap = new ConcurrentHashMap<>(); + alertChannelMap.put(pluginName,alertChannelMock); + PowerMockito.when(alertPluginManager.getAlertChannelMap()).thenReturn(alertChannelMap); + + alertSendResponseCommand = alertSender.syncHandler(alertGroupId, title, content); + Assert.assertFalse(alertSendResponseCommand.getResStatus()); + alertSendResponseCommand.getResResults().forEach(result -> + logger.info("alert send response result, status:{}, message:{}",result.getStatus(),result.getMessage())); + + //5.alert plugin send success + alertResult = new AlertResult(); + alertResult.setStatus(String.valueOf(true)); + alertResult.setMessage(String.format("Alert Plugin %s send success",pluginInstanceName)); + PowerMockito.when(alertChannelMock.process(Mockito.any())).thenReturn(alertResult); + alertChannelMap = new ConcurrentHashMap<>(); + alertChannelMap.put(pluginName,alertChannelMock); + PowerMockito.when(alertPluginManager.getAlertChannelMap()).thenReturn(alertChannelMap); + + alertSendResponseCommand = alertSender.syncHandler(alertGroupId, title, content); + Assert.assertTrue(alertSendResponseCommand.getResStatus()); + alertSendResponseCommand.getResResults().forEach(result -> + logger.info("alert send response result, status:{}, message:{}",result.getStatus(),result.getMessage())); + + } + + @Test + public void testRun() { + int alertGroupId = 1; + String title = "alert mail test title"; + String content = "alert mail test content"; + List alertList = new ArrayList<>(); + Alert alert = new Alert(); + alert.setAlertGroupId(alertGroupId); + alert.setTitle(title); + alert.setContent(content); + alertList.add(alert); + + alertSender = new AlertSender(alertList,alertDao,alertPluginManager,pluginDao); + + int pluginDefineId = 1; + String pluginInstanceParams = "alert-instance-mail-params"; + String pluginInstanceName = "alert-instance-mail"; + List alertInstanceList = new ArrayList<>(); + AlertPluginInstance alertPluginInstance = new AlertPluginInstance( + pluginDefineId,pluginInstanceParams,pluginInstanceName); + alertInstanceList.add(alertPluginInstance); + PowerMockito.when(alertDao.listInstanceByAlertGroupId(alertGroupId)).thenReturn(alertInstanceList); + + String pluginName = "alert-plugin-mail"; + PluginDefine pluginDefine = new PluginDefine(pluginName,"1",null); + PowerMockito.when(pluginDao.getPluginDefineById(pluginDefineId)).thenReturn(pluginDefine); + + AlertResult alertResult = new AlertResult(); + alertResult.setStatus(String.valueOf(true)); + alertResult.setMessage(String.format("Alert Plugin %s send success",pluginInstanceName)); + AlertChannel alertChannelMock = PowerMockito.mock(AlertChannel.class); + PowerMockito.when(alertChannelMock.process(Mockito.any())).thenReturn(alertResult); + ConcurrentHashMap alertChannelMap = new ConcurrentHashMap<>(); + alertChannelMap.put(pluginName,alertChannelMock); + PowerMockito.when(alertPluginManager.getAlertChannelMap()).thenReturn(alertChannelMap); + Assert.assertTrue(Boolean.parseBoolean(alertResult.getStatus())); + alertSender.run(); + + } + +} diff --git a/dolphinscheduler-alert/src/test/java/org/apache/dolphinscheduler/alert/template/AlertTemplateFactoryTest.java b/dolphinscheduler-alert/src/test/java/org/apache/dolphinscheduler/alert/template/AlertTemplateFactoryTest.java deleted file mode 100644 index 32201e6011..0000000000 --- a/dolphinscheduler-alert/src/test/java/org/apache/dolphinscheduler/alert/template/AlertTemplateFactoryTest.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.dolphinscheduler.alert.template; - -import org.apache.dolphinscheduler.alert.template.impl.DefaultHTMLTemplate; -import org.apache.dolphinscheduler.alert.utils.Constants; -import org.apache.dolphinscheduler.alert.utils.PropertyUtils; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mockito; -import org.powermock.api.mockito.PowerMockito; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import static org.mockito.Mockito.*; -import static org.junit.Assert.*; - -/** - * test class for AlertTemplateFactory - */ -@RunWith(PowerMockRunner.class) -@PrepareForTest(PropertyUtils.class) -public class AlertTemplateFactoryTest { - - private static final Logger logger = LoggerFactory.getLogger(AlertTemplateFactoryTest.class); - - /** - * GetMessageTemplate method test - */ - @Test - public void testGetMessageTemplate(){ - - PowerMockito.mockStatic(PropertyUtils.class); - - AlertTemplate defaultTemplate = AlertTemplateFactory.getMessageTemplate(); - - assertTrue(defaultTemplate instanceof DefaultHTMLTemplate); - } - - /** - * GetMessageTemplate method throw Exception test - */ - @Test - public void testGetMessageTemplateException(){ - - AlertTemplate defaultTemplate = AlertTemplateFactory.getMessageTemplate(); - assertTrue(defaultTemplate instanceof DefaultHTMLTemplate); - } -} diff --git a/dolphinscheduler-alert/src/test/java/org/apache/dolphinscheduler/alert/template/impl/DefaultHTMLTemplateTest.java b/dolphinscheduler-alert/src/test/java/org/apache/dolphinscheduler/alert/template/impl/DefaultHTMLTemplateTest.java deleted file mode 100644 index c88f69224d..0000000000 --- a/dolphinscheduler-alert/src/test/java/org/apache/dolphinscheduler/alert/template/impl/DefaultHTMLTemplateTest.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.dolphinscheduler.alert.template.impl; - -import org.apache.dolphinscheduler.common.utils.*; -import org.apache.dolphinscheduler.alert.utils.Constants; -import org.apache.dolphinscheduler.common.enums.ShowType; -import org.junit.Test; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.ArrayList; -import java.util.LinkedHashMap; -import java.util.List; - -import static org.junit.Assert.*; - -/** - * test class for DefaultHTMLTemplate - */ -public class DefaultHTMLTemplateTest{ - - private static final Logger logger = LoggerFactory.getLogger(DefaultHTMLTemplateTest.class); - - /** - * only need test method GetMessageFromTemplate - */ - @Test - public void testGetMessageFromTemplate(){ - - DefaultHTMLTemplate template = new DefaultHTMLTemplate(); - - String tableTypeMessage = template.getMessageFromTemplate(list2String(), ShowType.TABLE,true); - - assertEquals(tableTypeMessage,generateMockTableTypeResultByHand()); - - String textTypeMessage = template.getMessageFromTemplate(list2String(), ShowType.TEXT,true); - - assertEquals(textTypeMessage,generateMockTextTypeResultByHand()); - } - - /** - * generate some simulation data - */ - private String list2String(){ - - LinkedHashMap map1 = new LinkedHashMap<>(); - map1.put("mysql service name","mysql200"); - map1.put("mysql address","192.168.xx.xx"); - map1.put("database client connections","190"); - map1.put("port","3306"); - map1.put("no index of number","80"); - - LinkedHashMap map2 = new LinkedHashMap<>(); - map2.put("mysql service name","mysql210"); - map2.put("mysql address","192.168.xx.xx"); - map2.put("database client connections","90"); - map2.put("port","3306"); - map2.put("no index of number","10"); - - List> maps = new ArrayList<>(); - maps.add(0,map1); - maps.add(1,map2); - String mapjson = JSONUtils.toJsonString(maps); - logger.info(mapjson); - - return mapjson; - } - - private String generateMockTableTypeResultByHand(){ - - return Constants.HTML_HEADER_PREFIX + - "mysql service namemysql addressdatabase client connectionsportno index of number\n" + - "mysql200192.168.xx.xx190330680mysql210192.168.xx.xx90330610" + Constants.TABLE_BODY_HTML_TAIL; - - } - - private String generateMockTextTypeResultByHand(){ - - return Constants.HTML_HEADER_PREFIX + "{\"mysql service name\":\"mysql200\",\"mysql address\":\"192.168.xx.xx\",\"database client connections\":\"190\",\"port\":\"3306\",\"no index of number\":\"80\"}{\"mysql service name\":\"mysql210\",\"mysql address\":\"192.168.xx.xx\",\"database client connections\":\"90\",\"port\":\"3306\",\"no index of number\":\"10\"}" + Constants.TABLE_BODY_HTML_TAIL; - } -} diff --git a/dolphinscheduler-alert/src/test/java/org/apache/dolphinscheduler/alert/utils/DingTalkUtilsTest.java b/dolphinscheduler-alert/src/test/java/org/apache/dolphinscheduler/alert/utils/DingTalkUtilsTest.java deleted file mode 100644 index 049881c087..0000000000 --- a/dolphinscheduler-alert/src/test/java/org/apache/dolphinscheduler/alert/utils/DingTalkUtilsTest.java +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.dolphinscheduler.alert.utils; - -import org.apache.http.client.config.RequestConfig; -import org.apache.http.impl.client.CloseableHttpClient; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mockito; -import org.powermock.api.mockito.PowerMockito; -import org.powermock.core.classloader.annotations.PowerMockIgnore; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.IOException; - -import static org.junit.Assert.*; - -@PrepareForTest(PropertyUtils.class) -@RunWith(PowerMockRunner.class) -@PowerMockIgnore("javax.net.ssl.*") -public class DingTalkUtilsTest { - Logger logger = LoggerFactory.getLogger(DingTalkUtilsTest.class); - - private static final String mockUrl = "https://oapi.dingtalk.com/robot/send?access_token=test"; - private static final String mockKeyWords = "onway"; - private static final String msg = "ding talk test"; - - @Before - public void init(){ - PowerMockito.mockStatic(PropertyUtils.class); - Mockito.when(PropertyUtils.getString(Constants.DINGTALK_WEBHOOK)).thenReturn(mockUrl); - Mockito.when(PropertyUtils.getString(Constants.DINGTALK_KEYWORD)).thenReturn(mockKeyWords); - Mockito.when(PropertyUtils.getBoolean(Constants.DINGTALK_PROXY_ENABLE)).thenReturn(true); - Mockito.when(PropertyUtils.getString(Constants.DINGTALK_PROXY)).thenReturn("proxy.com.cn"); - Mockito.when(PropertyUtils.getString(Constants.DINGTALK_USER)).thenReturn("user"); - Mockito.when(PropertyUtils.getString(Constants.DINGTALK_PASSWORD)).thenReturn("pswd"); - Mockito.when(PropertyUtils.getInt(Constants.DINGTALK_PORT)).thenReturn(80); - } - -// @Test -// @Ignore -// public void testSendMsg() { -// try { -// String msgTosend = "msg to send"; -// logger.info(PropertyUtils.getString(Constants.DINGTALK_WEBHOOK)); -// String rsp = DingTalkUtils.sendDingTalkMsg(msgTosend, Constants.UTF_8); -// logger.info("send msg result:{}",rsp); -// String errmsg = JSONUtils.parseObject(rsp).getString("errmsg"); -// Assert.assertEquals("ok", errmsg); -// } catch (Exception e) { -// e.printStackTrace(); -// } -// } - - @Test - public void testCreateDefaultClient() { - CloseableHttpClient client = DingTalkUtils.getDefaultClient();; - try { - Assert.assertNotNull(client); - client.close(); - } catch (IOException ex) { - logger.info("close exception",ex.getMessage()); - new Throwable(); - } - } - @Test - public void testCreateProxyClient() { - CloseableHttpClient client = DingTalkUtils.getProxyClient(); - try { - Assert.assertNotNull(client); - client.close(); - } catch (IOException ex) { - logger.info("close exception",ex.getMessage()); - new Throwable(); - } - - } - @Test - public void testProxyConfig() { - RequestConfig rc = DingTalkUtils.getProxyConfig(); - Assert.assertEquals(rc.getProxy().getPort(), 80); - Assert.assertEquals(rc.getProxy().getHostName(), "proxy.com.cn"); - } - - @Test - public void testDingTalkMsgToJson() { - String jsonString = DingTalkUtils.textToJsonString("this is test"); - - logger.info(jsonString); - String expect = "{\"text\":{\"content\":\"this is test\"},\"msgtype\":\"text\"}"; - Assert.assertEquals(expect, jsonString); - } - @Test - public void testDingTalkMsgUtf8() { - String msg = DingTalkUtils.textToJsonString("this is test:中文"); - - logger.info("test support utf8, actual:" + msg); - logger.info("test support utf8, actual:" + DingTalkUtils.isEnableDingTalk); - String expect = "{\"text\":{\"content\":\"this is test:中文\"},\"msgtype\":\"text\"}"; - Assert.assertEquals(expect, msg); - } - -} diff --git a/dolphinscheduler-alert/src/test/java/org/apache/dolphinscheduler/alert/utils/EnterpriseWeChatUtilsTest.java b/dolphinscheduler-alert/src/test/java/org/apache/dolphinscheduler/alert/utils/EnterpriseWeChatUtilsTest.java deleted file mode 100644 index 1a70c5becb..0000000000 --- a/dolphinscheduler-alert/src/test/java/org/apache/dolphinscheduler/alert/utils/EnterpriseWeChatUtilsTest.java +++ /dev/null @@ -1,283 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.dolphinscheduler.alert.utils; - -import org.apache.dolphinscheduler.common.enums.AlertType; -import org.apache.dolphinscheduler.common.enums.ShowType; -import org.apache.dolphinscheduler.common.utils.JSONUtils; -import org.apache.dolphinscheduler.dao.entity.Alert; -import org.apache.dolphinscheduler.plugin.model.AlertData; - -import java.util.ArrayList; -import java.util.LinkedHashMap; -import java.util.List; - -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mockito; -import org.powermock.api.mockito.PowerMockito; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; - -/** - * Please manually modify the configuration file before testing. - * file: alert.properties - * enterprise.wechat.corp.id - * enterprise.wechat.secret - * enterprise.wechat.token.url - * enterprise.wechat.push.url - * enterprise.wechat.send.msg - * enterprise.wechat.agent.id - * enterprise.wechat.users - */ -@PrepareForTest(PropertyUtils.class) -@RunWith(PowerMockRunner.class) -public class EnterpriseWeChatUtilsTest { - - private static final String toParty = "wwc99134b6fc1edb6"; - private static final String enterpriseWechatSecret = "Uuv2KFrkdf7SeKOsTDCpsTkpawXBMNRhFy6VKX5FV"; - private static final String enterpriseWechatAgentId = "1000004"; - private static final String enterpriseWechatUsers = "LiGang,journey"; - private static final String msg = "hello world"; - - private static final String enterpriseWechatTeamSendMsg = "{\\\"toparty\\\":\\\"{toParty}\\\",\\\"agentid\\\":\\\"{agentId}\\\"" - + - ",\\\"msgtype\\\":\\\"text\\\",\\\"text\\\":{\\\"content\\\":\\\"{msg}\\\"},\\\"safe\\\":\\\"0\\\"}"; - private static final String enterpriseWechatUserSendMsg = "{\\\"touser\\\":\\\"{toUser}\\\",\\\"agentid\\\":\\\"{agentId}\\\"" - + - ",\\\"msgtype\\\":\\\"markdown\\\",\\\"markdown\\\":{\\\"content\\\":\\\"{msg}\\\"}}"; - - @Before - public void init() { - PowerMockito.mockStatic(PropertyUtils.class); - Mockito.when(PropertyUtils.getBoolean(Constants.ENTERPRISE_WECHAT_ENABLE)).thenReturn(true); - Mockito.when(PropertyUtils.getString(Constants.ENTERPRISE_WECHAT_USER_SEND_MSG)).thenReturn(enterpriseWechatUserSendMsg); - Mockito.when(PropertyUtils.getString(Constants.ENTERPRISE_WECHAT_TEAM_SEND_MSG)).thenReturn(enterpriseWechatTeamSendMsg); - } - - @Test - public void testIsEnable() { - Boolean weChartEnable = EnterpriseWeChatUtils.isEnable(); - Assert.assertTrue(weChartEnable); - } - - @Test - public void testMakeTeamSendMsg1() { - String sendMsg = EnterpriseWeChatUtils.makeTeamSendMsg(toParty, enterpriseWechatSecret, msg); - Assert.assertTrue(sendMsg.contains(toParty)); - Assert.assertTrue(sendMsg.contains(enterpriseWechatSecret)); - Assert.assertTrue(sendMsg.contains(msg)); - - } - - @Test - public void testMakeTeamSendMsg2() { - List parties = new ArrayList<>(); - parties.add(toParty); - parties.add("test1"); - - String sendMsg = EnterpriseWeChatUtils.makeTeamSendMsg(parties, enterpriseWechatSecret, msg); - Assert.assertTrue(sendMsg.contains(toParty)); - Assert.assertTrue(sendMsg.contains(enterpriseWechatSecret)); - Assert.assertTrue(sendMsg.contains(msg)); - } - - @Test - public void tesMakeUserSendMsg1() { - - String sendMsg = EnterpriseWeChatUtils.makeUserSendMsg(enterpriseWechatUsers, enterpriseWechatAgentId, msg); - Assert.assertTrue(sendMsg.contains(enterpriseWechatUsers)); - Assert.assertTrue(sendMsg.contains(enterpriseWechatAgentId)); - Assert.assertTrue(sendMsg.contains(msg)); - } - - @Test - public void tesMakeUserSendMsg2() { - List users = new ArrayList<>(); - users.add("user1"); - users.add("user2"); - - String sendMsg = EnterpriseWeChatUtils.makeUserSendMsg(users, enterpriseWechatAgentId, msg); - Assert.assertTrue(sendMsg.contains(users.get(0))); - Assert.assertTrue(sendMsg.contains(users.get(1))); - Assert.assertTrue(sendMsg.contains(enterpriseWechatAgentId)); - Assert.assertTrue(sendMsg.contains(msg)); - } - - @Test - public void testMarkdownByAlertForText() { - Alert alertForText = createAlertForText(); - AlertData alertData = new AlertData(); - alertData.setTitle(alertForText.getTitle()) - .setShowType(alertForText.getShowType().getDescp()) - .setContent(alertForText.getContent()); - String result = EnterpriseWeChatUtils.markdownByAlert(alertData); - Assert.assertNotNull(result); - } - - @Test - public void testMarkdownByAlertForTable() { - Alert alertForText = createAlertForTable(); - AlertData alertData = new AlertData(); - alertData.setTitle(alertForText.getTitle()) - .setShowType(alertForText.getShowType().getDescp()) - .setContent(alertForText.getContent()); - String result = EnterpriseWeChatUtils.markdownByAlert(alertData); - Assert.assertNotNull(result); - } - - private Alert createAlertForText() { - String content = "[{\"id\":\"69\"," - + - "\"name\":\"UserBehavior-0--1193959466\"," - + - "\"Job name\":\"Start workflow\"," - + - "\"State\":\"SUCCESS\"," - + - "\"Recovery\":\"NO\"," - + - "\"Run time\":\"1\"," - + - "\"Start time\": \"2018-08-06 10:31:34.0\"," - + - "\"End time\": \"2018-08-06 10:31:49.0\"," - + - "\"Host\": \"192.168.xx.xx\"," - + - "\"Notify group\" :\"4\"}]"; - - Alert alert = new Alert(); - alert.setTitle("Mysql Exception"); - alert.setShowType(ShowType.TEXT); - alert.setContent(content); - alert.setAlertType(AlertType.EMAIL); - alert.setAlertGroupId(4); - - return alert; - } - - private String list2String() { - - LinkedHashMap map1 = new LinkedHashMap<>(); - map1.put("mysql service name", "mysql200"); - map1.put("mysql address", "192.168.xx.xx"); - map1.put("port", "3306"); - map1.put("no index of number", "80"); - map1.put("database client connections", "190"); - - LinkedHashMap map2 = new LinkedHashMap<>(); - map2.put("mysql service name", "mysql210"); - map2.put("mysql address", "192.168.xx.xx"); - map2.put("port", "3306"); - map2.put("no index of number", "10"); - map2.put("database client connections", "90"); - - List> maps = new ArrayList<>(); - maps.add(0, map1); - maps.add(1, map2); - String mapjson = JSONUtils.toJsonString(maps); - return mapjson; - } - - private Alert createAlertForTable() { - Alert alert = new Alert(); - alert.setTitle("Mysql Exception"); - alert.setShowType(ShowType.TABLE); - String content = list2String(); - alert.setContent(content); - alert.setAlertType(AlertType.EMAIL); - alert.setAlertGroupId(1); - return alert; - } - - - // @Test - // public void testSendSingleTeamWeChat() { - // try { - // String token = EnterpriseWeChatUtils.getToken(); - // String msg = EnterpriseWeChatUtils.makeTeamSendMsg(partyId, agentId, "hello world"); - // String resp = EnterpriseWeChatUtils.sendEnterpriseWeChat("utf-8", msg, token); - // - // String errmsg = JSONUtils.parseObject(resp).getString("errmsg"); - // Assert.assertEquals("ok",errmsg); - // } catch (IOException e) { - // e.printStackTrace(); - // } - // } - // - // @Test - // public void testSendMultiTeamWeChat() { - // - // try { - // String token = EnterpriseWeChatUtils.getToken(); - // String msg = EnterpriseWeChatUtils.makeTeamSendMsg(listPartyId, agentId, "hello world"); - // String resp = EnterpriseWeChatUtils.sendEnterpriseWeChat("utf-8", msg, token); - // - // String errmsg = JSONUtils.parseObject(resp).getString("errmsg"); - // Assert.assertEquals("ok",errmsg); - // } catch (IOException e) { - // e.printStackTrace(); - // } - // } - // - // @Test - // public void testSendSingleUserWeChat() { - // try { - // String token = EnterpriseWeChatUtils.getToken(); - // String msg = EnterpriseWeChatUtils.makeUserSendMsg(listUserId.stream().findFirst().get(), agentId, "your meeting room has been booked and will be synced to the 'mailbox' later \n" + - // ">**matter details** \n" + - // ">matter:meeting
" + - // ">organizer:@miglioguan \n" + - // ">participant:@miglioguan、@kunliu、@jamdeezhou、@kanexiong、@kisonwang \n" + - // "> \n" + - // ">meeting room:Guangzhou TIT 1st Floor 301 \n" + - // ">date:May 18, 2018 \n" + - // ">time:9:00-11:00 am \n" + - // "> \n" + - // ">please attend the meeting on time\n" + - // "> \n" + - // ">to modify the meeting information, please click: [Modify Meeting Information](https://work.weixin.qq.com)\""); - // - // String resp = EnterpriseWeChatUtils.sendEnterpriseWeChat("utf-8", msg, token); - // - // String errmsg = JSONUtils.parseObject(resp).getString("errmsg"); - // Assert.assertEquals("ok",errmsg); - // } catch (IOException e) { - // e.printStackTrace(); - // } - // } - // - // @Test - // public void testSendMultiUserWeChat() { - // try { - // String token = EnterpriseWeChatUtils.getToken(); - // - // String msg = EnterpriseWeChatUtils.makeUserSendMsg(listUserId, agentId, "hello world"); - // String resp = EnterpriseWeChatUtils.sendEnterpriseWeChat("utf-8", msg, token); - // - // String errmsg = JSONUtils.parseObject(resp).getString("errmsg"); - // Assert.assertEquals("ok",errmsg); - // } catch (IOException e) { - // e.printStackTrace(); - // } - // } - -} diff --git a/dolphinscheduler-alert/src/test/java/org/apache/dolphinscheduler/alert/utils/FuncUtilsTest.java b/dolphinscheduler-alert/src/test/java/org/apache/dolphinscheduler/alert/utils/FuncUtilsTest.java index a4aeea9c0c..818fac98b6 100644 --- a/dolphinscheduler-alert/src/test/java/org/apache/dolphinscheduler/alert/utils/FuncUtilsTest.java +++ b/dolphinscheduler-alert/src/test/java/org/apache/dolphinscheduler/alert/utils/FuncUtilsTest.java @@ -17,14 +17,14 @@ package org.apache.dolphinscheduler.alert.utils; -import org.junit.Test; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; import java.util.Arrays; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNull; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class FuncUtilsTest { diff --git a/dolphinscheduler-alert/src/test/java/org/apache/dolphinscheduler/alert/utils/MailUtilsTest.java b/dolphinscheduler-alert/src/test/java/org/apache/dolphinscheduler/alert/utils/MailUtilsTest.java deleted file mode 100644 index 26a69c43ba..0000000000 --- a/dolphinscheduler-alert/src/test/java/org/apache/dolphinscheduler/alert/utils/MailUtilsTest.java +++ /dev/null @@ -1,190 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.dolphinscheduler.alert.utils; - - -import org.apache.dolphinscheduler.common.enums.AlertType; -import org.apache.dolphinscheduler.common.enums.ShowType; -import org.apache.dolphinscheduler.dao.AlertDao; -import org.apache.dolphinscheduler.dao.DaoFactory; -import org.apache.dolphinscheduler.dao.entity.Alert; -import org.apache.dolphinscheduler.dao.entity.User; -import org.junit.Assert; -import org.junit.Test; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.*; -import org.apache.dolphinscheduler.common.utils.*; - - -/** - */ -public class MailUtilsTest { - private static final Logger logger = LoggerFactory.getLogger(MailUtilsTest.class); - @Test - public void testSendMails() { - String[] receivers = new String[]{"347801120@qq.com"}; - String[] receiversCc = new String[]{"347801120@qq.com"}; - - String content ="[\"id:69\"," + - "\"name:UserBehavior-0--1193959466\"," + - "\"Job name: Start workflow\"," + - "\"State: SUCCESS\"," + - "\"Recovery:NO\"," + - "\"Run time: 1\"," + - "\"Start time: 2018-08-06 10:31:34.0\"," + - "\"End time: 2018-08-06 10:31:49.0\"," + - "\"Host: 192.168.xx.xx\"," + - "\"Notify group :4\"]"; - - Alert alert = new Alert(); - alert.setTitle("Mysql Exception"); - alert.setShowType(ShowType.TEXT); - alert.setContent(content); - alert.setAlertType(AlertType.EMAIL); - alert.setAlertGroupId(4); - - MailUtils.sendMails(Arrays.asList(receivers),Arrays.asList(receiversCc),alert.getTitle(),alert.getContent(), ShowType.TEXT.getDescp()); - } - - - @Test - public void testQuery(){ - AlertDao alertDao = DaoFactory.getDaoInstance(AlertDao.class); - List alerts = alertDao.listWaitExecutionAlert(); - - String[] mails = new String[]{"xx@xx.com"}; - - for(Alert alert : alerts){ - MailUtils.sendMails(Arrays.asList(mails),"gaojing", alert.getContent(), ShowType.TABLE.getDescp()); - } - - } - - public String list2String(){ - - LinkedHashMap map1 = new LinkedHashMap<>(); - map1.put("mysql service name","mysql200"); - map1.put("mysql address","192.168.xx.xx"); - map1.put("port","3306"); - map1.put("no index of number","80"); - map1.put("database client connections","190"); - - LinkedHashMap map2 = new LinkedHashMap<>(); - map2.put("mysql service name","mysql210"); - map2.put("mysql address","192.168.xx.xx"); - map2.put("port","3306"); - map2.put("no index of number","10"); - map2.put("database client connections","90"); - - List> maps = new ArrayList<>(); - maps.add(0,map1); - maps.add(1,map2); - String mapjson = JSONUtils.toJsonString(maps); - logger.info(mapjson); - - return mapjson; - - } - - @Test - public void testSendTableMail(){ - String[] mails = new String[]{"347801120@qq.com"}; - Alert alert = new Alert(); - alert.setTitle("Mysql Exception"); - alert.setShowType(ShowType.TABLE); - String content= list2String(); - alert.setContent(content); - alert.setAlertType(AlertType.EMAIL); - alert.setAlertGroupId(1); - MailUtils.sendMails(Arrays.asList(mails),"gaojing", alert.getContent(), ShowType.TABLE.getDescp()); - } - - /** - * Used to test add alarm information, mail sent - * Text - */ - @Test - public void addAlertText(){ - AlertDao alertDao = DaoFactory.getDaoInstance(AlertDao.class); - Alert alert = new Alert(); - alert.setTitle("Mysql Exception"); - alert.setShowType(ShowType.TEXT); - alert.setContent("[\"alarm time:2018-02-05\", \"service name:MYSQL_ALTER\", \"alarm name:MYSQL_ALTER_DUMP\", " + - "\"get the alarm exception.!,interface error,exception information:timed out\", \"request address:http://blog.csdn.net/dreamInTheWorld/article/details/78539286\"]"); - alert.setAlertType(AlertType.EMAIL); - alert.setAlertGroupId(1); - alertDao.addAlert(alert); - } - - - /** - * Used to test add alarm information, mail sent - * Table - */ - @Test - public void testAddAlertTable(){ - logger.info("testAddAlertTable"); - AlertDao alertDao = DaoFactory.getDaoInstance(AlertDao.class); - Assert.assertNotNull(alertDao); - Alert alert = new Alert(); - alert.setTitle("Mysql Exception"); - alert.setShowType(ShowType.TABLE); - - String content = list2String(); - alert.setContent(content); - alert.setAlertType(AlertType.EMAIL); - alert.setAlertGroupId(1); - alertDao.addAlert(alert); - logger.info("" +alert); - } - - @Test - public void testAlertDao(){ - AlertDao alertDao = DaoFactory.getDaoInstance(AlertDao.class); - List users = alertDao.listUserByAlertgroupId(3); - logger.info(users.toString()); - } - - @Test - public void testAttachmentFile()throws Exception{ - String[] mails = new String[]{"xx@xx.com"}; - Alert alert = new Alert(); - alert.setTitle("Mysql Exception"); - alert.setShowType(ShowType.ATTACHMENT); - String content = list2String(); - alert.setContent(content); - alert.setAlertType(AlertType.EMAIL); - alert.setAlertGroupId(1); - MailUtils.sendMails(Arrays.asList(mails),"gaojing",alert.getContent(),ShowType.ATTACHMENT.getDescp()); - } - - @Test - public void testTableAttachmentFile()throws Exception{ - String[] mails = new String[]{"xx@xx.com"}; - Alert alert = new Alert(); - alert.setTitle("Mysql Exception"); - alert.setShowType(ShowType.TABLEATTACHMENT); - String content = list2String(); - alert.setContent(content); - alert.setAlertType(AlertType.EMAIL); - alert.setAlertGroupId(1); - MailUtils.sendMails(Arrays.asList(mails),"gaojing",alert.getContent(),ShowType.TABLEATTACHMENT.getDescp()); - } - -} diff --git a/dolphinscheduler-alert/src/test/java/org/apache/dolphinscheduler/alert/utils/PropertyUtilsTest.java b/dolphinscheduler-alert/src/test/java/org/apache/dolphinscheduler/alert/utils/PropertyUtilsTest.java index 2a300c9d57..68f90b588d 100644 --- a/dolphinscheduler-alert/src/test/java/org/apache/dolphinscheduler/alert/utils/PropertyUtilsTest.java +++ b/dolphinscheduler-alert/src/test/java/org/apache/dolphinscheduler/alert/utils/PropertyUtilsTest.java @@ -17,13 +17,18 @@ package org.apache.dolphinscheduler.alert.utils; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; + import org.apache.dolphinscheduler.common.enums.ZKNodeType; + import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import static org.junit.Assert.*; - /** * Test PropertyUtils * and the resource path is src/test/resources/alert.properties. @@ -41,11 +46,11 @@ public class PropertyUtilsTest { //Expected "EMAIL" String result = PropertyUtils.getString("alert.type"); logger.info(result); - assertEquals(result, "EMAIL"); + assertEquals("EMAIL", result); //Expected "xxx.xxx.test" result = PropertyUtils.getString("mail.server.host"); - assertEquals(result, "xxx.xxx.test"); + assertEquals("xxx.xxx.test", result); //If key is undefine in alert.properties, then return null result = PropertyUtils.getString("abc"); @@ -88,23 +93,23 @@ public class PropertyUtilsTest { //Expected 25 long result = PropertyUtils.getLong("mail.server.port"); - assertSame(result, 25L); + assertSame(25L, result); //If key is null, then return -1 result = PropertyUtils.getLong(null); - assertSame(result, -1L); + assertSame(-1L, result); //If key is undefine in alert.properties, then return -1 result = PropertyUtils.getLong("abc"); - assertSame(result, -1L); + assertSame(-1L, result); //If key is undefine in alert.properties, and there is a defaultval, then return defaultval result = PropertyUtils.getLong("abc", 200); - assertEquals(result, 200L); + assertEquals(200L, result); //If the value can not parse to long ,it will log the error and return -1L result = PropertyUtils.getLong("test.server.testnumber"); - assertSame(result, -1L); + assertSame(-1L, result); } /** @@ -115,23 +120,23 @@ public class PropertyUtilsTest { //Expected 3.0 double result = PropertyUtils.getDouble("test.server.factor"); - assertEquals(result, 3.0, 0); + assertEquals(3.0, result, 0); //If key is null, then return -1.0 result = PropertyUtils.getDouble(null); - assertEquals(result, -1.0, 0); + assertEquals(-1.0, result, 0); //If key is undefine in alert.properties, then return -1 result = PropertyUtils.getDouble("abc"); - assertEquals(result, -1.0, 0); + assertEquals(-1.0, result, 0); //If key is undefine in alert.properties, and there is a defaultval, then return defaultval result = PropertyUtils.getDouble("abc", 5.0); - assertEquals(result, 5.0, 0); + assertEquals(5.0, result, 0); //If the value can not parse to double ,it will log the error and return -1.0 result = PropertyUtils.getDouble("test.server.testnumber"); - assertEquals(result, -1.0, 0); + assertEquals(-1.0, result, 0); } /** @@ -145,9 +150,9 @@ public class PropertyUtilsTest { assertEquals(result.length, 3); //Equal array values - assertEquals(result[0], "xxx.xxx.test1"); - assertEquals(result[1], "xxx.xxx.test2"); - assertEquals(result[2], "xxx.xxx.test3"); + assertEquals("xxx.xxx.test1", result[0]); + assertEquals("xxx.xxx.test2", result[1]); + assertEquals("xxx.xxx.test3", result[2]); //If key is null, then return -1 result = PropertyUtils.getArray(null, ","); @@ -170,23 +175,23 @@ public class PropertyUtilsTest { //Expected 25 int result = PropertyUtils.getInt("mail.server.port"); - assertSame(result, 25); + assertSame(25, result); //If key is null, then return -1 result = PropertyUtils.getInt(null); - assertSame(result, -1); + assertSame(-1, result); //If key is undefine in alert.properties, then return -1 result = PropertyUtils.getInt("abc"); - assertSame(result, -1); + assertSame(-1, result); //If key is undefine in alert.properties, and there is a defaultval, then return defaultval result = PropertyUtils.getInt("abc", 300); - assertEquals(result, 300); + assertEquals(300, result); //If the value can not parse to int ,it will log the error and return -1 result = PropertyUtils.getInt("test.server.testnumber"); - assertSame(result, -1); + assertSame(-1, result); } /** @@ -196,20 +201,20 @@ public class PropertyUtilsTest { public void testGetEnum() { //Expected MASTER - ZKNodeType zkNodeType = PropertyUtils.getEnum("test.server.enum1", ZKNodeType.class,ZKNodeType.WORKER); - assertEquals(zkNodeType, ZKNodeType.MASTER); + ZKNodeType zkNodeType = PropertyUtils.getEnum("test.server.enum1", ZKNodeType.class, ZKNodeType.WORKER); + assertEquals(ZKNodeType.MASTER, zkNodeType); //Expected DEAD_SERVER - zkNodeType = PropertyUtils.getEnum("test.server.enum2", ZKNodeType.class,ZKNodeType.WORKER); - assertEquals(zkNodeType, ZKNodeType.DEAD_SERVER); + zkNodeType = PropertyUtils.getEnum("test.server.enum2", ZKNodeType.class, ZKNodeType.WORKER); + assertEquals(ZKNodeType.DEAD_SERVER, zkNodeType); //If key is null, then return defaultval - zkNodeType = PropertyUtils.getEnum(null, ZKNodeType.class,ZKNodeType.WORKER); - assertEquals(zkNodeType, ZKNodeType.WORKER); + zkNodeType = PropertyUtils.getEnum(null, ZKNodeType.class, ZKNodeType.WORKER); + assertEquals(ZKNodeType.WORKER, zkNodeType); //If the value doesn't define in enum ,it will log the error and return -1 - zkNodeType = PropertyUtils.getEnum("test.server.enum3", ZKNodeType.class,ZKNodeType.WORKER); - assertEquals(zkNodeType, ZKNodeType.WORKER); + zkNodeType = PropertyUtils.getEnum("test.server.enum3", ZKNodeType.class, ZKNodeType.WORKER); + assertEquals(ZKNodeType.WORKER, zkNodeType); } -} \ No newline at end of file +} diff --git a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/controller/AlertGroupController.java b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/controller/AlertGroupController.java index 37c38d6b6c..10590529bf 100644 --- a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/controller/AlertGroupController.java +++ b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/controller/AlertGroupController.java @@ -14,31 +14,44 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.dolphinscheduler.api.controller; +import static org.apache.dolphinscheduler.api.enums.Status.CREATE_ALERT_GROUP_ERROR; +import static org.apache.dolphinscheduler.api.enums.Status.DELETE_ALERT_GROUP_ERROR; +import static org.apache.dolphinscheduler.api.enums.Status.LIST_PAGING_ALERT_GROUP_ERROR; +import static org.apache.dolphinscheduler.api.enums.Status.QUERY_ALL_ALERTGROUP_ERROR; +import static org.apache.dolphinscheduler.api.enums.Status.UPDATE_ALERT_GROUP_ERROR; + +import org.apache.dolphinscheduler.api.enums.Status; import org.apache.dolphinscheduler.api.exceptions.ApiException; import org.apache.dolphinscheduler.api.service.AlertGroupService; import org.apache.dolphinscheduler.api.utils.Result; import org.apache.dolphinscheduler.common.Constants; -import org.apache.dolphinscheduler.common.enums.AlertType; import org.apache.dolphinscheduler.common.utils.ParameterUtils; +import org.apache.dolphinscheduler.common.utils.StringUtils; import org.apache.dolphinscheduler.dao.entity.User; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiImplicitParam; -import io.swagger.annotations.ApiImplicitParams; -import io.swagger.annotations.ApiOperation; -import org.apache.dolphinscheduler.api.enums.Status; + +import java.util.HashMap; +import java.util.Map; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; -import org.springframework.web.bind.annotation.*; -import springfox.documentation.annotations.ApiIgnore; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestAttribute; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.bind.annotation.RestController; -import java.util.HashMap; -import java.util.Map; - -import static org.apache.dolphinscheduler.api.enums.Status.*; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiImplicitParams; +import io.swagger.annotations.ApiOperation; +import springfox.documentation.annotations.ApiIgnore; /** * alert group controller @@ -57,28 +70,31 @@ public class AlertGroupController extends BaseController { /** * create alert group * - * @param loginUser login user - * @param groupName group name - * @param groupType group type + * @param loginUser login user + * @param groupName group name * @param description description * @return create result code */ @ApiOperation(value = "createAlertgroup", notes = "CREATE_ALERT_GROUP_NOTES") @ApiImplicitParams({ @ApiImplicitParam(name = "groupName", value = "GROUP_NAME", required = true, dataType = "String"), - @ApiImplicitParam(name = "groupType", value = "GROUP_TYPE", required = true, dataType = "AlertType"), - @ApiImplicitParam(name = "description", value = "DESC", dataType = "String") + @ApiImplicitParam(name = "description", value = "DESC", dataType = "String"), + @ApiImplicitParam(name = "alertInstanceIds", value = "alertInstanceIds", dataType = "String") }) @PostMapping(value = "/create") @ResponseStatus(HttpStatus.CREATED) @ApiException(CREATE_ALERT_GROUP_ERROR) public Result createAlertgroup(@ApiIgnore @RequestAttribute(value = Constants.SESSION_USER) User loginUser, @RequestParam(value = "groupName") String groupName, - @RequestParam(value = "groupType") AlertType groupType, - @RequestParam(value = "description", required = false) String description) { - logger.info("loginUser user {}, create alertgroup, groupName: {}, groupType: {}, desc: {}", - loginUser.getUserName(), groupName, groupType, description); - Map result = alertGroupService.createAlertgroup(loginUser, groupName, groupType, description); + @RequestParam(value = "description", required = false) String description, + @RequestParam(value = "alertInstanceIds") String alertInstanceIds) { + String strUserName = StringUtils.replaceNRTtoUnderline(loginUser.getUserName()); + String strGroupName = StringUtils.replaceNRTtoUnderline(groupName); + String strDescription = StringUtils.replaceNRTtoUnderline(description); + String strAlertInstanceIds = StringUtils.replaceNRTtoUnderline(alertInstanceIds); + logger.info("loginUser user {}, create alert group, groupName: {}, desc: {},alertInstanceIds:{}", + strUserName, strGroupName, strDescription, strAlertInstanceIds); + Map result = alertGroupService.createAlertgroup(loginUser, groupName, description, alertInstanceIds); return returnDataList(result); } @@ -103,9 +119,9 @@ public class AlertGroupController extends BaseController { * paging query alarm group list * * @param loginUser login user - * @param pageNo page number + * @param pageNo page number * @param searchVal search value - * @param pageSize page size + * @param pageSize page size * @return alert group list page */ @ApiOperation(value = "queryAlertGroupListPaging", notes = "QUERY_ALERT_GROUP_LIST_PAGING_NOTES") @@ -136,10 +152,9 @@ public class AlertGroupController extends BaseController { /** * updateProcessInstance alert group * - * @param loginUser login user - * @param id alert group id - * @param groupName group name - * @param groupType group type + * @param loginUser login user + * @param id alert group id + * @param groupName group name * @param description description * @return update result code */ @@ -147,8 +162,8 @@ public class AlertGroupController extends BaseController { @ApiImplicitParams({ @ApiImplicitParam(name = "id", value = "ALERT_GROUP_ID", required = true, dataType = "Int", example = "100"), @ApiImplicitParam(name = "groupName", value = "GROUP_NAME", required = true, dataType = "String"), - @ApiImplicitParam(name = "groupType", value = "GROUP_TYPE", required = true, dataType = "AlertType"), - @ApiImplicitParam(name = "description", value = "DESC", dataType = "String") + @ApiImplicitParam(name = "description", value = "DESC", dataType = "String"), + @ApiImplicitParam(name = "alertInstanceIds", value = "alertInstanceIds", dataType = "String") }) @PostMapping(value = "/update") @ResponseStatus(HttpStatus.OK) @@ -156,11 +171,13 @@ public class AlertGroupController extends BaseController { public Result updateAlertgroup(@ApiIgnore @RequestAttribute(value = Constants.SESSION_USER) User loginUser, @RequestParam(value = "id") int id, @RequestParam(value = "groupName") String groupName, - @RequestParam(value = "groupType") AlertType groupType, - @RequestParam(value = "description", required = false) String description) { - logger.info("login user {}, updateProcessInstance alertgroup, groupName: {}, groupType: {}, desc: {}", - loginUser.getUserName(), groupName, groupType, description); - Map result = alertGroupService.updateAlertgroup(loginUser, id, groupName, groupType, description); + @RequestParam(value = "description", required = false) String description, + @RequestParam(value = "alertInstanceIds") String alertInstanceIds) { + logger.info("login user {}, updateProcessInstance alert group, groupName: {}, desc: {}", + StringUtils.replaceNRTtoUnderline(loginUser.getUserName()), + StringUtils.replaceNRTtoUnderline(groupName), + StringUtils.replaceNRTtoUnderline(description)); + Map result = alertGroupService.updateAlertgroup(loginUser, id, groupName, description, alertInstanceIds); return returnDataList(result); } @@ -168,7 +185,7 @@ public class AlertGroupController extends BaseController { * delete alert group by id * * @param loginUser login user - * @param id alert group id + * @param id alert group id * @return delete result code */ @ApiOperation(value = "delAlertgroupById", notes = "DELETE_ALERT_GROUP_BY_ID_NOTES") @@ -215,28 +232,4 @@ public class AlertGroupController extends BaseController { } return result; } - - /** - * grant user - * - * @param loginUser login user - * @param userIds user ids in the group - * @param alertgroupId alert group id - * @return grant result code - */ - @ApiOperation(value = "grantUser", notes = "GRANT_ALERT_GROUP_NOTES") - @ApiImplicitParams({ - @ApiImplicitParam(name = "id", value = "ALERT_GROUP_ID", required = true, dataType = "Int", example = "100"), - @ApiImplicitParam(name = "userIds", value = "USER_IDS", required = true, dataType = "String") - }) - @PostMapping(value = "/grant-user") - @ResponseStatus(HttpStatus.OK) - @ApiException(ALERT_GROUP_GRANT_USER_ERROR) - public Result grantUser(@ApiIgnore @RequestAttribute(value = Constants.SESSION_USER) User loginUser, - @RequestParam(value = "alertgroupId") int alertgroupId, - @RequestParam(value = "userIds") String userIds) { - logger.info("login user {}, grant user, alertGroupId: {},userIds : {}", loginUser.getUserName(), alertgroupId, userIds); - Map result = alertGroupService.grantUser(loginUser, alertgroupId, userIds); - return returnDataList(result); - } } diff --git a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/controller/AlertPluginInstanceController.java b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/controller/AlertPluginInstanceController.java new file mode 100644 index 0000000000..d34f42060f --- /dev/null +++ b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/controller/AlertPluginInstanceController.java @@ -0,0 +1,240 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.dolphinscheduler.api.controller; + +import static org.apache.dolphinscheduler.api.enums.Status.CREATE_ALERT_PLUGIN_INSTANCE_ERROR; +import static org.apache.dolphinscheduler.api.enums.Status.DELETE_ALERT_PLUGIN_INSTANCE_ERROR; +import static org.apache.dolphinscheduler.api.enums.Status.GET_ALERT_PLUGIN_INSTANCE_ERROR; +import static org.apache.dolphinscheduler.api.enums.Status.LIST_PAGING_ALERT_PLUGIN_INSTANCE_ERROR; +import static org.apache.dolphinscheduler.api.enums.Status.QUERY_ALL_ALERT_PLUGIN_INSTANCE_ERROR; +import static org.apache.dolphinscheduler.api.enums.Status.UPDATE_ALERT_PLUGIN_INSTANCE_ERROR; + +import org.apache.dolphinscheduler.api.enums.Status; +import org.apache.dolphinscheduler.api.exceptions.ApiException; +import org.apache.dolphinscheduler.api.service.AlertPluginInstanceService; +import org.apache.dolphinscheduler.api.utils.Result; +import org.apache.dolphinscheduler.common.Constants; +import org.apache.dolphinscheduler.common.utils.StringUtils; +import org.apache.dolphinscheduler.dao.entity.User; + +import java.util.Map; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestAttribute; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.bind.annotation.RestController; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiImplicitParams; +import io.swagger.annotations.ApiOperation; +import springfox.documentation.annotations.ApiIgnore; + +/** + * alert plugin instance controller + */ +@Api(tags = "ALERT_PLUGIN_INSTANCE_TAG", position = 1) +@RestController +@RequestMapping("alert-plugin-instance") +public class AlertPluginInstanceController extends BaseController { + + private static final Logger logger = LoggerFactory.getLogger(AlertPluginInstanceController.class); + + @Autowired + private AlertPluginInstanceService alertPluginInstanceService; + + + /** + * create alert plugin instance + * + * @param loginUser login user + * @param pluginDefineId alert plugin define id + * @param instanceName instance name + * @param pluginInstanceParams instance params + * @return result + */ + @ApiOperation(value = "createAlertPluginInstance", notes = "CREATE_ALERT_PLUGIN_INSTANCE_NOTES") + @ApiImplicitParams({ + @ApiImplicitParam(name = "pluginDefineId", value = "ALERT_PLUGIN_DEFINE_ID", required = true, dataType = "Int", example = "100"), + @ApiImplicitParam(name = "instanceName", value = "ALERT_PLUGIN_INSTANCE_NAME", required = true, dataType = "String", example = "DING TALK"), + @ApiImplicitParam(name = "pluginInstanceParams", value = "ALERT_PLUGIN_INSTANCE_PARAMS", required = true, dataType = "String", example = "ALERT_PLUGIN_INSTANCE_PARAMS") + }) + @PostMapping(value = "/create") + @ResponseStatus(HttpStatus.CREATED) + @ApiException(CREATE_ALERT_PLUGIN_INSTANCE_ERROR) + public Result createAlertPluginInstance(@ApiIgnore @RequestAttribute(value = Constants.SESSION_USER) User loginUser, + @RequestParam(value = "pluginDefineId") int pluginDefineId, + @RequestParam(value = "instanceName") String instanceName, + @RequestParam(value = "pluginInstanceParams") String pluginInstanceParams) { + logger.info("login user {},create alert plugin instance, instanceName:{} ", + StringUtils.replaceNRTtoUnderline(loginUser.getUserName()), + StringUtils.replaceNRTtoUnderline(instanceName)); + Map result = alertPluginInstanceService.create(loginUser, pluginDefineId, instanceName, pluginInstanceParams); + return returnDataList(result); + } + + /** + * updateAlertPluginInstance + * + * @param loginUser login user + * @param alertPluginInstanceId alert plugin instance id + * @param instanceName instance name + * @param pluginInstanceParams instance params + * @return result + */ + @ApiOperation(value = "update", notes = "UPDATE_ALERT_PLUGIN_INSTANCE_NOTES") + @ApiImplicitParams({ + @ApiImplicitParam(name = "alertPluginInstanceId", value = "ALERT_PLUGIN_INSTANCE_ID", required = true, dataType = "Int", example = "100"), + @ApiImplicitParam(name = "instanceName", value = "ALERT_PLUGIN_INSTANCE_NAME", required = true, dataType = "String", example = "DING TALK"), + @ApiImplicitParam(name = "pluginInstanceParams", value = "ALERT_PLUGIN_INSTANCE_PARAMS", required = true, dataType = "String", example = "ALERT_PLUGIN_INSTANCE_PARAMS") + }) + @GetMapping(value = "/update") + @ResponseStatus(HttpStatus.OK) + @ApiException(UPDATE_ALERT_PLUGIN_INSTANCE_ERROR) + public Result updateAlertPluginInstance(@ApiIgnore @RequestAttribute(value = Constants.SESSION_USER) User loginUser, + @RequestParam(value = "alertPluginInstanceId") int alertPluginInstanceId, + @RequestParam(value = "instanceName") String instanceName, + @RequestParam(value = "pluginInstanceParams") String pluginInstanceParams) { + logger.info("login user {},update alert plugin instance id {}", StringUtils.replaceNRTtoUnderline(loginUser.getUserName()), alertPluginInstanceId); + Map result = alertPluginInstanceService.update(loginUser, alertPluginInstanceId, instanceName, pluginInstanceParams); + return returnDataList(result); + } + + /** + * deleteAlertPluginInstance + * + * @param loginUser login user + * @param id id + * @return result + */ + @ApiOperation(value = "delete", notes = "DELETE_ALERT_PLUGIN_INSTANCE_NOTES") + @ApiImplicitParams({ + @ApiImplicitParam(name = "id", value = "ALERT_PLUGIN_ID", required = true, dataType = "Int", example = "100") + }) + @GetMapping(value = "/delete") + @ResponseStatus(HttpStatus.OK) + @ApiException(DELETE_ALERT_PLUGIN_INSTANCE_ERROR) + public Result deleteAlertPluginInstance(@ApiIgnore @RequestAttribute(value = Constants.SESSION_USER) User loginUser, + @RequestParam(value = "id") int id) { + logger.info("login user {},delete alert plugin instance id {}", StringUtils.replaceNRTtoUnderline(loginUser.getUserName()), id); + + Map result = alertPluginInstanceService.delete(loginUser, id); + return returnDataList(result); + } + + /** + * getAlertPluginInstance + * + * @param loginUser login user + * @param id alert plugin instance id + * @return result + */ + @ApiOperation(value = "get", notes = "GET_ALERT_PLUGIN_INSTANCE_NOTES") + @PostMapping(value = "/get") + @ResponseStatus(HttpStatus.OK) + @ApiException(GET_ALERT_PLUGIN_INSTANCE_ERROR) + public Result getAlertPluginInstance(@ApiIgnore @RequestAttribute(value = Constants.SESSION_USER) User loginUser, + @RequestParam(value = "id") int id) { + logger.info("login user {},get alert plugin instance, id {}", StringUtils.replaceNRTtoUnderline(loginUser.getUserName()), id); + Map result = alertPluginInstanceService.get(loginUser, id); + return returnDataList(result); + } + + /** + * getAlertPluginInstance + * + * @param loginUser login user + * @return result + */ + @ApiOperation(value = "/queryAll", notes = "QUERY_ALL_ALERT_PLUGIN_INSTANCE_NOTES") + @PostMapping(value = "/queryAll") + @ResponseStatus(HttpStatus.OK) + @ApiException(QUERY_ALL_ALERT_PLUGIN_INSTANCE_ERROR) + public Result getAlertPluginInstance(@ApiIgnore @RequestAttribute(value = Constants.SESSION_USER) User loginUser) { + logger.info("login user {}, query all alert plugin instance", StringUtils.replaceNRTtoUnderline(loginUser.getUserName())); + Map result = alertPluginInstanceService.queryAll(); + return returnDataList(result); + } + + /** + * check alert group exist + * + * @param loginUser login user + * @param alertInstanceName alert instance name + * @return check result code + */ + @ApiOperation(value = "verifyAlertInstanceName", notes = "VERIFY_ALERT_INSTANCE_NAME_NOTES") + @ApiImplicitParams({ + @ApiImplicitParam(name = "groupName", value = "GROUP_NAME", required = true, dataType = "String"), + }) + @GetMapping(value = "/verify-alert-instance-name") + @ResponseStatus(HttpStatus.OK) + public Result verifyGroupName(@ApiIgnore @RequestAttribute(value = Constants.SESSION_USER) User loginUser, + @RequestParam(value = "alertInstanceName") String alertInstanceName) { + logger.info("login user {},verify alert instance name: {}", StringUtils.replaceNRTtoUnderline(loginUser.getUserName()), StringUtils.replaceNRTtoUnderline(alertInstanceName)); + + boolean exist = alertPluginInstanceService.checkExistPluginInstanceName(alertInstanceName); + Result result = new Result(); + if (exist) { + logger.error("alert plugin instance {} has exist, can't create again.", alertInstanceName); + result.setCode(Status.PLUGIN_INSTANCE_ALREADY_EXIT.getCode()); + result.setMsg(Status.PLUGIN_INSTANCE_ALREADY_EXIT.getMsg()); + } else { + result.setCode(Status.SUCCESS.getCode()); + result.setMsg(Status.SUCCESS.getMsg()); + } + return result; + } + + /** + * paging query alert plugin instance group list + * + * @param loginUser login user + * @param pageNo page number + * @param pageSize page size + * @return alert plugin instance list page + */ + @ApiOperation(value = "queryAlertPluginInstanceListPaging", notes = "QUERY_ALERT_PLUGIN_INSTANCE_LIST_PAGING_NOTES") + @ApiImplicitParams({ + @ApiImplicitParam(name = "pageNo", value = "PAGE_NO", dataType = "Int", example = "1"), + @ApiImplicitParam(name = "pageSize", value = "PAGE_SIZE", dataType = "Int", example = "20") + }) + @GetMapping(value = "/list-paging") + @ResponseStatus(HttpStatus.OK) + @ApiException(LIST_PAGING_ALERT_PLUGIN_INSTANCE_ERROR) + public Result listPaging(@ApiIgnore @RequestAttribute(value = Constants.SESSION_USER) User loginUser, + @RequestParam("pageNo") Integer pageNo, + @RequestParam("pageSize") Integer pageSize) { + logger.info("login user {}, list paging, pageNo: {}, pageSize: {}",StringUtils.replaceNRTtoUnderline(loginUser.getUserName()), pageNo, pageSize); + Map result = checkPageParams(pageNo, pageSize); + if (result.get(Constants.STATUS) != Status.SUCCESS) { + return returnDataListPaging(result); + } + + result = alertPluginInstanceService.queryPluginPage(pageNo, pageSize); + return returnDataListPaging(result); + } + +} diff --git a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/controller/DataSourceController.java b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/controller/DataSourceController.java index 4bdaa365ee..a67ade2ba7 100644 --- a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/controller/DataSourceController.java +++ b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/controller/DataSourceController.java @@ -14,12 +14,20 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.dolphinscheduler.api.controller; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiImplicitParam; -import io.swagger.annotations.ApiImplicitParams; -import io.swagger.annotations.ApiOperation; +import static org.apache.dolphinscheduler.api.enums.Status.AUTHORIZED_DATA_SOURCE; +import static org.apache.dolphinscheduler.api.enums.Status.CONNECTION_TEST_FAILURE; +import static org.apache.dolphinscheduler.api.enums.Status.CONNECT_DATASOURCE_FAILURE; +import static org.apache.dolphinscheduler.api.enums.Status.CREATE_DATASOURCE_ERROR; +import static org.apache.dolphinscheduler.api.enums.Status.DELETE_DATA_SOURCE_FAILURE; +import static org.apache.dolphinscheduler.api.enums.Status.KERBEROS_STARTUP_STATE; +import static org.apache.dolphinscheduler.api.enums.Status.QUERY_DATASOURCE_ERROR; +import static org.apache.dolphinscheduler.api.enums.Status.UNAUTHORIZED_DATASOURCE; +import static org.apache.dolphinscheduler.api.enums.Status.UPDATE_DATASOURCE_ERROR; +import static org.apache.dolphinscheduler.api.enums.Status.VERIFY_DATASOURCE_NAME_FAILURE; + import org.apache.dolphinscheduler.api.enums.Status; import org.apache.dolphinscheduler.api.exceptions.ApiException; import org.apache.dolphinscheduler.api.service.DataSourceService; @@ -30,16 +38,26 @@ import org.apache.dolphinscheduler.common.enums.DbType; import org.apache.dolphinscheduler.common.utils.CommonUtils; import org.apache.dolphinscheduler.common.utils.ParameterUtils; import org.apache.dolphinscheduler.dao.entity.User; + +import java.util.Map; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; -import org.springframework.web.bind.annotation.*; -import springfox.documentation.annotations.ApiIgnore; - -import java.util.Map; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestAttribute; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.bind.annotation.RestController; -import static org.apache.dolphinscheduler.api.enums.Status.*; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiImplicitParams; +import io.swagger.annotations.ApiOperation; +import springfox.documentation.annotations.ApiIgnore; /** * data source controller @@ -101,8 +119,7 @@ public class DataSourceController extends BaseController { logger.info("login user {} create datasource name: {}, note: {}, type: {}, host: {}, port: {}, database : {}, principal: {}, userName : {}, connectType: {}, other: {}", loginUser.getUserName(), name, note, type, host, port, database, principal, userName, connectType, other); String parameter = dataSourceService.buildParameter(type, host, port, database, principal, userName, password, connectType, other); - Map result = dataSourceService.createDataSource(loginUser, name, note, type, parameter); - return returnDataList(result); + return dataSourceService.createDataSource(loginUser, name, note, type, parameter); } @@ -156,8 +173,7 @@ public class DataSourceController extends BaseController { logger.info("login user {} updateProcessInstance datasource name: {}, note: {}, type: {}, connectType: {}, other: {}", loginUser.getUserName(), name, note, type, connectType, other); String parameter = dataSourceService.buildParameter(type, host, port, database, principal, userName, password, connectType, other); - Map dataSource = dataSourceService.updateDataSource(id, loginUser, name, note, type, parameter); - return returnDataList(dataSource); + return dataSourceService.updateDataSource(id, loginUser, name, note, type, parameter); } /** @@ -281,15 +297,7 @@ public class DataSourceController extends BaseController { logger.info("login user {}, connect datasource: {}, note: {}, type: {}, connectType: {}, other: {}", loginUser.getUserName(), name, note, type, connectType, other); String parameter = dataSourceService.buildParameter(type, host, port, database, principal, userName, password, connectType, other); - Boolean isConnection = dataSourceService.checkConnection(type, parameter); - Result result = new Result(); - - if (isConnection) { - putMsg(result, SUCCESS); - } else { - putMsg(result, CONNECT_DATASOURCE_FAILURE); - } - return result; + return dataSourceService.checkConnection(type, parameter); } /** @@ -309,16 +317,7 @@ public class DataSourceController extends BaseController { public Result connectionTest(@ApiIgnore @RequestAttribute(value = Constants.SESSION_USER) User loginUser, @RequestParam("id") int id) { logger.info("connection test, login user:{}, id:{}", loginUser.getUserName(), id); - - Boolean isConnection = dataSourceService.connectionTest(id); - Result result = new Result(); - - if (isConnection) { - putMsg(result, SUCCESS); - } else { - putMsg(result, CONNECTION_TEST_FAILURE); - } - return result; + return dataSourceService.connectionTest(id); } /** diff --git a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/controller/ExecutorController.java b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/controller/ExecutorController.java index 20f4285ffa..c1e75a73f5 100644 --- a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/controller/ExecutorController.java +++ b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/controller/ExecutorController.java @@ -14,30 +14,49 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.dolphinscheduler.api.controller; +import static org.apache.dolphinscheduler.api.enums.Status.CHECK_PROCESS_DEFINITION_ERROR; +import static org.apache.dolphinscheduler.api.enums.Status.EXECUTE_PROCESS_INSTANCE_ERROR; +import static org.apache.dolphinscheduler.api.enums.Status.START_PROCESS_INSTANCE_ERROR; import org.apache.dolphinscheduler.api.enums.ExecuteType; import org.apache.dolphinscheduler.api.exceptions.ApiException; import org.apache.dolphinscheduler.api.service.ExecutorService; import org.apache.dolphinscheduler.api.utils.Result; import org.apache.dolphinscheduler.common.Constants; +import org.apache.dolphinscheduler.common.enums.CommandType; +import org.apache.dolphinscheduler.common.enums.FailureStrategy; +import org.apache.dolphinscheduler.common.enums.Priority; +import org.apache.dolphinscheduler.common.enums.RunMode; +import org.apache.dolphinscheduler.common.enums.TaskDependType; +import org.apache.dolphinscheduler.common.enums.WarningType; +import org.apache.dolphinscheduler.common.utils.JSONUtils; import org.apache.dolphinscheduler.dao.entity.User; -import io.swagger.annotations.*; -import org.apache.dolphinscheduler.common.enums.*; + +import java.text.ParseException; +import java.util.Map; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; -import org.springframework.web.bind.annotation.*; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestAttribute; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.bind.annotation.RestController; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiImplicitParams; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; import springfox.documentation.annotations.ApiIgnore; -import java.text.ParseException; -import java.util.Map; - -import static org.apache.dolphinscheduler.api.enums.Status.*; - - /** * execute process controller */ @@ -54,22 +73,20 @@ public class ExecutorController extends BaseController { /** * execute process instance * - * @param loginUser login user - * @param projectName project name - * @param processDefinitionId process definition id - * @param scheduleTime schedule time - * @param failureStrategy failure strategy - * @param startNodeList start nodes list - * @param taskDependType task depend type - * @param execType execute type - * @param warningType warning type - * @param warningGroupId warning group id - * @param receivers receivers - * @param receiversCc receivers cc - * @param runMode run mode + * @param loginUser login user + * @param projectName project name + * @param processDefinitionId process definition id + * @param scheduleTime schedule time + * @param failureStrategy failure strategy + * @param startNodeList start nodes list + * @param taskDependType task depend type + * @param execType execute type + * @param warningType warning type + * @param warningGroupId warning group id + * @param runMode run mode * @param processInstancePriority process instance priority - * @param workerGroup worker group - * @param timeout timeout + * @param workerGroup worker group + * @param timeout timeout * @return start process result code */ @ApiOperation(value = "startProcessInstance", notes = "RUN_PROCESS_INSTANCE_NOTES") @@ -82,8 +99,6 @@ public class ExecutorController extends BaseController { @ApiImplicitParam(name = "execType", value = "COMMAND_TYPE", dataType = "CommandType"), @ApiImplicitParam(name = "warningType", value = "WARNING_TYPE", required = true, dataType = "WarningType"), @ApiImplicitParam(name = "warningGroupId", value = "WARNING_GROUP_ID", required = true, dataType = "Int", example = "100"), - @ApiImplicitParam(name = "receivers", value = "RECEIVERS", dataType = "String"), - @ApiImplicitParam(name = "receiversCc", value = "RECEIVERS_CC", dataType = "String"), @ApiImplicitParam(name = "runMode", value = "RUN_MODE", dataType = "RunMode"), @ApiImplicitParam(name = "processInstancePriority", value = "PROCESS_INSTANCE_PRIORITY", required = true, dataType = "Priority"), @ApiImplicitParam(name = "workerGroup", value = "WORKER_GROUP", dataType = "String", example = "default"), @@ -102,26 +117,28 @@ public class ExecutorController extends BaseController { @RequestParam(value = "execType", required = false) CommandType execType, @RequestParam(value = "warningType", required = true) WarningType warningType, @RequestParam(value = "warningGroupId", required = false) int warningGroupId, - @RequestParam(value = "receivers", required = false) String receivers, - @RequestParam(value = "receiversCc", required = false) String receiversCc, @RequestParam(value = "runMode", required = false) RunMode runMode, @RequestParam(value = "processInstancePriority", required = false) Priority processInstancePriority, @RequestParam(value = "workerGroup", required = false, defaultValue = "default") String workerGroup, - @RequestParam(value = "timeout", required = false) Integer timeout) throws ParseException { - logger.info("login user {}, start process instance, project name: {}, process definition id: {}, schedule time: {}, " + @RequestParam(value = "timeout", required = false) Integer timeout, + @RequestParam(value = "startParams", required = false) String startParams) throws ParseException { + logger.info("login user {}, start process instance, project name: {}, process definition id: {}, schedule time: {}, " + "failure policy: {}, node name: {}, node dep: {}, notify type: {}, " - + "notify group id: {},receivers:{},receiversCc:{}, run mode: {},process instance priority:{}, workerGroup: {}, timeout: {}", + + "notify group id: {}, run mode: {},process instance priority:{}, workerGroup: {}, timeout: {}, startParams: {} ", loginUser.getUserName(), projectName, processDefinitionId, scheduleTime, - failureStrategy, startNodeList, taskDependType, warningType, workerGroup, receivers, receiversCc, runMode, processInstancePriority, - workerGroup, timeout); + failureStrategy, startNodeList, taskDependType, warningType, workerGroup, runMode, processInstancePriority, + workerGroup, timeout, startParams); if (timeout == null) { timeout = Constants.MAX_TASK_TIMEOUT; } - + Map startParamMap = null; + if (startParams != null) { + startParamMap = JSONUtils.toMap(startParams); + } Map result = execService.execProcessInstance(loginUser, projectName, processDefinitionId, scheduleTime, execType, failureStrategy, startNodeList, taskDependType, warningType, - warningGroupId, receivers, receiversCc, runMode, processInstancePriority, workerGroup, timeout); + warningGroupId, runMode, processInstancePriority, workerGroup, timeout, startParamMap); return returnDataList(result); } @@ -129,10 +146,10 @@ public class ExecutorController extends BaseController { /** * do action to process instance:pause, stop, repeat, recover from pause, recover from stop * - * @param loginUser login user - * @param projectName project name + * @param loginUser login user + * @param projectName project name * @param processInstanceId process instance id - * @param executeType execute type + * @param executeType execute type * @return execute result code */ @ApiOperation(value = "execute", notes = "EXECUTE_ACTION_TO_PROCESS_INSTANCE_NOTES") @@ -157,7 +174,7 @@ public class ExecutorController extends BaseController { /** * check process definition and all of the son process definitions is on line. * - * @param loginUser login user + * @param loginUser login user * @param processDefinitionId process definition id * @return check result code */ @@ -174,32 +191,4 @@ public class ExecutorController extends BaseController { Map result = execService.startCheckByProcessDefinedId(processDefinitionId); return returnDataList(result); } - - /** - * query recipients and copyers by process definition ID - * - * @param loginUser login user - * @param processDefinitionId process definition id - * @param processInstanceId process instance id - * @return receivers cc list - */ - @ApiIgnore - @ApiOperation(value = "getReceiverCc", notes = "GET_RECEIVER_CC_NOTES") - @ApiImplicitParams({ - @ApiImplicitParam(name = "processDefinitionId", value = "PROCESS_DEFINITION_ID", required = true, dataType = "Int", example = "100"), - @ApiImplicitParam(name = "processInstanceId", value = "PROCESS_INSTANCE_ID", required = true, dataType = "Int", example = "100") - - }) - @GetMapping(value = "/get-receiver-cc") - @ResponseStatus(HttpStatus.OK) - @ApiException(QUERY_RECIPIENTS_AND_COPYERS_BY_PROCESS_DEFINITION_ERROR) - public Result getReceiverCc(@ApiIgnore @RequestAttribute(value = Constants.SESSION_USER) User loginUser, - @RequestParam(value = "processDefinitionId", required = false) Integer processDefinitionId, - @RequestParam(value = "processInstanceId", required = false) Integer processInstanceId) { - logger.info("login user {}, get process definition receiver and cc", loginUser.getUserName()); - Map result = execService.getReceiverCc(processDefinitionId, processInstanceId); - return returnDataList(result); - } - - } diff --git a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/controller/ProcessDefinitionController.java b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/controller/ProcessDefinitionController.java index 8cfbc32fa9..de80740d4e 100644 --- a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/controller/ProcessDefinitionController.java +++ b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/controller/ProcessDefinitionController.java @@ -40,6 +40,7 @@ import org.apache.dolphinscheduler.api.service.ProcessDefinitionService; import org.apache.dolphinscheduler.api.service.ProcessDefinitionVersionService; import org.apache.dolphinscheduler.api.utils.Result; import org.apache.dolphinscheduler.common.Constants; +import org.apache.dolphinscheduler.common.enums.ReleaseState; import org.apache.dolphinscheduler.common.utils.ParameterUtils; import org.apache.dolphinscheduler.common.utils.StringUtils; import org.apache.dolphinscheduler.dao.entity.ProcessDefinition; @@ -95,22 +96,22 @@ public class ProcessDefinitionController extends BaseController { /** * create process definition * - * @param loginUser login user + * @param loginUser login user * @param projectName project name - * @param name process definition name - * @param json process definition json + * @param name process definition name + * @param json process definition json * @param description description - * @param locations locations for nodes - * @param connects connects for nodes + * @param locations locations for nodes + * @param connects connects for nodes * @return create result code */ @ApiOperation(value = "save", notes = "CREATE_PROCESS_DEFINITION_NOTES") @ApiImplicitParams({ - @ApiImplicitParam(name = "name", value = "PROCESS_DEFINITION_NAME", required = true, type = "String"), - @ApiImplicitParam(name = "processDefinitionJson", value = "PROCESS_DEFINITION_JSON", required = true, type = "String"), - @ApiImplicitParam(name = "locations", value = "PROCESS_DEFINITION_LOCATIONS", required = true, type = "String"), - @ApiImplicitParam(name = "connects", value = "PROCESS_DEFINITION_CONNECTS", required = true, type = "String"), - @ApiImplicitParam(name = "description", value = "PROCESS_DEFINITION_DESC", required = false, type = "String"), + @ApiImplicitParam(name = "name", value = "PROCESS_DEFINITION_NAME", required = true, type = "String"), + @ApiImplicitParam(name = "processDefinitionJson", value = "PROCESS_DEFINITION_JSON", required = true, type = "String"), + @ApiImplicitParam(name = "locations", value = "PROCESS_DEFINITION_LOCATIONS", required = true, type = "String"), + @ApiImplicitParam(name = "connects", value = "PROCESS_DEFINITION_CONNECTS", required = true, type = "String"), + @ApiImplicitParam(name = "description", value = "PROCESS_DEFINITION_DESC", required = false, type = "String"), }) @PostMapping(value = "/save") @ResponseStatus(HttpStatus.CREATED) @@ -124,26 +125,26 @@ public class ProcessDefinitionController extends BaseController { @RequestParam(value = "description", required = false) String description) throws JsonProcessingException { logger.info("login user {}, create process definition, project name: {}, process definition name: {}, " - + "process_definition_json: {}, desc: {} locations:{}, connects:{}", - loginUser.getUserName(), projectName, name, json, description, locations, connects); + + "process_definition_json: {}, desc: {} locations:{}, connects:{}", + loginUser.getUserName(), projectName, name, json, description, locations, connects); Map result = processDefinitionService.createProcessDefinition(loginUser, projectName, name, json, - description, locations, connects); + description, locations, connects); return returnDataList(result); } /** * copy process definition * - * @param loginUser login user - * @param projectName project name + * @param loginUser login user + * @param projectName project name * @param processDefinitionIds process definition ids - * @param targetProjectId target project id + * @param targetProjectId target project id * @return copy result code */ @ApiOperation(value = "copyProcessDefinition", notes = "COPY_PROCESS_DEFINITION_NOTES") @ApiImplicitParams({ - @ApiImplicitParam(name = "processDefinitionIds", value = "PROCESS_DEFINITION_IDS", required = true, dataType = "String", example = "3,4"), - @ApiImplicitParam(name = "targetProjectId", value = "TARGET_PROJECT_ID", required = true, dataType = "Int", example = "10") + @ApiImplicitParam(name = "processDefinitionIds", value = "PROCESS_DEFINITION_IDS", required = true, dataType = "String", example = "3,4"), + @ApiImplicitParam(name = "targetProjectId", value = "TARGET_PROJECT_ID", required = true, dataType = "Int", example = "10") }) @PostMapping(value = "/copy") @ResponseStatus(HttpStatus.OK) @@ -153,28 +154,28 @@ public class ProcessDefinitionController extends BaseController { @RequestParam(value = "processDefinitionIds", required = true) String processDefinitionIds, @RequestParam(value = "targetProjectId", required = true) int targetProjectId) { logger.info("batch copy process definition, login user:{}, project name:{}, process definition ids:{},target project id:{}", - StringUtils.replaceNRTtoUnderline(loginUser.getUserName()), - StringUtils.replaceNRTtoUnderline(projectName), - StringUtils.replaceNRTtoUnderline(processDefinitionIds), - StringUtils.replaceNRTtoUnderline(String.valueOf(targetProjectId))); + StringUtils.replaceNRTtoUnderline(loginUser.getUserName()), + StringUtils.replaceNRTtoUnderline(projectName), + StringUtils.replaceNRTtoUnderline(processDefinitionIds), + StringUtils.replaceNRTtoUnderline(String.valueOf(targetProjectId))); return returnDataList( - processDefinitionService.batchCopyProcessDefinition(loginUser, projectName, processDefinitionIds, targetProjectId)); + processDefinitionService.batchCopyProcessDefinition(loginUser, projectName, processDefinitionIds, targetProjectId)); } /** * move process definition * - * @param loginUser login user - * @param projectName project name + * @param loginUser login user + * @param projectName project name * @param processDefinitionIds process definition ids - * @param targetProjectId target project id + * @param targetProjectId target project id * @return move result code */ @ApiOperation(value = "moveProcessDefinition", notes = "MOVE_PROCESS_DEFINITION_NOTES") @ApiImplicitParams({ - @ApiImplicitParam(name = "processDefinitionIds", value = "PROCESS_DEFINITION_IDS", required = true, dataType = "String", example = "3,4"), - @ApiImplicitParam(name = "targetProjectId", value = "TARGET_PROJECT_ID", required = true, dataType = "Int", example = "10") + @ApiImplicitParam(name = "processDefinitionIds", value = "PROCESS_DEFINITION_IDS", required = true, dataType = "String", example = "3,4"), + @ApiImplicitParam(name = "targetProjectId", value = "TARGET_PROJECT_ID", required = true, dataType = "Int", example = "10") }) @PostMapping(value = "/move") @ResponseStatus(HttpStatus.OK) @@ -184,26 +185,26 @@ public class ProcessDefinitionController extends BaseController { @RequestParam(value = "processDefinitionIds", required = true) String processDefinitionIds, @RequestParam(value = "targetProjectId", required = true) int targetProjectId) { logger.info("batch move process definition, login user:{}, project name:{}, process definition ids:{},target project id:{}", - StringUtils.replaceNRTtoUnderline(loginUser.getUserName()), - StringUtils.replaceNRTtoUnderline(projectName), - StringUtils.replaceNRTtoUnderline(processDefinitionIds), - StringUtils.replaceNRTtoUnderline(String.valueOf(targetProjectId))); + StringUtils.replaceNRTtoUnderline(loginUser.getUserName()), + StringUtils.replaceNRTtoUnderline(projectName), + StringUtils.replaceNRTtoUnderline(processDefinitionIds), + StringUtils.replaceNRTtoUnderline(String.valueOf(targetProjectId))); return returnDataList( - processDefinitionService.batchMoveProcessDefinition(loginUser, projectName, processDefinitionIds, targetProjectId)); + processDefinitionService.batchMoveProcessDefinition(loginUser, projectName, processDefinitionIds, targetProjectId)); } /** * verify process definition name unique * - * @param loginUser login user + * @param loginUser login user * @param projectName project name - * @param name name + * @param name name * @return true if process definition name not exists, otherwise false */ @ApiOperation(value = "verify-name", notes = "VERIFY_PROCESS_DEFINITION_NAME_NOTES") @ApiImplicitParams({ - @ApiImplicitParam(name = "name", value = "PROCESS_DEFINITION_NAME", required = true, type = "String") + @ApiImplicitParam(name = "name", value = "PROCESS_DEFINITION_NAME", required = true, type = "String") }) @GetMapping(value = "/verify-name") @ResponseStatus(HttpStatus.OK) @@ -212,7 +213,7 @@ public class ProcessDefinitionController extends BaseController { @ApiParam(name = "projectName", value = "PROJECT_NAME", required = true) @PathVariable String projectName, @RequestParam(value = "name", required = true) String name) { logger.info("verify process definition name unique, user:{}, project name:{}, process definition name:{}", - loginUser.getUserName(), projectName, name); + loginUser.getUserName(), projectName, name); Map result = processDefinitionService.verifyProcessDefinitionName(loginUser, projectName, name); return returnDataList(result); } @@ -220,25 +221,26 @@ public class ProcessDefinitionController extends BaseController { /** * update process definition * - * @param loginUser login user - * @param projectName project name - * @param name process definition name - * @param id process definition id + * @param loginUser login user + * @param projectName project name + * @param name process definition name + * @param id process definition id * @param processDefinitionJson process definition json - * @param description description - * @param locations locations for nodes - * @param connects connects for nodes + * @param description description + * @param locations locations for nodes + * @param connects connects for nodes * @return update result code */ @ApiOperation(value = "updateProcessDefinition", notes = "UPDATE_PROCESS_DEFINITION_NOTES") @ApiImplicitParams({ - @ApiImplicitParam(name = "name", value = "PROCESS_DEFINITION_NAME", required = true, type = "String"), - @ApiImplicitParam(name = "id", value = "PROCESS_DEFINITION_ID", required = true, dataType = "Int", example = "100"), - @ApiImplicitParam(name = "processDefinitionJson", value = "PROCESS_DEFINITION_JSON", required = true, type = "String"), - @ApiImplicitParam(name = "locations", value = "PROCESS_DEFINITION_LOCATIONS", required = true, type = "String"), - @ApiImplicitParam(name = "connects", value = "PROCESS_DEFINITION_CONNECTS", required = true, type = "String"), - @ApiImplicitParam(name = "description", value = "PROCESS_DEFINITION_DESC", required = false, type = "String"), + @ApiImplicitParam(name = "name", value = "PROCESS_DEFINITION_NAME", required = true, type = "String"), + @ApiImplicitParam(name = "id", value = "PROCESS_DEFINITION_ID", required = true, dataType = "Int", example = "100"), + @ApiImplicitParam(name = "processDefinitionJson", value = "PROCESS_DEFINITION_JSON", required = true, type = "String"), + @ApiImplicitParam(name = "locations", value = "PROCESS_DEFINITION_LOCATIONS", required = true, type = "String"), + @ApiImplicitParam(name = "connects", value = "PROCESS_DEFINITION_CONNECTS", required = true, type = "String"), + @ApiImplicitParam(name = "description", value = "PROCESS_DEFINITION_DESC", required = false, type = "String"), + @ApiImplicitParam(name = "releaseState", value = "RELEASE_PROCESS_DEFINITION_NOTES", required = false, dataType = "ReleaseState") }) @PostMapping(value = "/update") @ResponseStatus(HttpStatus.OK) @@ -250,31 +252,41 @@ public class ProcessDefinitionController extends BaseController { @RequestParam(value = "processDefinitionJson", required = true) String processDefinitionJson, @RequestParam(value = "locations", required = false) String locations, @RequestParam(value = "connects", required = false) String connects, - @RequestParam(value = "description", required = false) String description) { + @RequestParam(value = "description", required = false) String description, + @RequestParam(value = "releaseState", required = false, defaultValue = "OFFLINE") ReleaseState releaseState) { logger.info("login user {}, update process define, project name: {}, process define name: {}, " - + "process_definition_json: {}, desc: {}, locations:{}, connects:{}", - loginUser.getUserName(), projectName, name, processDefinitionJson, description, locations, connects); + + "process_definition_json: {}, desc: {}, locations:{}, connects:{}", + loginUser.getUserName(), projectName, name, processDefinitionJson, description, locations, connects); Map result = processDefinitionService.updateProcessDefinition(loginUser, projectName, id, name, - processDefinitionJson, description, locations, connects); + processDefinitionJson, description, locations, connects); + // If the update fails, the result will be returned directly + if (result.get(Constants.STATUS) != Status.SUCCESS) { + return returnDataList(result); + } + + // Judge whether to go online after editing,0 means offline, 1 means online + if (releaseState == ReleaseState.ONLINE) { + result = processDefinitionService.releaseProcessDefinition(loginUser, projectName, id, releaseState); + } return returnDataList(result); } /** * query process definition version paging list info * - * @param loginUser login user info - * @param projectName the process definition project name - * @param pageNo the process definition version list current page number - * @param pageSize the process definition version list page size + * @param loginUser login user info + * @param projectName the process definition project name + * @param pageNo the process definition version list current page number + * @param pageSize the process definition version list page size * @param processDefinitionId the process definition id * @return the process definition version list */ @ApiOperation(value = "queryProcessDefinitionVersions", notes = "QUERY_PROCESS_DEFINITION_VERSIONS_NOTES") @ApiImplicitParams({ - @ApiImplicitParam(name = "pageNo", value = "PAGE_NO", required = true, dataType = "Int", example = "100"), - @ApiImplicitParam(name = "pageSize", value = "PAGE_SIZE", required = true, dataType = "Int", example = "100"), - @ApiImplicitParam(name = "processDefinitionId", value = "PROCESS_DEFINITION_ID", required = true, dataType = "Int", example = "100") + @ApiImplicitParam(name = "pageNo", value = "PAGE_NO", required = true, dataType = "Int", example = "100"), + @ApiImplicitParam(name = "pageSize", value = "PAGE_SIZE", required = true, dataType = "Int", example = "100"), + @ApiImplicitParam(name = "processDefinitionId", value = "PROCESS_DEFINITION_ID", required = true, dataType = "Int", example = "100") }) @GetMapping(value = "/versions") @ResponseStatus(HttpStatus.OK) @@ -286,23 +298,23 @@ public class ProcessDefinitionController extends BaseController { @RequestParam(value = "processDefinitionId") int processDefinitionId) { Map result = processDefinitionVersionService.queryProcessDefinitionVersions(loginUser - , projectName, pageNo, pageSize, processDefinitionId); + , projectName, pageNo, pageSize, processDefinitionId); return returnDataList(result); } /** * switch certain process definition version * - * @param loginUser login user info - * @param projectName the process definition project name + * @param loginUser login user info + * @param projectName the process definition project name * @param processDefinitionId the process definition id - * @param version the version user want to switch + * @param version the version user want to switch * @return switch version result code */ @ApiOperation(value = "switchProcessDefinitionVersion", notes = "SWITCH_PROCESS_DEFINITION_VERSION_NOTES") @ApiImplicitParams({ - @ApiImplicitParam(name = "processDefinitionId", value = "PROCESS_DEFINITION_ID", required = true, dataType = "Int", example = "100"), - @ApiImplicitParam(name = "version", value = "VERSION", required = true, dataType = "Long", example = "100") + @ApiImplicitParam(name = "processDefinitionId", value = "PROCESS_DEFINITION_ID", required = true, dataType = "Int", example = "100"), + @ApiImplicitParam(name = "version", value = "VERSION", required = true, dataType = "Long", example = "100") }) @GetMapping(value = "/version/switch") @ResponseStatus(HttpStatus.OK) @@ -313,23 +325,23 @@ public class ProcessDefinitionController extends BaseController { @RequestParam(value = "version") long version) { Map result = processDefinitionService.switchProcessDefinitionVersion(loginUser, projectName - , processDefinitionId, version); + , processDefinitionId, version); return returnDataList(result); } /** * delete the certain process definition version by version and process definition id * - * @param loginUser login user info - * @param projectName the process definition project name + * @param loginUser login user info + * @param projectName the process definition project name * @param processDefinitionId process definition id - * @param version the process definition version user want to delete + * @param version the process definition version user want to delete * @return delete version result code */ @ApiOperation(value = "deleteProcessDefinitionVersion", notes = "DELETE_PROCESS_DEFINITION_VERSION_NOTES") @ApiImplicitParams({ - @ApiImplicitParam(name = "processDefinitionId", value = "PROCESS_DEFINITION_ID", required = true, dataType = "Int", example = "100"), - @ApiImplicitParam(name = "version", value = "VERSION", required = true, dataType = "Long", example = "100") + @ApiImplicitParam(name = "processDefinitionId", value = "PROCESS_DEFINITION_ID", required = true, dataType = "Int", example = "100"), + @ApiImplicitParam(name = "version", value = "VERSION", required = true, dataType = "Long", example = "100") }) @GetMapping(value = "/version/delete") @ResponseStatus(HttpStatus.OK) @@ -346,17 +358,17 @@ public class ProcessDefinitionController extends BaseController { /** * release process definition * - * @param loginUser login user - * @param projectName project name - * @param processId process definition id + * @param loginUser login user + * @param projectName project name + * @param processId process definition id * @param releaseState release state * @return release result code */ @ApiOperation(value = "releaseProcessDefinition", notes = "RELEASE_PROCESS_DEFINITION_NOTES") @ApiImplicitParams({ - @ApiImplicitParam(name = "name", value = "PROCESS_DEFINITION_NAME", required = true, type = "String"), - @ApiImplicitParam(name = "processId", value = "PROCESS_DEFINITION_ID", required = true, dataType = "Int", example = "100"), - @ApiImplicitParam(name = "releaseState", value = "PROCESS_DEFINITION_CONNECTS", required = true, dataType = "Int", example = "100"), + @ApiImplicitParam(name = "name", value = "PROCESS_DEFINITION_NAME", required = true, type = "String"), + @ApiImplicitParam(name = "processId", value = "PROCESS_DEFINITION_ID", required = true, dataType = "Int", example = "100"), + @ApiImplicitParam(name = "releaseState", value = "PROCESS_DEFINITION_CONNECTS", required = true, dataType = "ReleaseState"), }) @PostMapping(value = "/release") @ResponseStatus(HttpStatus.OK) @@ -364,10 +376,10 @@ public class ProcessDefinitionController extends BaseController { public Result releaseProcessDefinition(@ApiIgnore @RequestAttribute(value = Constants.SESSION_USER) User loginUser, @ApiParam(name = "projectName", value = "PROJECT_NAME", required = true) @PathVariable String projectName, @RequestParam(value = "processId", required = true) int processId, - @RequestParam(value = "releaseState", required = true) int releaseState) { + @RequestParam(value = "releaseState", required = true) ReleaseState releaseState) { logger.info("login user {}, release process definition, project name: {}, release state: {}", - loginUser.getUserName(), projectName, releaseState); + loginUser.getUserName(), projectName, releaseState); Map result = processDefinitionService.releaseProcessDefinition(loginUser, projectName, processId, releaseState); return returnDataList(result); } @@ -375,14 +387,14 @@ public class ProcessDefinitionController extends BaseController { /** * query datail of process definition by id * - * @param loginUser login user + * @param loginUser login user * @param projectName project name - * @param processId process definition id + * @param processId process definition id * @return process definition detail */ @ApiOperation(value = "queryProcessDefinitionById", notes = "QUERY_PROCESS_DEFINITION_BY_ID_NOTES") @ApiImplicitParams({ - @ApiImplicitParam(name = "processId", value = "PROCESS_DEFINITION_ID", required = true, dataType = "Int", example = "100") + @ApiImplicitParam(name = "processId", value = "PROCESS_DEFINITION_ID", required = true, dataType = "Int", example = "100") }) @GetMapping(value = "/select-by-id") @ResponseStatus(HttpStatus.OK) @@ -392,7 +404,7 @@ public class ProcessDefinitionController extends BaseController { @RequestParam("processId") Integer processId ) { logger.info("query detail of process definition, login user:{}, project name:{}, process definition id:{}", - loginUser.getUserName(), projectName, processId); + loginUser.getUserName(), projectName, processId); Map result = processDefinitionService.queryProcessDefinitionById(loginUser, projectName, processId); return returnDataList(result); } @@ -423,7 +435,7 @@ public class ProcessDefinitionController extends BaseController { /** * query Process definition list * - * @param loginUser login user + * @param loginUser login user * @param projectName project name * @return process definition list */ @@ -435,7 +447,7 @@ public class ProcessDefinitionController extends BaseController { @ApiParam(name = "projectName", value = "PROJECT_NAME", required = true) @PathVariable String projectName ) { logger.info("query process definition list, login user:{}, project name:{}", - loginUser.getUserName(), projectName); + loginUser.getUserName(), projectName); Map result = processDefinitionService.queryProcessDefinitionList(loginUser, projectName); return returnDataList(result); } @@ -443,20 +455,20 @@ public class ProcessDefinitionController extends BaseController { /** * query process definition list paging * - * @param loginUser login user + * @param loginUser login user * @param projectName project name - * @param searchVal search value - * @param pageNo page number - * @param pageSize page size - * @param userId user id + * @param searchVal search value + * @param pageNo page number + * @param pageSize page size + * @param userId user id * @return process definition page */ @ApiOperation(value = "queryProcessDefinitionListPaging", notes = "QUERY_PROCESS_DEFINITION_LIST_PAGING_NOTES") @ApiImplicitParams({ - @ApiImplicitParam(name = "pageNo", value = "PAGE_NO", required = true, dataType = "Int", example = "100"), - @ApiImplicitParam(name = "searchVal", value = "SEARCH_VAL", required = false, type = "String"), - @ApiImplicitParam(name = "userId", value = "USER_ID", required = false, dataType = "Int", example = "100"), - @ApiImplicitParam(name = "pageSize", value = "PAGE_SIZE", required = true, dataType = "Int", example = "100") + @ApiImplicitParam(name = "pageNo", value = "PAGE_NO", required = true, dataType = "Int", example = "100"), + @ApiImplicitParam(name = "searchVal", value = "SEARCH_VAL", required = false, type = "String"), + @ApiImplicitParam(name = "userId", value = "USER_ID", required = false, dataType = "Int", example = "100"), + @ApiImplicitParam(name = "pageSize", value = "PAGE_SIZE", required = true, dataType = "Int", example = "100") }) @GetMapping(value = "/list-paging") @ResponseStatus(HttpStatus.OK) @@ -480,16 +492,16 @@ public class ProcessDefinitionController extends BaseController { /** * encapsulation treeview structure * - * @param loginUser login user + * @param loginUser login user * @param projectName project name - * @param id process definition id - * @param limit limit + * @param id process definition id + * @param limit limit * @return tree view json data */ @ApiOperation(value = "viewTree", notes = "VIEW_TREE_NOTES") @ApiImplicitParams({ - @ApiImplicitParam(name = "processId", value = "PROCESS_DEFINITION_ID", required = true, dataType = "Int", example = "100"), - @ApiImplicitParam(name = "limit", value = "LIMIT", required = true, dataType = "Int", example = "100") + @ApiImplicitParam(name = "processId", value = "PROCESS_DEFINITION_ID", required = true, dataType = "Int", example = "100"), + @ApiImplicitParam(name = "limit", value = "LIMIT", required = true, dataType = "Int", example = "100") }) @GetMapping(value = "/view-tree") @ResponseStatus(HttpStatus.OK) @@ -505,24 +517,24 @@ public class ProcessDefinitionController extends BaseController { /** * get tasks list by process definition id * - * @param loginUser login user - * @param projectName project name + * @param loginUser login user + * @param projectName project name * @param processDefinitionId process definition id * @return task list */ @ApiOperation(value = "getNodeListByDefinitionId", notes = "GET_NODE_LIST_BY_DEFINITION_ID_NOTES") @ApiImplicitParams({ - @ApiImplicitParam(name = "processDefinitionId", value = "PROCESS_DEFINITION_ID", required = true, dataType = "Int", example = "100") + @ApiImplicitParam(name = "processDefinitionId", value = "PROCESS_DEFINITION_ID", required = true, dataType = "Int", example = "100") }) @GetMapping(value = "gen-task-list") @ResponseStatus(HttpStatus.OK) @ApiException(GET_TASKS_LIST_BY_PROCESS_DEFINITION_ID_ERROR) public Result getNodeListByDefinitionId( - @ApiIgnore @RequestAttribute(value = Constants.SESSION_USER) User loginUser, - @ApiParam(name = "projectName", value = "PROJECT_NAME", required = true) @PathVariable String projectName, - @RequestParam("processDefinitionId") Integer processDefinitionId) throws Exception { + @ApiIgnore @RequestAttribute(value = Constants.SESSION_USER) User loginUser, + @ApiParam(name = "projectName", value = "PROJECT_NAME", required = true) @PathVariable String projectName, + @RequestParam("processDefinitionId") Integer processDefinitionId) throws Exception { logger.info("query task node name list by definitionId, login user:{}, project name:{}, id : {}", - loginUser.getUserName(), projectName, processDefinitionId); + loginUser.getUserName(), projectName, processDefinitionId); Map result = processDefinitionService.getTaskNodeListByDefinitionId(processDefinitionId); return returnDataList(result); } @@ -530,25 +542,25 @@ public class ProcessDefinitionController extends BaseController { /** * get tasks list by process definition id * - * @param loginUser login user - * @param projectName project name + * @param loginUser login user + * @param projectName project name * @param processDefinitionIdList process definition id list * @return node list data */ @ApiOperation(value = "getNodeListByDefinitionIdList", notes = "GET_NODE_LIST_BY_DEFINITION_ID_NOTES") @ApiImplicitParams({ - @ApiImplicitParam(name = "processDefinitionIdList", value = "PROCESS_DEFINITION_ID_LIST", required = true, type = "String") + @ApiImplicitParam(name = "processDefinitionIdList", value = "PROCESS_DEFINITION_ID_LIST", required = true, type = "String") }) @GetMapping(value = "get-task-list") @ResponseStatus(HttpStatus.OK) @ApiException(GET_TASKS_LIST_BY_PROCESS_DEFINITION_ID_ERROR) public Result getNodeListByDefinitionIdList( - @ApiIgnore @RequestAttribute(value = Constants.SESSION_USER) User loginUser, - @ApiParam(name = "projectName", value = "PROJECT_NAME", required = true) @PathVariable String projectName, - @RequestParam("processDefinitionIdList") String processDefinitionIdList) { + @ApiIgnore @RequestAttribute(value = Constants.SESSION_USER) User loginUser, + @ApiParam(name = "projectName", value = "PROJECT_NAME", required = true) @PathVariable String projectName, + @RequestParam("processDefinitionIdList") String processDefinitionIdList) { logger.info("query task node name list by definitionId list, login user:{}, project name:{}, id list: {}", - loginUser.getUserName(), projectName, processDefinitionIdList); + loginUser.getUserName(), projectName, processDefinitionIdList); Map result = processDefinitionService.getTaskNodeListByDefinitionIdList(processDefinitionIdList); return returnDataList(result); } @@ -556,14 +568,14 @@ public class ProcessDefinitionController extends BaseController { /** * delete process definition by id * - * @param loginUser login user - * @param projectName project name + * @param loginUser login user + * @param projectName project name * @param processDefinitionId process definition id * @return delete result code */ @ApiOperation(value = "deleteProcessDefinitionById", notes = "DELETE_PROCESS_DEFINITION_BY_ID_NOTES") @ApiImplicitParams({ - @ApiImplicitParam(name = "processDefinitionId", value = "PROCESS_DEFINITION_ID", dataType = "Int", example = "100") + @ApiImplicitParam(name = "processDefinitionId", value = "PROCESS_DEFINITION_ID", dataType = "Int", example = "100") }) @GetMapping(value = "/delete") @ResponseStatus(HttpStatus.OK) @@ -573,7 +585,7 @@ public class ProcessDefinitionController extends BaseController { @RequestParam("processDefinitionId") Integer processDefinitionId ) { logger.info("delete process definition by id, login user:{}, project name:{}, process definition id:{}", - loginUser.getUserName(), projectName, processDefinitionId); + loginUser.getUserName(), projectName, processDefinitionId); Map result = processDefinitionService.deleteProcessDefinitionById(loginUser, projectName, processDefinitionId); return returnDataList(result); } @@ -581,14 +593,14 @@ public class ProcessDefinitionController extends BaseController { /** * batch delete process definition by ids * - * @param loginUser login user - * @param projectName project name + * @param loginUser login user + * @param projectName project name * @param processDefinitionIds process definition id list * @return delete result code */ @ApiOperation(value = "batchDeleteProcessDefinitionByIds", notes = "BATCH_DELETE_PROCESS_DEFINITION_BY_IDS_NOTES") @ApiImplicitParams({ - @ApiImplicitParam(name = "processDefinitionIds", value = "PROCESS_DEFINITION_IDS", type = "String") + @ApiImplicitParam(name = "processDefinitionIds", value = "PROCESS_DEFINITION_IDS", type = "String") }) @GetMapping(value = "/batch-delete") @ResponseStatus(HttpStatus.OK) @@ -598,7 +610,7 @@ public class ProcessDefinitionController extends BaseController { @RequestParam("processDefinitionIds") String processDefinitionIds ) { logger.info("delete process definition by ids, login user:{}, project name:{}, process definition ids:{}", - loginUser.getUserName(), projectName, processDefinitionIds); + loginUser.getUserName(), projectName, processDefinitionIds); Map result = new HashMap<>(); List deleteFailedIdList = new ArrayList<>(); @@ -631,15 +643,15 @@ public class ProcessDefinitionController extends BaseController { /** * batch export process definition by ids * - * @param loginUser login user - * @param projectName project name + * @param loginUser login user + * @param projectName project name * @param processDefinitionIds process definition ids - * @param response response + * @param response response */ @ApiOperation(value = "batchExportProcessDefinitionByIds", notes = "BATCH_EXPORT_PROCESS_DEFINITION_BY_IDS_NOTES") @ApiImplicitParams({ - @ApiImplicitParam(name = "processDefinitionIds", value = "PROCESS_DEFINITION_ID", required = true, dataType = "String") + @ApiImplicitParam(name = "processDefinitionIds", value = "PROCESS_DEFINITION_ID", required = true, dataType = "String") }) @GetMapping(value = "/export") @ResponseBody @@ -649,7 +661,7 @@ public class ProcessDefinitionController extends BaseController { HttpServletResponse response) { try { logger.info("batch export process definition by ids, login user:{}, project name:{}, process definition ids:{}", - loginUser.getUserName(), projectName, processDefinitionIds); + loginUser.getUserName(), projectName, processDefinitionIds); processDefinitionService.batchExportProcessDefinitionByIds(loginUser, projectName, processDefinitionIds, response); } catch (Exception e) { logger.error(Status.BATCH_EXPORT_PROCESS_DEFINE_BY_IDS_ERROR.getMsg(), e); @@ -670,7 +682,7 @@ public class ProcessDefinitionController extends BaseController { public Result queryProcessDefinitionAllByProjectId(@ApiIgnore @RequestAttribute(value = Constants.SESSION_USER) User loginUser, @RequestParam("projectId") Integer projectId) { logger.info("query process definition list, login user:{}, project id:{}", - loginUser.getUserName(), projectId); + loginUser.getUserName(), projectId); Map result = processDefinitionService.queryProcessDefinitionAllByProjectId(projectId); return returnDataList(result); } diff --git a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/controller/SchedulerController.java b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/controller/SchedulerController.java index 5713d7ffc4..ca57ad11a4 100644 --- a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/controller/SchedulerController.java +++ b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/controller/SchedulerController.java @@ -14,8 +14,18 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.dolphinscheduler.api.controller; +import static org.apache.dolphinscheduler.api.enums.Status.CREATE_SCHEDULE_ERROR; +import static org.apache.dolphinscheduler.api.enums.Status.DELETE_SCHEDULE_CRON_BY_ID_ERROR; +import static org.apache.dolphinscheduler.api.enums.Status.OFFLINE_SCHEDULE_ERROR; +import static org.apache.dolphinscheduler.api.enums.Status.PREVIEW_SCHEDULE_ERROR; +import static org.apache.dolphinscheduler.api.enums.Status.PUBLISH_SCHEDULE_ONLINE_ERROR; +import static org.apache.dolphinscheduler.api.enums.Status.QUERY_SCHEDULE_LIST_ERROR; +import static org.apache.dolphinscheduler.api.enums.Status.QUERY_SCHEDULE_LIST_PAGING_ERROR; +import static org.apache.dolphinscheduler.api.enums.Status.UPDATE_SCHEDULE_ERROR; +import static org.apache.dolphinscheduler.common.Constants.SESSION_USER; import org.apache.dolphinscheduler.api.exceptions.ApiException; import org.apache.dolphinscheduler.api.service.SchedulerService; @@ -25,20 +35,30 @@ import org.apache.dolphinscheduler.common.enums.Priority; import org.apache.dolphinscheduler.common.enums.ReleaseState; import org.apache.dolphinscheduler.common.enums.WarningType; import org.apache.dolphinscheduler.common.utils.ParameterUtils; +import org.apache.dolphinscheduler.common.utils.StringUtils; import org.apache.dolphinscheduler.dao.entity.User; -import io.swagger.annotations.*; + +import java.util.Map; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; -import org.springframework.web.bind.annotation.*; -import springfox.documentation.annotations.ApiIgnore; - -import java.io.IOException; -import java.util.Map; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestAttribute; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.bind.annotation.RestController; -import static org.apache.dolphinscheduler.api.enums.Status.*; -import static org.apache.dolphinscheduler.common.Constants.SESSION_USER; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiImplicitParams; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import springfox.documentation.annotations.ApiIgnore; /** * schedule controller @@ -61,17 +81,15 @@ public class SchedulerController extends BaseController { /** * create schedule * - * @param loginUser login user - * @param projectName project name - * @param processDefinitionId process definition id - * @param schedule scheduler - * @param warningType warning type - * @param warningGroupId warning group id - * @param failureStrategy failure strategy + * @param loginUser login user + * @param projectName project name + * @param processDefinitionId process definition id + * @param schedule scheduler + * @param warningType warning type + * @param warningGroupId warning group id + * @param failureStrategy failure strategy * @param processInstancePriority process instance priority - * @param receivers receivers - * @param receiversCc receivers cc - * @param workerGroup worker group + * @param workerGroup worker group * @return create result code */ @ApiOperation(value = "createSchedule", notes = "CREATE_SCHEDULE_NOTES") @@ -81,8 +99,6 @@ public class SchedulerController extends BaseController { @ApiImplicitParam(name = "warningType", value = "WARNING_TYPE", type = "WarningType"), @ApiImplicitParam(name = "warningGroupId", value = "WARNING_GROUP_ID", dataType = "Int", example = "100"), @ApiImplicitParam(name = "failureStrategy", value = "FAILURE_STRATEGY", type = "FailureStrategy"), - @ApiImplicitParam(name = "receivers", value = "RECEIVERS", type = "String"), - @ApiImplicitParam(name = "receiversCc", value = "RECEIVERS_CC", type = "String"), @ApiImplicitParam(name = "workerGroupId", value = "WORKER_GROUP_ID", dataType = "Int", example = "100"), @ApiImplicitParam(name = "processInstancePriority", value = "PROCESS_INSTANCE_PRIORITY", type = "Priority"), }) @@ -96,16 +112,14 @@ public class SchedulerController extends BaseController { @RequestParam(value = "warningType", required = false, defaultValue = DEFAULT_WARNING_TYPE) WarningType warningType, @RequestParam(value = "warningGroupId", required = false, defaultValue = DEFAULT_NOTIFY_GROUP_ID) int warningGroupId, @RequestParam(value = "failureStrategy", required = false, defaultValue = DEFAULT_FAILURE_POLICY) FailureStrategy failureStrategy, - @RequestParam(value = "receivers", required = false) String receivers, - @RequestParam(value = "receiversCc", required = false) String receiversCc, @RequestParam(value = "workerGroup", required = false, defaultValue = "default") String workerGroup, - @RequestParam(value = "processInstancePriority", required = false, defaultValue = DEFAULT_PROCESS_INSTANCE_PRIORITY) Priority processInstancePriority) throws IOException { - logger.info("login user {}, project name: {}, process name: {}, create schedule: {}, warning type: {}, warning group id: {}," + - "failure policy: {},receivers : {},receiversCc : {},processInstancePriority : {}, workGroupId:{}", - loginUser.getUserName(), projectName, processDefinitionId, schedule, warningType, warningGroupId, - failureStrategy, receivers, receiversCc, processInstancePriority, workerGroup); + @RequestParam(value = "processInstancePriority", required = false, defaultValue = DEFAULT_PROCESS_INSTANCE_PRIORITY) Priority processInstancePriority) { + logger.info("login user {},project name: {}, process name: {}, create schedule: {}, warning type: {}, warning group id: {}," + + "failure policy: {},processInstancePriority : {}, workGroupId:{}", + StringUtils.replaceNRTtoUnderline(loginUser.getUserName()), StringUtils.replaceNRTtoUnderline(projectName), processDefinitionId, schedule, warningType, warningGroupId, + failureStrategy, processInstancePriority, workerGroup); Map result = schedulerService.insertSchedule(loginUser, projectName, processDefinitionId, schedule, - warningType, warningGroupId, failureStrategy, receivers, receiversCc, processInstancePriority, workerGroup); + warningType, warningGroupId, failureStrategy, processInstancePriority, workerGroup); return returnDataList(result); } @@ -113,17 +127,15 @@ public class SchedulerController extends BaseController { /** * updateProcessInstance schedule * - * @param loginUser login user - * @param projectName project name - * @param id scheduler id - * @param schedule scheduler - * @param warningType warning type - * @param warningGroupId warning group id - * @param failureStrategy failure strategy - * @param receivers receivers - * @param workerGroup worker group + * @param loginUser login user + * @param projectName project name + * @param id scheduler id + * @param schedule scheduler + * @param warningType warning type + * @param warningGroupId warning group id + * @param failureStrategy failure strategy + * @param workerGroup worker group * @param processInstancePriority process instance priority - * @param receiversCc receivers cc * @return update result code */ @ApiOperation(value = "updateSchedule", notes = "UPDATE_SCHEDULE_NOTES") @@ -133,8 +145,6 @@ public class SchedulerController extends BaseController { @ApiImplicitParam(name = "warningType", value = "WARNING_TYPE", type = "WarningType"), @ApiImplicitParam(name = "warningGroupId", value = "WARNING_GROUP_ID", dataType = "Int", example = "100"), @ApiImplicitParam(name = "failureStrategy", value = "FAILURE_STRATEGY", type = "FailureStrategy"), - @ApiImplicitParam(name = "receivers", value = "RECEIVERS", type = "String"), - @ApiImplicitParam(name = "receiversCc", value = "RECEIVERS_CC", type = "String"), @ApiImplicitParam(name = "workerGroupId", value = "WORKER_GROUP_ID", dataType = "Int", example = "100"), @ApiImplicitParam(name = "processInstancePriority", value = "PROCESS_INSTANCE_PRIORITY", type = "Priority"), }) @@ -147,26 +157,24 @@ public class SchedulerController extends BaseController { @RequestParam(value = "warningType", required = false, defaultValue = DEFAULT_WARNING_TYPE) WarningType warningType, @RequestParam(value = "warningGroupId", required = false) int warningGroupId, @RequestParam(value = "failureStrategy", required = false, defaultValue = "END") FailureStrategy failureStrategy, - @RequestParam(value = "receivers", required = false) String receivers, - @RequestParam(value = "receiversCc", required = false) String receiversCc, @RequestParam(value = "workerGroup", required = false, defaultValue = "default") String workerGroup, - @RequestParam(value = "processInstancePriority", required = false) Priority processInstancePriority) throws IOException { - logger.info("login user {}, project name: {},id: {}, updateProcessInstance schedule: {}, notify type: {}, notify mails: {}, " + - "failure policy: {},receivers : {},receiversCc : {},processInstancePriority : {},workerGroupId:{}", - loginUser.getUserName(), projectName, id, schedule, warningType, warningGroupId, failureStrategy, - receivers, receiversCc, processInstancePriority, workerGroup); + @RequestParam(value = "processInstancePriority", required = false) Priority processInstancePriority) { + logger.info("login user {},project name: {},id: {}, updateProcessInstance schedule: {}, notify type: {}, notify mails: {}, " + + "failure policy: {},processInstancePriority : {},workerGroupId:{}", + StringUtils.replaceNRTtoUnderline(loginUser.getUserName()), StringUtils.replaceNRTtoUnderline(projectName), id, schedule, warningType, warningGroupId, failureStrategy, + processInstancePriority, workerGroup); Map result = schedulerService.updateSchedule(loginUser, projectName, id, schedule, - warningType, warningGroupId, failureStrategy, receivers, receiversCc, null, processInstancePriority, workerGroup); + warningType, warningGroupId, failureStrategy, null, processInstancePriority, workerGroup); return returnDataList(result); } /** * publish schedule setScheduleState * - * @param loginUser login user + * @param loginUser login user * @param projectName project name - * @param id scheduler id + * @param id scheduler id * @return publish result code */ @ApiOperation(value = "online", notes = "ONLINE_SCHEDULE_NOTES") @@ -187,9 +195,9 @@ public class SchedulerController extends BaseController { /** * offline schedule * - * @param loginUser login user + * @param loginUser login user * @param projectName project name - * @param id schedule id + * @param id schedule id * @return operation result code */ @ApiOperation(value = "offline", notes = "OFFLINE_SCHEDULE_NOTES") @@ -211,12 +219,12 @@ public class SchedulerController extends BaseController { /** * query schedule list paging * - * @param loginUser login user - * @param projectName project name + * @param loginUser login user + * @param projectName project name * @param processDefinitionId process definition id - * @param pageNo page number - * @param pageSize page size - * @param searchVal search value + * @param pageNo page number + * @param pageSize page size + * @param searchVal search value * @return schedule list page */ @ApiOperation(value = "queryScheduleListPaging", notes = "QUERY_SCHEDULE_LIST_PAGING_NOTES") @@ -245,9 +253,9 @@ public class SchedulerController extends BaseController { /** * delete schedule by id * - * @param loginUser login user + * @param loginUser login user * @param projectName project name - * @param scheduleId scheule id + * @param scheduleId scheule id * @return delete result code */ @ApiOperation(value = "deleteScheduleById", notes = "OFFLINE_SCHEDULE_NOTES") @@ -270,7 +278,7 @@ public class SchedulerController extends BaseController { /** * query schedule list * - * @param loginUser login user + * @param loginUser login user * @param projectName project name * @return schedule list */ @@ -288,9 +296,9 @@ public class SchedulerController extends BaseController { /** * preview schedule * - * @param loginUser login user + * @param loginUser login user * @param projectName project name - * @param schedule schedule expression + * @param schedule schedule expression * @return the next five fire time */ @ApiOperation(value = "previewSchedule", notes = "PREVIEW_SCHEDULE_NOTES") diff --git a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/controller/TaskInstanceController.java b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/controller/TaskInstanceController.java index 56e7ef2087..a07478315a 100644 --- a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/controller/TaskInstanceController.java +++ b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/controller/TaskInstanceController.java @@ -17,6 +17,7 @@ package org.apache.dolphinscheduler.api.controller; +import static org.apache.dolphinscheduler.api.enums.Status.FORCE_TASK_SUCCESS_ERROR; import static org.apache.dolphinscheduler.api.enums.Status.QUERY_TASK_LIST_PAGING_ERROR; import org.apache.dolphinscheduler.api.exceptions.ApiException; @@ -36,6 +37,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestAttribute; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; @@ -127,4 +129,27 @@ public class TaskInstanceController extends BaseController { return returnDataListPaging(result); } + /** + * change one task instance's state from FAILURE to FORCED_SUCCESS + * + * @param loginUser login user + * @param projectName project name + * @param taskInstanceId task instance id + * @return the result code and msg + */ + @ApiOperation(value = "force-success", notes = "FORCE_TASK_SUCCESS") + @ApiImplicitParams({ + @ApiImplicitParam(name = "taskInstanceId", value = "TASK_INSTANCE_ID", required = true, dataType = "Int", example = "12") + }) + @PostMapping(value = "/force-success") + @ResponseStatus(HttpStatus.OK) + @ApiException(FORCE_TASK_SUCCESS_ERROR) + public Result forceTaskSuccess(@ApiIgnore @RequestAttribute(value = Constants.SESSION_USER) User loginUser, + @ApiParam(name = "projectName", value = "PROJECT_NAME", required = true) @PathVariable String projectName, + @RequestParam(value = "taskInstanceId") Integer taskInstanceId) { + logger.info("force task success, project: {}, task instance id: {}", projectName, taskInstanceId); + Map result = taskInstanceService.forceTaskSuccess(loginUser, projectName, taskInstanceId); + return returnDataList(result); + } + } diff --git a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/controller/UiPluginController.java b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/controller/UiPluginController.java new file mode 100644 index 0000000000..3589bdcdc0 --- /dev/null +++ b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/controller/UiPluginController.java @@ -0,0 +1,93 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.dolphinscheduler.api.controller; + +import static org.apache.dolphinscheduler.api.enums.Status.QUERY_PLUGINS_ERROR; + +import org.apache.dolphinscheduler.api.exceptions.ApiException; +import org.apache.dolphinscheduler.api.service.UiPluginService; +import org.apache.dolphinscheduler.api.utils.Result; +import org.apache.dolphinscheduler.common.Constants; +import org.apache.dolphinscheduler.common.enums.PluginType; +import org.apache.dolphinscheduler.dao.entity.User; + +import java.util.Map; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestAttribute; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.bind.annotation.RestController; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiImplicitParams; +import io.swagger.annotations.ApiOperation; +import springfox.documentation.annotations.ApiIgnore; + +/** + * UiPluginController + * Some plugins (such as alert plugin) need to provide UI interfaces to users. + * We use from-creat to dynamically generate UI interfaces. Related parameters are mainly provided by pluginParams. + * From-create can generate dynamic ui based on this parameter. + */ +@Api(tags = "UI_PLUGINS", position = 1) +@RestController +@RequestMapping("ui-plugins") +public class UiPluginController extends BaseController { + + private static final Logger logger = LoggerFactory.getLogger(UiPluginController.class); + + @Autowired + UiPluginService uiPluginService; + + @ApiOperation(value = "queryUiPluginsByType", notes = "QUERY_UI_PLUGINS_BY_TYPE") + @ApiImplicitParams({ + @ApiImplicitParam(name = "pluginType", value = "pluginType", required = true, dataType = "PluginType"), + }) + @PostMapping(value = "/queryUiPluginsByType") + @ResponseStatus(HttpStatus.CREATED) + @ApiException(QUERY_PLUGINS_ERROR) + public Result queryUiPluginsByType(@ApiIgnore @RequestAttribute(value = Constants.SESSION_USER) User loginUser, + @RequestParam(value = "pluginType") PluginType pluginType) { + + logger.info("query plugins by type , pluginType: {}", pluginType); + Map result = uiPluginService.queryUiPluginsByType(pluginType); + return returnDataList(result); + } + + @ApiOperation(value = "queryUiPluginDetailById", notes = "QUERY_UI_PLUGIN_DETAIL_BY_ID") + @ApiImplicitParams({ + @ApiImplicitParam(name = "id", value = "id", required = true, dataType = "PluginType"), + }) + @PostMapping(value = "/queryUiPluginDetailById") + @ResponseStatus(HttpStatus.CREATED) + @ApiException(QUERY_PLUGINS_ERROR) + public Result queryUiPluginDetailById(@ApiIgnore @RequestAttribute(value = Constants.SESSION_USER) User loginUser, + @RequestParam("pluginId") Integer pluginId) { + + logger.info("query plugin detail by id , pluginId: {}", pluginId); + Map result = uiPluginService.queryUiPluginDetailById(pluginId); + return returnDataList(result); + } +} diff --git a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/dto/TaskCountDto.java b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/dto/TaskCountDto.java index 6f42ba9f56..41c7abba85 100644 --- a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/dto/TaskCountDto.java +++ b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/dto/TaskCountDto.java @@ -57,6 +57,16 @@ public class TaskCountDto { .sum(); } + // remove the specified state + public void removeStateFromCountList(ExecutionStatus status) { + for (TaskStateCount count : this.taskCountDtos) { + if (count.getTaskStateType().equals(status)) { + this.taskCountDtos.remove(count); + break; + } + } + } + public List getTaskCountDtos() { return taskCountDtos; } diff --git a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/enums/ExecuteType.java b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/enums/ExecuteType.java index cc1797295a..f4dac5aecd 100644 --- a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/enums/ExecuteType.java +++ b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/enums/ExecuteType.java @@ -30,7 +30,7 @@ public enum ExecuteType { * 4 stop * 5 pause */ - NONE,REPEAT_RUNNING, RECOVER_SUSPENDED_PROCESS, START_FAILURE_TASK_PROCESS, STOP, PAUSE; + NONE, REPEAT_RUNNING, RECOVER_SUSPENDED_PROCESS, START_FAILURE_TASK_PROCESS, STOP, PAUSE; public static ExecuteType getEnum(int value){ diff --git a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/enums/Status.java b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/enums/Status.java index 86b815cf9a..04ef02303d 100644 --- a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/enums/Status.java +++ b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/enums/Status.java @@ -196,6 +196,9 @@ public enum Status { QUERY_AUTHORIZED_AND_USER_CREATED_PROJECT_ERROR(10162, "query authorized and user created project error error", "查询授权的和用户创建的项目错误"), DELETE_PROCESS_DEFINITION_BY_ID_FAIL(10163,"delete process definition by id fail, for there are {0} process instances in executing using it", "删除工作流定义失败,有[{0}]个运行中的工作流实例正在使用"), CHECK_OS_TENANT_CODE_ERROR(10164, "Please enter the English os tenant code", "请输入英文操作系统租户"), + FORCE_TASK_SUCCESS_ERROR(10165, "force task success error", "强制成功任务实例错误"), + TASK_INSTANCE_STATE_OPERATION_ERROR(10166, "the status of task instance {0} is {1},Cannot perform force success operation", "任务实例[{0}]的状态是[{1}],无法执行强制成功操作"), + DATASOURCE_TYPE_NOT_EXIST(10167, "data source type not exist", "数据源类型不存在"), UDF_FUNCTION_NOT_EXIST(20001, "UDF function not found", "UDF函数不存在"), UDF_FUNCTION_EXISTS(20002, "UDF function already exists", "UDF函数已存在"), @@ -247,7 +250,7 @@ public enum Status { BATCH_DELETE_PROCESS_DEFINE_BY_IDS_ERROR(50026, "batch delete process definition by ids {0} error", "批量删除工作流定义[{0}]错误"), TENANT_NOT_SUITABLE(50027, "there is not any tenant suitable, please choose a tenant available.", "没有合适的租户,请选择可用的租户"), EXPORT_PROCESS_DEFINE_BY_ID_ERROR(50028, "export process definition by id error", "导出工作流定义错误"), - BATCH_EXPORT_PROCESS_DEFINE_BY_IDS_ERROR(50028, "batch export process definition by ids error", "批量导出工作流定义错误"), + BATCH_EXPORT_PROCESS_DEFINE_BY_IDS_ERROR(50028,"batch export process definition by ids error", "批量导出工作流定义错误"), IMPORT_PROCESS_DEFINE_ERROR(50029, "import process definition error", "导入工作流定义错误"), HDFS_NOT_STARTUP(60001, "hdfs not startup", "hdfs未启用"), @@ -273,13 +276,28 @@ public enum Status { QUEUE_COUNT_ERROR(90001, "queue count error", "查询队列数据错误"), KERBEROS_STARTUP_STATE(100001, "get kerberos startup state error", "获取kerberos启动状态错误"), + + //plugin + PLUGIN_NOT_A_UI_COMPONENT(110001, "query plugin error, this plugin has no UI component", "查询插件错误,此插件无UI组件"), + QUERY_PLUGINS_RESULT_IS_NULL(110002, "query plugins result is null", "查询插件为空"), + QUERY_PLUGINS_ERROR(110003, "query plugins error", "查询插件错误"), + QUERY_PLUGIN_DETAIL_RESULT_IS_NULL(110004, "query plugin detail result is null", "查询插件详情结果为空"), + + UPDATE_ALERT_PLUGIN_INSTANCE_ERROR(110005, "update alert plugin instance error", "更新告警组和告警组插件实例错误"), + DELETE_ALERT_PLUGIN_INSTANCE_ERROR(110006, "delete alert plugin instance error", "删除告警组和告警组插件实例错误"), + GET_ALERT_PLUGIN_INSTANCE_ERROR(110007, "get alert plugin instance error", "获取告警组和告警组插件实例错误"), + CREATE_ALERT_PLUGIN_INSTANCE_ERROR(110008, "create alert plugin instance error", "创建告警组和告警组插件实例错误"), + QUERY_ALL_ALERT_PLUGIN_INSTANCE_ERROR(110009, "query all alert plugin instance error", "查询所有告警实例失败"), + PLUGIN_INSTANCE_ALREADY_EXIT(110010,"plugin instance already exit","该告警插件实例已存在"), + LIST_PAGING_ALERT_PLUGIN_INSTANCE_ERROR(110011,"query plugin instance page error","分页查询告警实例失败"), + ; private final int code; private final String enMsg; private final String zhMsg; - private Status(int code, String enMsg, String zhMsg) { + Status(int code, String enMsg, String zhMsg) { this.code = code; this.enMsg = enMsg; this.zhMsg = zhMsg; diff --git a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/AlertGroupService.java b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/AlertGroupService.java index 72cbd50833..e1e63a623c 100644 --- a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/AlertGroupService.java +++ b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/AlertGroupService.java @@ -14,9 +14,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.dolphinscheduler.api.service; -import java.util.*; import org.apache.dolphinscheduler.api.enums.Status; import org.apache.dolphinscheduler.api.utils.PageInfo; import org.apache.dolphinscheduler.common.Constants; @@ -25,29 +25,33 @@ import org.apache.dolphinscheduler.common.utils.CollectionUtils; import org.apache.dolphinscheduler.common.utils.StringUtils; import org.apache.dolphinscheduler.dao.entity.AlertGroup; import org.apache.dolphinscheduler.dao.entity.User; -import org.apache.dolphinscheduler.dao.entity.UserAlertGroup; import org.apache.dolphinscheduler.dao.mapper.AlertGroupMapper; -import com.baomidou.mybatisplus.core.metadata.IPage; -import com.baomidou.mybatisplus.extension.plugins.pagination.Page; + +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; + /** * alert group service */ @Service -public class AlertGroupService extends BaseService{ +public class AlertGroupService extends BaseService { private static final Logger logger = LoggerFactory.getLogger(AlertGroupService.class); @Autowired private AlertGroupMapper alertGroupMapper; - @Autowired - private UserAlertGroupService userAlertGroupService; /** * query alert group list * @@ -75,15 +79,15 @@ public class AlertGroupService extends BaseService{ public Map listPaging(User loginUser, String searchVal, Integer pageNo, Integer pageSize) { Map result = new HashMap<>(); - if (checkAdmin(loginUser, result)) { + if (isNotAdmin(loginUser, result)) { return result; } Page page = new Page(pageNo, pageSize); IPage alertGroupIPage = alertGroupMapper.queryAlertGroupPage( - page, searchVal); + page, searchVal); PageInfo pageInfo = new PageInfo<>(pageNo, pageSize); - pageInfo.setTotalCount((int)alertGroupIPage.getTotal()); + pageInfo.setTotalCount((int) alertGroupIPage.getTotal()); pageInfo.setLists(alertGroupIPage.getRecords()); result.put(Constants.DATA_LIST, pageInfo); putMsg(result, Status.SUCCESS); @@ -96,14 +100,14 @@ public class AlertGroupService extends BaseService{ * * @param loginUser login user * @param groupName group name - * @param groupType group type * @param desc description + * @param alertInstanceIds alertInstanceIds * @return create result code */ - public Map createAlertgroup(User loginUser, String groupName, AlertType groupType, String desc) { + public Map createAlertgroup(User loginUser, String groupName, String desc, String alertInstanceIds) { Map result = new HashMap<>(); //only admin can operate - if (checkAdmin(loginUser, result)){ + if (isNotAdmin(loginUser, result)) { return result; } @@ -111,10 +115,11 @@ public class AlertGroupService extends BaseService{ Date now = new Date(); alertGroup.setGroupName(groupName); - alertGroup.setGroupType(groupType); + alertGroup.setAlertInstanceIds(alertInstanceIds); alertGroup.setDescription(desc); alertGroup.setCreateTime(now); alertGroup.setUpdateTime(now); + alertGroup.setCreateUserId(loginUser.getId()); // insert int insert = alertGroupMapper.insert(alertGroup); @@ -133,18 +138,17 @@ public class AlertGroupService extends BaseService{ * @param loginUser login user * @param id alert group id * @param groupName group name - * @param groupType group type * @param desc description + * @param alertInstanceIds alertInstanceIds * @return update result code */ - public Map updateAlertgroup(User loginUser, int id, String groupName, AlertType groupType, String desc) { + public Map updateAlertgroup(User loginUser, int id, String groupName, String desc, String alertInstanceIds) { Map result = new HashMap<>(); - if (checkAdmin(loginUser, result)){ + if (isNotAdmin(loginUser, result)) { return result; } - AlertGroup alertGroup = alertGroupMapper.selectById(id); if (alertGroup == null) { @@ -158,12 +162,10 @@ public class AlertGroupService extends BaseService{ if (StringUtils.isNotEmpty(groupName)) { alertGroup.setGroupName(groupName); } - - if (groupType != null) { - alertGroup.setGroupType(groupType); - } alertGroup.setDescription(desc); alertGroup.setUpdateTime(now); + alertGroup.setCreateUserId(loginUser.getId()); + alertGroup.setAlertInstanceIds(alertInstanceIds); // updateProcessInstance alertGroupMapper.updateById(alertGroup); putMsg(result, Status.SUCCESS); @@ -183,7 +185,7 @@ public class AlertGroupService extends BaseService{ result.put(Constants.STATUS, false); //only admin can operate - if (checkAdmin(loginUser, result)){ + if (isNotAdmin(loginUser, result)) { return result; } //check exist @@ -192,57 +194,11 @@ public class AlertGroupService extends BaseService{ putMsg(result, Status.ALERT_GROUP_NOT_EXIST); return result; } - - userAlertGroupService.deleteByAlertGroupId(id); alertGroupMapper.deleteById(id); putMsg(result, Status.SUCCESS); return result; } - - /** - * grant user - * - * @param loginUser login user - * @param alertgroupId alert group id - * @param userIds user id list - * @return grant result code - */ - public Map grantUser(User loginUser, int alertgroupId, String userIds) { - Map result = new HashMap<>(); - result.put(Constants.STATUS, false); - - //only admin can operate - if (checkAdmin(loginUser, result)){ - return result; - } - - userAlertGroupService.deleteByAlertGroupId(alertgroupId); - if (StringUtils.isEmpty(userIds)) { - putMsg(result, Status.SUCCESS); - return result; - } - - String[] userIdsArr = userIds.split(","); - Date now = new Date(); - List alertGroups = new ArrayList<>(userIds.length()); - for (String userId : userIdsArr) { - UserAlertGroup userAlertGroup = new UserAlertGroup(); - userAlertGroup.setAlertgroupId(alertgroupId); - userAlertGroup.setUserId(Integer.parseInt(userId)); - userAlertGroup.setCreateTime(now); - userAlertGroup.setUpdateTime(now); - alertGroups.add(userAlertGroup); - } - - if (CollectionUtils.isNotEmpty(alertGroups)) { - userAlertGroupService.saveBatch(alertGroups); - } - - putMsg(result, Status.SUCCESS); - return result; - } - /** * verify group name exists * diff --git a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/AlertPluginInstanceService.java b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/AlertPluginInstanceService.java new file mode 100644 index 0000000000..d526a41d99 --- /dev/null +++ b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/AlertPluginInstanceService.java @@ -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.api.service; + +import org.apache.dolphinscheduler.dao.entity.User; + +import java.util.Map; + +/** + * alert plugin instance service + */ +public interface AlertPluginInstanceService { + + /** + * creat alert plugin instance + * + * @param loginUser login user + * @param pluginDefineId plugin define id + * @param instanceName instance name + * @param pluginInstanceParams plugin instance params + * @return result + */ + Map create(User loginUser,int pluginDefineId,String instanceName,String pluginInstanceParams); + + /** + * update + * @param loginUser login user + * @param alertPluginInstanceId plugin instance id + * @param instanceName instance name + * @param pluginInstanceParams plugin instance params + * @return result + */ + Map update(User loginUser, int alertPluginInstanceId,String instanceName,String pluginInstanceParams); + + /** + * delete alert plugin instance + * + * @param loginUser login user + * @param id id + * @return result + */ + Map delete(User loginUser, int id); + + /** + * get alert plugin instance + * + * @param loginUser login user + * @param id get id + * @return alert plugin + */ + Map get(User loginUser, int id); + + /** + * queryAll + * + * @return alert plugins + */ + Map queryAll(); + + /** + * checkExistPluginInstanceName + * @param pluginName plugin name + * @return isExist + */ + boolean checkExistPluginInstanceName(String pluginName); + + /** + * queryPluginPage + * @param pageIndex page index + * @param pageSize page size + * @return plugins + */ + Map queryPluginPage(int pageIndex,int pageSize); +} diff --git a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/BaseService.java b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/BaseService.java index e9b25250a8..c61cd1eeb5 100644 --- a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/BaseService.java +++ b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/BaseService.java @@ -46,13 +46,13 @@ public class BaseService { } /** - * check admin + * isNotAdmin * * @param loginUser login user * @param result result code - * @return true if administrator, otherwise false + * @return true if not administrator, otherwise false */ - protected boolean checkAdmin(User loginUser, Map result) { + protected boolean isNotAdmin(User loginUser, Map result) { //only admin can operate if (!isAdmin(loginUser)) { putMsg(result, Status.USER_NO_OPERATION_PERM); diff --git a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/DataSourceService.java b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/DataSourceService.java index 1fa0494d13..58bb657c6f 100644 --- a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/DataSourceService.java +++ b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/DataSourceService.java @@ -14,12 +14,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.dolphinscheduler.api.service; -import com.baomidou.mybatisplus.core.metadata.IPage; -import com.baomidou.mybatisplus.extension.plugins.pagination.Page; -import com.fasterxml.jackson.databind.node.ObjectNode; -import org.apache.commons.lang.StringUtils; import org.apache.dolphinscheduler.api.enums.Status; import org.apache.dolphinscheduler.api.utils.PageInfo; import org.apache.dolphinscheduler.api.utils.Result; @@ -27,27 +24,36 @@ import org.apache.dolphinscheduler.common.Constants; import org.apache.dolphinscheduler.common.enums.DbConnectType; import org.apache.dolphinscheduler.common.enums.DbType; import org.apache.dolphinscheduler.common.utils.CommonUtils; -import org.apache.dolphinscheduler.common.utils.*; -import org.apache.dolphinscheduler.dao.datasource.*; +import org.apache.dolphinscheduler.common.utils.JSONUtils; +import org.apache.dolphinscheduler.common.utils.StringUtils; +import org.apache.dolphinscheduler.dao.datasource.BaseDataSource; +import org.apache.dolphinscheduler.dao.datasource.DataSourceFactory; +import org.apache.dolphinscheduler.dao.datasource.OracleDataSource; import org.apache.dolphinscheduler.dao.entity.DataSource; import org.apache.dolphinscheduler.dao.entity.Resource; import org.apache.dolphinscheduler.dao.entity.User; import org.apache.dolphinscheduler.dao.mapper.DataSourceMapper; import org.apache.dolphinscheduler.dao.mapper.DataSourceUserMapper; -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.security.UserGroupInformation; + +import java.sql.Connection; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import java.sql.Connection; -import java.sql.DriverManager; -import java.sql.SQLException; -import java.util.*; - -import static org.apache.dolphinscheduler.common.utils.PropertyUtils.getString; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.fasterxml.jackson.databind.node.ObjectNode; /** * datasource service @@ -67,11 +73,9 @@ public class DataSourceService extends BaseService { public static final String USER_NAME = "userName"; public static final String OTHER = "other"; - @Autowired private DataSourceMapper dataSourceMapper; - @Autowired private DataSourceUserMapper datasourceUserMapper; @@ -85,24 +89,16 @@ public class DataSourceService extends BaseService { * @param parameter datasource parameters * @return create result code */ - public Map createDataSource(User loginUser, String name, String desc, DbType type, String parameter) { + public Result createDataSource(User loginUser, String name, String desc, DbType type, String parameter) { - Map result = new HashMap<>(); + Result result = new Result<>(); // check name can use or not if (checkName(name)) { putMsg(result, Status.DATASOURCE_EXIST); return result; } - Boolean isConnection = checkConnection(type, parameter); - if (!isConnection) { - logger.info("connect failed, type:{}, parameter:{}", type, parameter); - putMsg(result, Status.DATASOURCE_CONNECT_FAILED); - return result; - } - - BaseDataSource datasource = DataSourceFactory.getDatasource(type, parameter); - if (datasource == null) { - putMsg(result, Status.REQUEST_PARAMS_NOT_VALID_ERROR, parameter); + Result isConnection = checkConnection(type, parameter); + if (Status.SUCCESS.getCode() != isConnection.getCode()) { return result; } @@ -125,7 +121,6 @@ public class DataSourceService extends BaseService { return result; } - /** * updateProcessInstance datasource * @@ -137,9 +132,9 @@ public class DataSourceService extends BaseService { * @param id data source id * @return update result code */ - public Map updateDataSource(int id, User loginUser, String name, String desc, DbType type, String parameter) { + public Result updateDataSource(int id, User loginUser, String name, String desc, DbType type, String parameter) { - Map result = new HashMap<>(); + Result result = new Result<>(); // determine whether the data source exists DataSource dataSource = dataSourceMapper.selectById(id); if (dataSource == null) { @@ -168,12 +163,11 @@ public class DataSourceService extends BaseService { // connectionParams json String connectionParams = paramObject.toString(); - Boolean isConnection = checkConnection(type, connectionParams); - if (!isConnection) { - logger.info("connect failed, type:{}, parameter:{}", type, parameter); - putMsg(result, Status.DATASOURCE_CONNECT_FAILED); + Result isConnection = checkConnection(type, parameter); + if (Status.SUCCESS.getCode() != isConnection.getCode()) { return result; } + Date now = new Date(); dataSource.setName(name.trim()); @@ -192,7 +186,6 @@ public class DataSourceService extends BaseService { return queryDataSource != null && queryDataSource.size() > 0; } - /** * updateProcessInstance datasource * @@ -360,8 +353,8 @@ public class DataSourceService extends BaseService { * @param name datasource name * @return true if data datasource not exists, otherwise return false */ - public Result verifyDataSourceName(String name) { - Result result = new Result(); + public Result verifyDataSourceName(String name) { + Result result = new Result<>(); List dataSourceList = dataSourceMapper.queryDataSourceByName(name); if (dataSourceList != null && dataSourceList.size() > 0) { logger.error("datasource name:{} has exist, can't create again.", name); @@ -373,77 +366,6 @@ public class DataSourceService extends BaseService { return result; } - /** - * get connection - * - * @param dbType datasource type - * @param parameter parameter - * @return connection for datasource - */ - private Connection getConnection(DbType dbType, String parameter) { - Connection connection = null; - BaseDataSource datasource = null; - try { - switch (dbType) { - case POSTGRESQL: - datasource = JSONUtils.parseObject(parameter, PostgreDataSource.class); - Class.forName(Constants.ORG_POSTGRESQL_DRIVER); - break; - case MYSQL: - datasource = JSONUtils.parseObject(parameter, MySQLDataSource.class); - Class.forName(Constants.COM_MYSQL_JDBC_DRIVER); - break; - case HIVE: - case SPARK: - if (CommonUtils.getKerberosStartupState()) { - System.setProperty(org.apache.dolphinscheduler.common.Constants.JAVA_SECURITY_KRB5_CONF, - getString(org.apache.dolphinscheduler.common.Constants.JAVA_SECURITY_KRB5_CONF_PATH)); - Configuration configuration = new Configuration(); - configuration.set(org.apache.dolphinscheduler.common.Constants.HADOOP_SECURITY_AUTHENTICATION, "kerberos"); - UserGroupInformation.setConfiguration(configuration); - UserGroupInformation.loginUserFromKeytab(getString(org.apache.dolphinscheduler.common.Constants.LOGIN_USER_KEY_TAB_USERNAME), - getString(org.apache.dolphinscheduler.common.Constants.LOGIN_USER_KEY_TAB_PATH)); - } - if (dbType == DbType.HIVE) { - datasource = JSONUtils.parseObject(parameter, HiveDataSource.class); - } else if (dbType == DbType.SPARK) { - datasource = JSONUtils.parseObject(parameter, SparkDataSource.class); - } - Class.forName(Constants.ORG_APACHE_HIVE_JDBC_HIVE_DRIVER); - break; - case CLICKHOUSE: - datasource = JSONUtils.parseObject(parameter, ClickHouseDataSource.class); - Class.forName(Constants.COM_CLICKHOUSE_JDBC_DRIVER); - break; - case ORACLE: - datasource = JSONUtils.parseObject(parameter, OracleDataSource.class); - Class.forName(Constants.COM_ORACLE_JDBC_DRIVER); - break; - case SQLSERVER: - datasource = JSONUtils.parseObject(parameter, SQLServerDataSource.class); - Class.forName(Constants.COM_SQLSERVER_JDBC_DRIVER); - break; - case DB2: - datasource = JSONUtils.parseObject(parameter, DB2ServerDataSource.class); - Class.forName(Constants.COM_DB2_JDBC_DRIVER); - break; - case PRESTO: - datasource = JSONUtils.parseObject(parameter, PrestoDataSource.class); - Class.forName(Constants.COM_PRESTO_JDBC_DRIVER); - break; - default: - break; - } - - if (datasource != null) { - connection = DriverManager.getConnection(datasource.getJdbcUrl(), datasource.getUser(), datasource.getPassword()); - } - } catch (Exception e) { - logger.error(e.getMessage(), e); - } - return connection; - } - /** * check connection * @@ -451,18 +373,24 @@ public class DataSourceService extends BaseService { * @param parameter data source parameters * @return true if connect successfully, otherwise false */ - public boolean checkConnection(DbType type, String parameter) { - Boolean isConnection = false; - Connection con = getConnection(type, parameter); - if (con != null) { - isConnection = true; - try { - con.close(); - } catch (SQLException e) { - logger.error("close connection fail at DataSourceService::checkConnection()", e); + public Result checkConnection(DbType type, String parameter) { + Result result = new Result<>(); + BaseDataSource datasource = DataSourceFactory.getDatasource(type, parameter); + if (datasource == null) { + putMsg(result, Status.DATASOURCE_TYPE_NOT_EXIST, type); + return result; + } + try (Connection connection = datasource.getConnection()) { + if (connection == null) { + putMsg(result, Status.CONNECTION_TEST_FAILURE); + return result; } + putMsg(result, Status.SUCCESS); + return result; + } catch (Exception e) { + logger.error("datasource test connection error, dbType:{}, jdbcUrl:{}, message:{}.", type, datasource.getJdbcUrl(), e.getMessage()); + return new Result<>(Status.CONNECTION_TEST_FAILURE.getCode(),e.getMessage()); } - return isConnection; } /** @@ -471,13 +399,14 @@ public class DataSourceService extends BaseService { * @param id datasource id * @return connect result code */ - public boolean connectionTest(int id) { + public Result connectionTest(int id) { DataSource dataSource = dataSourceMapper.selectById(id); - if (dataSource != null) { - return checkConnection(dataSource.getType(), dataSource.getConnectionParams()); - } else { - return false; + if (dataSource == null) { + Result result = new Result<>(); + putMsg(result, Status.RESOURCE_NOT_EXIST); + return result; } + return checkConnection(dataSource.getType(), dataSource.getConnectionParams()); } /** @@ -510,8 +439,8 @@ public class DataSourceService extends BaseService { parameterMap.put(Constants.ORACLE_DB_CONNECT_TYPE, connectType); } - if (CommonUtils.getKerberosStartupState() && - (type == DbType.HIVE || type == DbType.SPARK)) { + if (CommonUtils.getKerberosStartupState() + && (type == DbType.HIVE || type == DbType.SPARK)) { jdbcUrl += ";principal=" + principal; } @@ -535,8 +464,8 @@ public class DataSourceService extends BaseService { parameterMap.put(Constants.JDBC_URL, jdbcUrl); parameterMap.put(Constants.USER, userName); parameterMap.put(Constants.PASSWORD, CommonUtils.encodePassword(password)); - if (CommonUtils.getKerberosStartupState() && - (type == DbType.HIVE || type == DbType.SPARK)) { + if (CommonUtils.getKerberosStartupState() + && (type == DbType.HIVE || type == DbType.SPARK)) { parameterMap.put(Constants.PRINCIPAL, principal); } @@ -557,7 +486,6 @@ public class DataSourceService extends BaseService { } return JSONUtils.toJsonString(parameterMap); - } private String buildAddress(DbType type, String host, String port, DbConnectType connectType) { @@ -609,8 +537,8 @@ public class DataSourceService extends BaseService { * @return delete result code */ @Transactional(rollbackFor = RuntimeException.class) - public Result delete(User loginUser, int datasourceId) { - Result result = new Result(); + public Result delete(User loginUser, int datasourceId) { + Result result = new Result<>(); try { //query datasource by id DataSource dataSource = dataSourceMapper.selectById(datasourceId); @@ -673,7 +601,6 @@ public class DataSourceService extends BaseService { return result; } - /** * authorized datasource * @@ -695,7 +622,6 @@ public class DataSourceService extends BaseService { return result; } - /** * get host and port by address * diff --git a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/ExecutorService.java b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/ExecutorService.java index 7a0fd0f845..77be0a048c 100644 --- a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/ExecutorService.java +++ b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/ExecutorService.java @@ -21,6 +21,7 @@ import static org.apache.dolphinscheduler.common.Constants.CMDPARAM_COMPLEMENT_D import static org.apache.dolphinscheduler.common.Constants.CMDPARAM_COMPLEMENT_DATA_START_DATE; import static org.apache.dolphinscheduler.common.Constants.CMD_PARAM_RECOVER_PROCESS_ID_STRING; import static org.apache.dolphinscheduler.common.Constants.CMD_PARAM_START_NODE_NAMES; +import static org.apache.dolphinscheduler.common.Constants.CMD_PARAM_START_PARAMS; import static org.apache.dolphinscheduler.common.Constants.MAX_TASK_TIMEOUT; import org.apache.dolphinscheduler.api.enums.ExecuteType; @@ -106,12 +107,11 @@ public class ExecutorService extends BaseService { * @param taskDependType node dependency type * @param warningType warning type * @param warningGroupId notify group id - * @param receivers receivers - * @param receiversCc receivers cc * @param processInstancePriority process instance priority * @param workerGroup worker group name * @param runMode run mode * @param timeout timeout + * @param startParams the global param values which pass to new process instance * @return execute process instance code * @throws ParseException Parse Exception */ @@ -119,8 +119,9 @@ public class ExecutorService extends BaseService { int processDefinitionId, String cronTime, CommandType commandType, FailureStrategy failureStrategy, String startNodeList, TaskDependType taskDependType, WarningType warningType, int warningGroupId, - String receivers, String receiversCc, RunMode runMode, - Priority processInstancePriority, String workerGroup, Integer timeout) throws ParseException { + RunMode runMode, + Priority processInstancePriority, String workerGroup, Integer timeout, + Map startParams) throws ParseException { Map result = new HashMap<>(); // timeout is invalid if (timeout <= 0 || timeout > MAX_TASK_TIMEOUT) { @@ -157,13 +158,10 @@ public class ExecutorService extends BaseService { */ int create = this.createCommand(commandType, processDefinitionId, taskDependType, failureStrategy, startNodeList, cronTime, warningType, loginUser.getId(), - warningGroupId, runMode, processInstancePriority, workerGroup); + warningGroupId, runMode, processInstancePriority, workerGroup, startParams); + if (create > 0) { - /** - * according to the process definition ID updateProcessInstance and CC recipient - */ - processDefinition.setReceivers(receivers); - processDefinition.setReceiversCc(receiversCc); + processDefinition.setWarningGroupId(warningGroupId); processDefinitionMapper.updateById(processDefinition); putMsg(result, Status.SUCCESS); } else { @@ -445,42 +443,6 @@ public class ExecutorService extends BaseService { return result; } - /** - * query recipients and copyers by process definition id or processInstanceId - * - * @param processDefineId process definition id - * @param processInstanceId process instance id - * @return receivers cc list - */ - public Map getReceiverCc(Integer processDefineId, Integer processInstanceId) { - Map result = new HashMap<>(); - logger.info("processInstanceId {}", processInstanceId); - if (processDefineId == null && processInstanceId == null) { - throw new RuntimeException("You must set values for parameters processDefineId or processInstanceId"); - } - if (processDefineId == null && processInstanceId != null) { - ProcessInstance processInstance = processInstanceMapper.selectById(processInstanceId); - if (processInstance == null) { - throw new RuntimeException("processInstanceId is not exists"); - } - processDefineId = processInstance.getProcessDefinitionId(); - } - ProcessDefinition processDefinition = processDefinitionMapper.selectById(processDefineId); - if (processDefinition == null) { - throw new RuntimeException(String.format("processDefineId %d is not exists", processDefineId)); - } - - String receivers = processDefinition.getReceivers(); - String receiversCc = processDefinition.getReceiversCc(); - Map dataMap = new HashMap<>(); - dataMap.put(Constants.RECEIVERS, receivers); - dataMap.put(Constants.RECEIVERS_CC, receiversCc); - - result.put(Constants.DATA_LIST, dataMap); - putMsg(result, Status.SUCCESS); - return result; - } - /** * create command * @@ -502,7 +464,8 @@ public class ExecutorService extends BaseService { TaskDependType nodeDep, FailureStrategy failureStrategy, String startNodeList, String schedule, WarningType warningType, int executorId, int warningGroupId, - RunMode runMode, Priority processInstancePriority, String workerGroup) throws ParseException { + RunMode runMode, Priority processInstancePriority, String workerGroup, + Map startParams) throws ParseException { /** * instantiate command schedule instance @@ -529,6 +492,9 @@ public class ExecutorService extends BaseService { if (warningType != null) { command.setWarningType(warningType); } + if (startParams != null && startParams.size() > 0) { + cmdParam.put(CMD_PARAM_START_PARAMS, JSONUtils.toJsonString(startParams)); + } command.setCommandParam(JSONUtils.toJsonString(cmdParam)); command.setExecutorId(executorId); command.setWarningGroupId(warningGroupId); diff --git a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/ProcessDefinitionService.java b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/ProcessDefinitionService.java index 37d856059c..82651dde74 100644 --- a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/ProcessDefinitionService.java +++ b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/ProcessDefinitionService.java @@ -17,6 +17,7 @@ package org.apache.dolphinscheduler.api.service; +import org.apache.dolphinscheduler.common.enums.ReleaseState; import org.apache.dolphinscheduler.dao.entity.ProcessData; import org.apache.dolphinscheduler.dao.entity.User; @@ -190,7 +191,7 @@ public interface ProcessDefinitionService { Map releaseProcessDefinition(User loginUser, String projectName, int id, - int releaseState); + ReleaseState releaseState); /** * batch export process definition by ids diff --git a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/ProcessInstanceService.java b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/ProcessInstanceService.java index 739fa19735..1d6169b06e 100644 --- a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/ProcessInstanceService.java +++ b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/ProcessInstanceService.java @@ -66,11 +66,13 @@ import java.io.InputStreamReader; import java.nio.charset.StandardCharsets; import java.text.ParseException; import java.util.ArrayList; +import java.util.Collections; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Objects; +import java.util.Optional; import java.util.stream.Collectors; import org.slf4j.Logger; @@ -187,8 +189,7 @@ public class ProcessInstanceService extends BaseService { ProcessInstance processInstance = processService.findProcessInstanceDetailById(processId); ProcessDefinition processDefinition = processService.findProcessDefineById(processInstance.getProcessDefinitionId()); - processInstance.setReceivers(processDefinition.getReceivers()); - processInstance.setReceiversCc(processDefinition.getReceiversCc()); + processInstance.setWarningGroupId(processDefinition.getWarningGroupId()); result.put(DATA_LIST, processInstance); putMsg(result, Status.SUCCESS); @@ -449,7 +450,7 @@ public class ProcessInstanceService extends BaseService { originDefParams = JSONUtils.toJsonString(processData.getGlobalParams()); List globalParamList = processData.getGlobalParams(); - Map globalParamMap = globalParamList.stream().collect(Collectors.toMap(Property::getProp, Property::getValue)); + Map globalParamMap = Optional.ofNullable(globalParamList).orElse(Collections.emptyList()).stream().collect(Collectors.toMap(Property::getProp, Property::getValue)); globalParams = ParameterUtils.curingGlobalParams(globalParamMap, globalParamList, processInstance.getCmdTypeIfComplement(), schedule); timeout = processData.getTimeout(); diff --git a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/QueueService.java b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/QueueService.java index caffeabd5c..23de453e11 100644 --- a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/QueueService.java +++ b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/QueueService.java @@ -60,7 +60,7 @@ public class QueueService extends BaseService { */ public Map queryList(User loginUser) { Map result = new HashMap<>(); - if (checkAdmin(loginUser, result)) { + if (isNotAdmin(loginUser, result)) { return result; } @@ -75,14 +75,14 @@ public class QueueService extends BaseService { * query queue list paging * * @param loginUser login user - * @param pageNo page number + * @param pageNo page number * @param searchVal search value - * @param pageSize page size + * @param pageSize page size * @return queue list */ public Map queryList(User loginUser, String searchVal, Integer pageNo, Integer pageSize) { Map result = new HashMap<>(); - if (checkAdmin(loginUser, result)) { + if (isNotAdmin(loginUser, result)) { return result; } @@ -105,13 +105,13 @@ public class QueueService extends BaseService { * create queue * * @param loginUser login user - * @param queue queue + * @param queue queue * @param queueName queue name * @return create result */ public Map createQueue(User loginUser, String queue, String queueName) { Map result = new HashMap<>(); - if (checkAdmin(loginUser, result)) { + if (isNotAdmin(loginUser, result)) { return result; } @@ -153,14 +153,14 @@ public class QueueService extends BaseService { * update queue * * @param loginUser login user - * @param queue queue - * @param id queue id + * @param queue queue + * @param id queue id * @param queueName queue name * @return update result code */ public Map updateQueue(User loginUser, int id, String queue, String queueName) { Map result = new HashMap<>(); - if (checkAdmin(loginUser, result)) { + if (isNotAdmin(loginUser, result)) { return result; } diff --git a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/ResourcesService.java b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/ResourcesService.java index dffc55edfe..e7d8906f28 100644 --- a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/ResourcesService.java +++ b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/ResourcesService.java @@ -1158,20 +1158,20 @@ public class ResourcesService extends BaseService { public Map authorizeResourceTree(User loginUser, Integer userId) { Map result = new HashMap<>(); - if (checkAdmin(loginUser, result)) { + if (isNotAdmin(loginUser, result)) { return result; } List resourceList = resourcesMapper.queryResourceExceptUserId(userId); - List list ; + List list; if (CollectionUtils.isNotEmpty(resourceList)) { Visitor visitor = new ResourceTreeVisitor(resourceList); list = visitor.visit().getChildren(); - }else { + } else { list = new ArrayList<>(0); } result.put(Constants.DATA_LIST, list); - putMsg(result,Status.SUCCESS); + putMsg(result, Status.SUCCESS); return result; } @@ -1185,23 +1185,23 @@ public class ResourcesService extends BaseService { public Map unauthorizedFile(User loginUser, Integer userId) { Map result = new HashMap<>(); - if (checkAdmin(loginUser, result)) { + if (isNotAdmin(loginUser, result)) { return result; } List resourceList = resourcesMapper.queryResourceExceptUserId(userId); - List list ; + List list; if (resourceList != null && resourceList.size() > 0) { Set resourceSet = new HashSet<>(resourceList); List authedResourceList = resourcesMapper.queryAuthorizedResourceList(userId); getAuthorizedResourceList(resourceSet, authedResourceList); list = new ArrayList<>(resourceSet); - }else { + } else { list = new ArrayList<>(0); } Visitor visitor = new ResourceTreeVisitor(list); result.put(Constants.DATA_LIST, visitor.visit().getChildren()); - putMsg(result,Status.SUCCESS); + putMsg(result, Status.SUCCESS); return result; } @@ -1215,7 +1215,7 @@ public class ResourcesService extends BaseService { public Map unauthorizedUDFFunction(User loginUser, Integer userId) { Map result = new HashMap<>(5); //only admin can operate - if (checkAdmin(loginUser, result)) { + if (isNotAdmin(loginUser, result)) { return result; } @@ -1231,13 +1231,11 @@ public class ResourcesService extends BaseService { resultList = new ArrayList<>(udfFuncSet); } result.put(Constants.DATA_LIST, resultList); - putMsg(result,Status.SUCCESS); + putMsg(result, Status.SUCCESS); return result; } - - /** * authorized udf function * @@ -1247,12 +1245,12 @@ public class ResourcesService extends BaseService { */ public Map authorizedUDFFunction(User loginUser, Integer userId) { Map result = new HashMap<>(); - if (checkAdmin(loginUser, result)) { + if (isNotAdmin(loginUser, result)) { return result; } List udfFuncs = udfFunctionMapper.queryAuthedUdfFunc(userId); result.put(Constants.DATA_LIST, udfFuncs); - putMsg(result,Status.SUCCESS); + putMsg(result, Status.SUCCESS); return result; } @@ -1266,7 +1264,7 @@ public class ResourcesService extends BaseService { */ public Map authorizedFile(User loginUser, Integer userId) { Map result = new HashMap<>(5); - if (checkAdmin(loginUser, result)){ + if (isNotAdmin(loginUser, result)) { return result; } List authedResources = resourcesMapper.queryAuthorizedResourceList(userId); diff --git a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/SchedulerService.java b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/SchedulerService.java index 93fa14872a..55880ad63c 100644 --- a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/SchedulerService.java +++ b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/SchedulerService.java @@ -14,18 +14,22 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.dolphinscheduler.api.service; +package org.apache.dolphinscheduler.api.service; import org.apache.dolphinscheduler.api.dto.ScheduleParam; import org.apache.dolphinscheduler.api.enums.Status; import org.apache.dolphinscheduler.api.exceptions.ServiceException; import org.apache.dolphinscheduler.api.utils.PageInfo; import org.apache.dolphinscheduler.common.Constants; -import org.apache.dolphinscheduler.common.enums.*; +import org.apache.dolphinscheduler.common.enums.FailureStrategy; +import org.apache.dolphinscheduler.common.enums.Priority; +import org.apache.dolphinscheduler.common.enums.ReleaseState; +import org.apache.dolphinscheduler.common.enums.UserType; +import org.apache.dolphinscheduler.common.enums.WarningType; import org.apache.dolphinscheduler.common.model.Server; import org.apache.dolphinscheduler.common.utils.DateUtils; -import org.apache.dolphinscheduler.common.utils.*; +import org.apache.dolphinscheduler.common.utils.JSONUtils; import org.apache.dolphinscheduler.common.utils.StringUtils; import org.apache.dolphinscheduler.dao.entity.ProcessDefinition; import org.apache.dolphinscheduler.dao.entity.Project; @@ -34,12 +38,18 @@ import org.apache.dolphinscheduler.dao.entity.User; import org.apache.dolphinscheduler.dao.mapper.ProcessDefinitionMapper; import org.apache.dolphinscheduler.dao.mapper.ProjectMapper; import org.apache.dolphinscheduler.dao.mapper.ScheduleMapper; -import com.baomidou.mybatisplus.core.metadata.IPage; -import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import org.apache.dolphinscheduler.service.process.ProcessService; import org.apache.dolphinscheduler.service.quartz.ProcessScheduleJob; import org.apache.dolphinscheduler.service.quartz.QuartzExecutors; import org.apache.dolphinscheduler.service.quartz.cron.CronUtils; + +import java.text.ParseException; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + import org.quartz.CronExpression; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -47,8 +57,8 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import java.text.ParseException; -import java.util.*; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; /** * scheduler service @@ -86,12 +96,10 @@ public class SchedulerService extends BaseService { * @param projectName project name * @param processDefineId process definition id * @param schedule scheduler - * @param warningType warning type + * @param warningType warning type * @param warningGroupId warning group id * @param failureStrategy failure strategy * @param processInstancePriority process instance priority - * @param receivers receivers - * @param receiversCc receivers cc * @param workerGroup worker group * @return create result code */ @@ -102,12 +110,10 @@ public class SchedulerService extends BaseService { WarningType warningType, int warningGroupId, FailureStrategy failureStrategy, - String receivers, - String receiversCc, Priority processInstancePriority, String workerGroup) { - Map result = new HashMap(5); + Map result = new HashMap(); Project project = projectMapper.queryByName(projectName); @@ -132,9 +138,9 @@ public class SchedulerService extends BaseService { scheduleObj.setProcessDefinitionName(processDefinition.getName()); ScheduleParam scheduleParam = JSONUtils.parseObject(schedule, ScheduleParam.class); - if (DateUtils.differSec(scheduleParam.getStartTime(),scheduleParam.getEndTime()) == 0) { + if (DateUtils.differSec(scheduleParam.getStartTime(), scheduleParam.getEndTime()) == 0) { logger.warn("The start time must not be the same as the end"); - putMsg(result,Status.SCHEDULE_START_TIME_END_TIME_SAME); + putMsg(result, Status.SCHEDULE_START_TIME_END_TIME_SAME); return result; } scheduleObj.setStartTime(scheduleParam.getStartTime()); @@ -161,8 +167,7 @@ public class SchedulerService extends BaseService { /** * updateProcessInstance receivers and cc by process definition id */ - processDefinition.setReceivers(receivers); - processDefinition.setReceiversCc(receiversCc); + processDefinition.setWarningGroupId(warningGroupId); processDefinitionMapper.updateById(processDefinition); // return scheduler object with ID @@ -173,7 +178,6 @@ public class SchedulerService extends BaseService { return result; } - /** * updateProcessInstance schedule * @@ -186,8 +190,6 @@ public class SchedulerService extends BaseService { * @param failureStrategy failure strategy * @param workerGroup worker group * @param processInstancePriority process instance priority - * @param receiversCc receiver cc - * @param receivers receivers * @param scheduleStatus schedule status * @return update result code */ @@ -199,8 +201,6 @@ public class SchedulerService extends BaseService { WarningType warningType, int warningGroupId, FailureStrategy failureStrategy, - String receivers, - String receiversCc, ReleaseState scheduleStatus, Priority processInstancePriority, String workerGroup) { @@ -240,9 +240,9 @@ public class SchedulerService extends BaseService { // updateProcessInstance param if (StringUtils.isNotEmpty(scheduleExpression)) { ScheduleParam scheduleParam = JSONUtils.parseObject(scheduleExpression, ScheduleParam.class); - if (DateUtils.differSec(scheduleParam.getStartTime(),scheduleParam.getEndTime()) == 0) { + if (DateUtils.differSec(scheduleParam.getStartTime(), scheduleParam.getEndTime()) == 0) { logger.warn("The start time must not be the same as the end"); - putMsg(result,Status.SCHEDULE_START_TIME_END_TIME_SAME); + putMsg(result, Status.SCHEDULE_START_TIME_END_TIME_SAME); return result; } schedule.setStartTime(scheduleParam.getStartTime()); @@ -275,8 +275,8 @@ public class SchedulerService extends BaseService { /** * updateProcessInstance recipients and cc by process definition ID */ - processDefinition.setReceivers(receivers); - processDefinition.setReceiversCc(receiversCc); + processDefinition.setWarningGroupId(warningGroupId); + processDefinitionMapper.updateById(processDefinition); putMsg(result, Status.SUCCESS); @@ -290,7 +290,7 @@ public class SchedulerService extends BaseService { * @param loginUser login user * @param projectName project name * @param id scheduler id - * @param scheduleStatus schedule status + * @param scheduleStatus schedule status * @return publish result code */ @Transactional(rollbackFor = RuntimeException.class) @@ -316,7 +316,7 @@ public class SchedulerService extends BaseService { return result; } // check schedule release state - if(scheduleObj.getReleaseState() == scheduleStatus){ + if (scheduleObj.getReleaseState() == scheduleStatus) { logger.info("schedule release is already {},needn't to change schedule id: {} from {} to {}", scheduleObj.getReleaseState(), scheduleObj.getId(), scheduleObj.getReleaseState(), scheduleStatus); putMsg(result, Status.SCHEDULE_CRON_REALEASE_NEED_NOT_CHANGE, scheduleStatus); @@ -328,9 +328,9 @@ public class SchedulerService extends BaseService { return result; } - if(scheduleStatus == ReleaseState.ONLINE){ + if (scheduleStatus == ReleaseState.ONLINE) { // check process definition release state - if(processDefinition.getReleaseState() != ReleaseState.ONLINE){ + if (processDefinition.getReleaseState() != ReleaseState.ONLINE) { logger.info("not release process definition id: {} , name : {}", processDefinition.getId(), processDefinition.getName()); putMsg(result, Status.PROCESS_DEFINE_NOT_RELEASE, processDefinition.getName()); @@ -340,15 +340,15 @@ public class SchedulerService extends BaseService { List subProcessDefineIds = new ArrayList<>(); processService.recurseFindSubProcessId(scheduleObj.getProcessDefinitionId(), subProcessDefineIds); Integer[] idArray = subProcessDefineIds.toArray(new Integer[subProcessDefineIds.size()]); - if (subProcessDefineIds.size() > 0){ + if (subProcessDefineIds.size() > 0) { List subProcessDefinitionList = processDefinitionMapper.queryDefinitionListByIdList(idArray); - if (subProcessDefinitionList != null && subProcessDefinitionList.size() > 0){ - for (ProcessDefinition subProcessDefinition : subProcessDefinitionList){ + if (subProcessDefinitionList != null && subProcessDefinitionList.size() > 0) { + for (ProcessDefinition subProcessDefinition : subProcessDefinitionList) { /** * if there is no online process, exit directly */ - if (subProcessDefinition.getReleaseState() != ReleaseState.ONLINE){ + if (subProcessDefinition.getReleaseState() != ReleaseState.ONLINE) { logger.info("not release process definition id: {} , name : {}", subProcessDefinition.getId(), subProcessDefinition.getName()); putMsg(result, Status.PROCESS_DEFINE_NOT_RELEASE, subProcessDefinition.getId()); @@ -362,7 +362,6 @@ public class SchedulerService extends BaseService { // check master server exists List masterServers = monitorService.getServerListFromZK(true); - if (masterServers.size() == 0) { putMsg(result, Status.MASTER_NOT_EXISTS); return result; @@ -399,8 +398,6 @@ public class SchedulerService extends BaseService { return result; } - - /** * query schedule * @@ -408,7 +405,7 @@ public class SchedulerService extends BaseService { * @param projectName project name * @param processDefineId process definition id * @param pageNo page number - * @param pageSize page size + * @param pageSize page size * @param searchVal search value * @return schedule list page */ @@ -434,9 +431,8 @@ public class SchedulerService extends BaseService { page, processDefineId, searchVal ); - PageInfo pageInfo = new PageInfo(pageNo, pageSize); - pageInfo.setTotalCount((int)scheduleIPage.getTotal()); + pageInfo.setTotalCount((int) scheduleIPage.getTotal()); pageInfo.setLists(scheduleIPage.getRecords()); result.put(Constants.DATA_LIST, pageInfo); putMsg(result, Status.SUCCESS); @@ -500,8 +496,8 @@ public class SchedulerService extends BaseService { String jobName = QuartzExecutors.buildJobName(scheduleId); String jobGroupName = QuartzExecutors.buildJobGroupName(projectId); - if(!QuartzExecutors.getInstance().deleteJob(jobName, jobGroupName)){ - logger.warn("set offline failure:projectId:{},scheduleId:{}",projectId,scheduleId); + if (!QuartzExecutors.getInstance().deleteJob(jobName, jobGroupName)) { + logger.warn("set offline failure:projectId:{},scheduleId:{}", projectId, scheduleId); throw new ServiceException("set offline failure"); } @@ -551,19 +547,18 @@ public class SchedulerService extends BaseService { } // Determine if the login user is the owner of the schedule - if (loginUser.getId() != schedule.getUserId() && - loginUser.getUserType() != UserType.ADMIN_USER) { + if (loginUser.getId() != schedule.getUserId() + && loginUser.getUserType() != UserType.ADMIN_USER) { putMsg(result, Status.USER_NO_OPERATION_PERM); return result; } // check schedule is already online - if(schedule.getReleaseState() == ReleaseState.ONLINE){ - putMsg(result, Status.SCHEDULE_CRON_STATE_ONLINE,schedule.getId()); + if (schedule.getReleaseState() == ReleaseState.ONLINE) { + putMsg(result, Status.SCHEDULE_CRON_STATE_ONLINE, schedule.getId()); return result; } - int delete = scheduleMapper.deleteById(scheduleId); if (delete > 0) { @@ -582,7 +577,7 @@ public class SchedulerService extends BaseService { * @param schedule schedule expression * @return the next five fire time */ - public Map previewSchedule(User loginUser, String projectName, String schedule) { + public Map previewSchedule(User loginUser, String projectName, String schedule) { Map result = new HashMap<>(); CronExpression cronExpression; ScheduleParam scheduleParam = JSONUtils.parseObject(schedule, ScheduleParam.class); @@ -593,11 +588,11 @@ public class SchedulerService extends BaseService { try { cronExpression = CronUtils.parse2CronExpression(scheduleParam.getCrontab()); } catch (ParseException e) { - logger.error(e.getMessage(),e); - putMsg(result,Status.PARSE_TO_CRON_EXPRESSION_ERROR); + logger.error(e.getMessage(), e); + putMsg(result, Status.PARSE_TO_CRON_EXPRESSION_ERROR); return result; } - List selfFireDateList = CronUtils.getSelfFireDateList(startTime, endTime,cronExpression,Constants.PREVIEW_SCHEDULE_EXECUTE_COUNT); + List selfFireDateList = CronUtils.getSelfFireDateList(startTime, endTime, cronExpression, Constants.PREVIEW_SCHEDULE_EXECUTE_COUNT); result.put(Constants.DATA_LIST, selfFireDateList.stream().map(t -> DateUtils.dateToString(t))); putMsg(result, Status.SUCCESS); return result; diff --git a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/TaskInstanceService.java b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/TaskInstanceService.java index 012af8fd38..dd2caff3b6 100644 --- a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/TaskInstanceService.java +++ b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/TaskInstanceService.java @@ -145,6 +145,50 @@ public class TaskInstanceService extends BaseService { return result; } + /** + * change one task instance's state from failure to forced success + * + * @param loginUser login user + * @param projectName project name + * @param taskInstanceId task instance id + * @return the result code and msg + */ + public Map forceTaskSuccess(User loginUser, String projectName, Integer taskInstanceId) { + Map result = new HashMap<>(5); + Project project = projectMapper.queryByName(projectName); + + // check user auth + Map checkResult = projectService.checkProjectAndAuth(loginUser, project, projectName); + Status status = (Status) checkResult.get(Constants.STATUS); + if (status != Status.SUCCESS) { + return checkResult; + } + + // check whether the task instance can be found + TaskInstance task = taskInstanceMapper.selectById(taskInstanceId); + if (task == null) { + putMsg(result, Status.TASK_INSTANCE_NOT_FOUND); + return result; + } + + // check whether the task instance state type is failure + if (!task.getState().typeIsFailure()) { + putMsg(result, Status.TASK_INSTANCE_STATE_OPERATION_ERROR, taskInstanceId, task.getState().toString()); + return result; + } + + // change the state of the task instance + task.setState(ExecutionStatus.FORCED_SUCCESS); + int changedNum = taskInstanceMapper.updateById(task); + if (changedNum > 0) { + putMsg(result, Status.SUCCESS); + } else { + putMsg(result, Status.FORCE_TASK_SUCCESS_ERROR); + } + + return result; + } + /*** * generate {@link org.apache.dolphinscheduler.api.enums.Status#REQUEST_PARAMS_NOT_VALID_ERROR} res with param name * @param result exist result map diff --git a/dolphinscheduler-common/src/main/java/org/apache/dolphinscheduler/common/plugin/PluginManager.java b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/UiPluginService.java similarity index 74% rename from dolphinscheduler-common/src/main/java/org/apache/dolphinscheduler/common/plugin/PluginManager.java rename to dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/UiPluginService.java index f8078841e4..102d927673 100644 --- a/dolphinscheduler-common/src/main/java/org/apache/dolphinscheduler/common/plugin/PluginManager.java +++ b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/UiPluginService.java @@ -14,20 +14,20 @@ * 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; +package org.apache.dolphinscheduler.api.service; + +import org.apache.dolphinscheduler.common.enums.PluginType; import java.util.Map; /** - * PluginManager + * UiPluginService */ -public interface PluginManager { +public interface UiPluginService { - AlertPlugin findOne(String name); + Map queryUiPluginsByType(PluginType pluginType); - Map findAll(); + Map queryUiPluginDetailById(int id); - void addPlugin(AlertPlugin plugin); } diff --git a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/WorkerGroupService.java b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/WorkerGroupService.java index 3f21679b34..83cbd197cd 100644 --- a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/WorkerGroupService.java +++ b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/WorkerGroupService.java @@ -70,7 +70,7 @@ public class WorkerGroupService extends BaseService { Integer toIndex = (pageNo - 1) * pageSize + pageSize; Map result = new HashMap<>(); - if (checkAdmin(loginUser, result)) { + if (isNotAdmin(loginUser, result)) { return result; } diff --git a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/AlertPluginInstanceServiceImpl.java b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/AlertPluginInstanceServiceImpl.java new file mode 100644 index 0000000000..8004a90fae --- /dev/null +++ b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/AlertPluginInstanceServiceImpl.java @@ -0,0 +1,208 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.dolphinscheduler.api.service.impl; + +import org.apache.dolphinscheduler.api.enums.Status; +import org.apache.dolphinscheduler.api.service.AlertPluginInstanceService; +import org.apache.dolphinscheduler.api.service.BaseService; +import org.apache.dolphinscheduler.api.utils.PageInfo; +import org.apache.dolphinscheduler.api.vo.AlertPluginInstanceVO; +import org.apache.dolphinscheduler.common.Constants; +import org.apache.dolphinscheduler.common.utils.CollectionUtils; +import org.apache.dolphinscheduler.dao.entity.AlertPluginInstance; +import org.apache.dolphinscheduler.dao.entity.PluginDefine; +import org.apache.dolphinscheduler.dao.entity.User; +import org.apache.dolphinscheduler.dao.mapper.AlertPluginInstanceMapper; +import org.apache.dolphinscheduler.dao.mapper.PluginDefineMapper; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Service; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; + +/** + * alert plugin instance service impl + */ +@Service +@Lazy +public class AlertPluginInstanceServiceImpl extends BaseService implements AlertPluginInstanceService { + + @Autowired + private AlertPluginInstanceMapper alertPluginInstanceMapper; + + @Autowired + private PluginDefineMapper pluginDefineMapper; + + /** + * creat alert plugin instance + * + * @param loginUser login user + * @param pluginDefineId plugin define id + * @param instanceName instance name + * @param pluginInstanceParams plugin instance params + */ + @Override + public Map create(User loginUser, int pluginDefineId, String instanceName, String pluginInstanceParams) { + AlertPluginInstance alertPluginInstance = new AlertPluginInstance(); + alertPluginInstance.setPluginInstanceParams(pluginInstanceParams); + alertPluginInstance.setInstanceName(instanceName); + alertPluginInstance.setPluginDefineId(pluginDefineId); + + Map result = new HashMap<>(); + + if (CollectionUtils.isNotEmpty(alertPluginInstanceMapper.queryByInstanceName(alertPluginInstance.getInstanceName()))) { + putMsg(result, Status.PLUGIN_INSTANCE_ALREADY_EXIT); + return result; + } + + int i = alertPluginInstanceMapper.insert(alertPluginInstance); + + if (i > 0) { + putMsg(result, Status.SUCCESS); + } + return result; + } + + /** + * update alert plugin instance + * + * @param loginUser login user + * @param pluginInstanceId plugin instance id + * @param instanceName instance name + * @param pluginInstanceParams plugin instance params + */ + @Override + public Map update(User loginUser, int pluginInstanceId, String instanceName, String pluginInstanceParams) { + + AlertPluginInstance alertPluginInstance = new AlertPluginInstance(); + alertPluginInstance.setPluginInstanceParams(pluginInstanceParams); + alertPluginInstance.setInstanceName(instanceName); + alertPluginInstance.setId(pluginInstanceId); + Map result = new HashMap<>(); + int i = alertPluginInstanceMapper.updateById(alertPluginInstance); + + if (i > 0) { + putMsg(result, Status.SUCCESS); + } + + return result; + } + + /** + * delete alert plugin instance + * + * @param loginUser login user + * @param id id + * @return result + */ + @Override + public Map delete(User loginUser, int id) { + Map result = new HashMap<>(); + int i = alertPluginInstanceMapper.deleteById(id); + if (i > 0) { + putMsg(result, Status.SUCCESS); + } + + return result; + } + + /** + * get alert plugin instance + * + * @param loginUser login user + * @param id get id + * @return alert plugin + */ + @Override + public Map get(User loginUser, int id) { + Map result = new HashMap<>(); + AlertPluginInstance alertPluginInstance = alertPluginInstanceMapper.selectById(id); + + if (null != alertPluginInstance) { + putMsg(result, Status.SUCCESS); + result.put(Constants.DATA_LIST, alertPluginInstance); + } + + return result; + } + + @Override + public Map queryAll() { + Map result = new HashMap<>(); + List alertPluginInstances = alertPluginInstanceMapper.queryAllAlertPluginInstanceList(); + List alertPluginInstanceVOS = buildPluginInstanceVOList(alertPluginInstances); + if (null != alertPluginInstances) { + putMsg(result, Status.SUCCESS); + result.put(Constants.DATA_LIST, alertPluginInstanceVOS); + } + return result; + } + + @Override + public boolean checkExistPluginInstanceName(String pluginInstanceName) { + return CollectionUtils.isNotEmpty(alertPluginInstanceMapper.queryByInstanceName(pluginInstanceName)); + } + + @Override + public Map queryPluginPage(int pageIndex, int pageSize) { + IPage pluginInstanceIPage = new Page<>(pageIndex, pageSize); + pluginInstanceIPage = alertPluginInstanceMapper.selectPage(pluginInstanceIPage, null); + + PageInfo pageInfo = new PageInfo<>(pageIndex, pageSize); + pageInfo.setTotalCount((int) pluginInstanceIPage.getTotal()); + pageInfo.setLists(buildPluginInstanceVOList(pluginInstanceIPage.getRecords())); + Map result = new HashMap<>(); + result.put(Constants.DATA_LIST, pageInfo); + putMsg(result, Status.SUCCESS); + return result; + } + + private List buildPluginInstanceVOList(List alertPluginInstances) { + if (CollectionUtils.isEmpty(alertPluginInstances)) { + return null; + } + List pluginDefineList = pluginDefineMapper.queryAllPluginDefineList(); + if (CollectionUtils.isEmpty(pluginDefineList)) { + return null; + } + Map pluginDefineMap = pluginDefineList.stream().collect(Collectors.toMap(PluginDefine::getId, PluginDefine::getPluginName)); + List alertPluginInstanceVOS = new ArrayList<>(); + alertPluginInstances.forEach(alertPluginInstance -> { + AlertPluginInstanceVO alertPluginInstanceVO = new AlertPluginInstanceVO(); + alertPluginInstanceVO.setAlertPluginName(pluginDefineMap.get(alertPluginInstance.getPluginDefineId())); + alertPluginInstanceVO.setCreateTime(alertPluginInstance.getCreateTime()); + alertPluginInstanceVO.setUpdateTime(alertPluginInstance.getUpdateTime()); + alertPluginInstanceVO.setPluginDefineId(alertPluginInstance.getPluginDefineId()); + alertPluginInstanceVO.setInstanceName(alertPluginInstance.getInstanceName()); + alertPluginInstanceVO.setId(alertPluginInstance.getId()); + //todo List pages do not recommend returning this parameter + alertPluginInstanceVO.setPluginInstanceParams(alertPluginInstance.getPluginInstanceParams()); + alertPluginInstanceVOS.add(alertPluginInstanceVO); + }); + return alertPluginInstanceVOS; + + } +} diff --git a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/DataAnalysisServiceImpl.java b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/DataAnalysisServiceImpl.java index c9560e1c50..7254fc1a88 100644 --- a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/DataAnalysisServiceImpl.java +++ b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/DataAnalysisServiceImpl.java @@ -25,6 +25,7 @@ import org.apache.dolphinscheduler.api.service.DataAnalysisService; import org.apache.dolphinscheduler.api.service.ProjectService; import org.apache.dolphinscheduler.common.Constants; import org.apache.dolphinscheduler.common.enums.CommandType; +import org.apache.dolphinscheduler.common.enums.ExecutionStatus; import org.apache.dolphinscheduler.common.enums.UserType; import org.apache.dolphinscheduler.common.utils.DateUtils; import org.apache.dolphinscheduler.common.utils.StringUtils; @@ -114,12 +115,17 @@ public class DataAnalysisServiceImpl extends BaseService implements DataAnalysis * @return process instance state count data */ public Map countProcessInstanceStateByProject(User loginUser, int projectId, String startDate, String endDate) { - return this.countStateByProject( + Map result = this.countStateByProject( loginUser, projectId, startDate, endDate, (start, end, projectIds) -> this.processInstanceMapper.countInstanceStateByUser(start, end, projectIds)); + // process state count needs to remove state of forced success + if (result.containsKey(Constants.STATUS) && result.get(Constants.STATUS).equals(Status.SUCCESS)) { + ((TaskCountDto)result.get(Constants.DATA_LIST)).removeStateFromCountList(ExecutionStatus.FORCED_SUCCESS); + } + return result; } private Map countStateByProject(User loginUser, int projectId, String startDate, String endDate diff --git a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/ProcessDefinitionServiceImpl.java b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/ProcessDefinitionServiceImpl.java index 245d33bb19..9810674863 100644 --- a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/ProcessDefinitionServiceImpl.java +++ b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/ProcessDefinitionServiceImpl.java @@ -157,7 +157,6 @@ public class ProcessDefinitionServiceImpl extends BaseService implements * @param locations locations for nodes * @param connects connects for nodes * @return create result code - * @throws JsonProcessingException JsonProcessingException */ @Override public Map createProcessDefinition(User loginUser, @@ -221,9 +220,8 @@ public class ProcessDefinitionServiceImpl extends BaseService implements processDefineMapper.updateVersionByProcessDefinitionId(processDefine.getId(), version); // return processDefinition object with ID - result.put(Constants.DATA_LIST, processDefineMapper.selectById(processDefine.getId())); + result.put(Constants.DATA_LIST, processDefine.getId()); putMsg(result, Status.SUCCESS); - result.put(PROCESSDEFINITIONID, processDefine.getId()); return result; } @@ -585,7 +583,7 @@ public class ProcessDefinitionServiceImpl extends BaseService implements */ @Override @Transactional(rollbackFor = RuntimeException.class) - public Map releaseProcessDefinition(User loginUser, String projectName, int id, int releaseState) { + public Map releaseProcessDefinition(User loginUser, String projectName, int id, ReleaseState releaseState) { HashMap result = new HashMap<>(); Project project = projectMapper.queryByName(projectName); @@ -595,17 +593,15 @@ public class ProcessDefinitionServiceImpl extends BaseService implements return checkResult; } - ReleaseState state = ReleaseState.getEnum(releaseState); - // check state - if (null == state) { + if (null == releaseState) { putMsg(result, Status.REQUEST_PARAMS_NOT_VALID_ERROR, RELEASESTATE); return result; } ProcessDefinition processDefinition = processDefineMapper.selectById(id); - switch (state) { + switch (releaseState) { case ONLINE: // To check resources whether they are already cancel authorized or deleted String resourceIds = processDefinition.getResourceIds(); @@ -621,11 +617,11 @@ public class ProcessDefinitionServiceImpl extends BaseService implements } } - processDefinition.setReleaseState(state); + processDefinition.setReleaseState(releaseState); processDefineMapper.updateById(processDefinition); break; case OFFLINE: - processDefinition.setReleaseState(state); + processDefinition.setReleaseState(releaseState); processDefineMapper.updateById(processDefinition); List scheduleList = scheduleMapper.selectAllByProcessDefineArray( new int[]{processDefinition.getId()} @@ -888,8 +884,8 @@ public class ProcessDefinitionServiceImpl extends BaseService implements //create process definition Integer processDefinitionId = - Objects.isNull(createProcessResult.get(PROCESSDEFINITIONID)) - ? null : Integer.parseInt(createProcessResult.get(PROCESSDEFINITIONID).toString()); + Objects.isNull(createProcessResult.get(Constants.DATA_LIST)) + ? null : Integer.parseInt(createProcessResult.get(Constants.DATA_LIST).toString()); //scheduler param return getImportProcessScheduleResult(loginUser, @@ -1131,8 +1127,7 @@ public class ProcessDefinitionServiceImpl extends BaseService implements processDefine.setCreateTime(now); processDefine.setUpdateTime(now); processDefine.setFlag(subProcess.getFlag()); - processDefine.setReceivers(subProcess.getReceivers()); - processDefine.setReceiversCc(subProcess.getReceiversCc()); + processDefine.setWarningGroupId(subProcess.getWarningGroupId()); processDefineMapper.insert(processDefine); logger.info("create sub process, project: {}, process name: {}", targetProject.getName(), processDefine.getName()); @@ -1516,41 +1511,6 @@ public class ProcessDefinitionServiceImpl extends BaseService implements } } - /** - * copy process definition - * - * @param loginUser login user - * @param projectName project name - * @param processId process definition id - * @return copy result code - */ - public Map copyProcessDefinition(User loginUser, String projectName, Integer processId) { - - Map result = new HashMap<>(5); - Project project = projectMapper.queryByName(projectName); - - Map checkResult = projectService.checkProjectAndAuth(loginUser, project, projectName); - Status resultStatus = (Status) checkResult.get(Constants.STATUS); - if (resultStatus != Status.SUCCESS) { - return checkResult; - } - - ProcessDefinition processDefinition = processDefineMapper.selectById(processId); - if (processDefinition == null) { - putMsg(result, Status.PROCESS_DEFINE_NOT_EXIST, processId); - return result; - } else { - return createProcessDefinition( - loginUser, - projectName, - processDefinition.getName() + "_copy_" + System.currentTimeMillis(), - processDefinition.getProcessDefinitionJson(), - processDefinition.getDescription(), - processDefinition.getLocations(), - processDefinition.getConnects()); - } - } - /** * batch copy process definition * @@ -1695,8 +1655,7 @@ public class ProcessDefinitionServiceImpl extends BaseService implements processDefinition.setTimeout(processDefinitionVersion.getTimeout()); processDefinition.setGlobalParams(processDefinitionVersion.getGlobalParams()); processDefinition.setUpdateTime(new Date()); - processDefinition.setReceivers(processDefinitionVersion.getReceivers()); - processDefinition.setReceiversCc(processDefinitionVersion.getReceiversCc()); + processDefinition.setWarningGroupId(processDefinitionVersion.getWarningGroupId()); processDefinition.setResourceIds(processDefinitionVersion.getResourceIds()); if (processDefineMapper.updateById(processDefinition) > 0) { diff --git a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/ProcessDefinitionVersionServiceImpl.java b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/ProcessDefinitionVersionServiceImpl.java index 6364242190..08cedfee15 100644 --- a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/ProcessDefinitionVersionServiceImpl.java +++ b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/ProcessDefinitionVersionServiceImpl.java @@ -66,18 +66,17 @@ public class ProcessDefinitionVersionServiceImpl extends BaseService implements long version = this.queryMaxVersionByProcessDefinitionId(processDefinition.getId()) + 1; ProcessDefinitionVersion processDefinitionVersion = ProcessDefinitionVersion - .newBuilder() - .processDefinitionId(processDefinition.getId()) - .version(version) - .processDefinitionJson(processDefinition.getProcessDefinitionJson()) - .description(processDefinition.getDescription()) - .locations(processDefinition.getLocations()) - .connects(processDefinition.getConnects()) - .timeout(processDefinition.getTimeout()) - .globalParams(processDefinition.getGlobalParams()) - .createTime(processDefinition.getUpdateTime()) - .receivers(processDefinition.getReceivers()) - .receiversCc(processDefinition.getReceiversCc()) + .newBuilder() + .processDefinitionId(processDefinition.getId()) + .version(version) + .processDefinitionJson(processDefinition.getProcessDefinitionJson()) + .description(processDefinition.getDescription()) + .locations(processDefinition.getLocations()) + .connects(processDefinition.getConnects()) + .timeout(processDefinition.getTimeout()) + .globalParams(processDefinition.getGlobalParams()) + .createTime(processDefinition.getUpdateTime()) + .warningGroupId(processDefinition.getWarningGroupId()) .resourceIds(processDefinition.getResourceIds()) .build(); diff --git a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/ProjectServiceImpl.java b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/ProjectServiceImpl.java index fd47342c12..9241df6d71 100644 --- a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/ProjectServiceImpl.java +++ b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/ProjectServiceImpl.java @@ -24,6 +24,7 @@ import org.apache.dolphinscheduler.api.service.ProjectService; import org.apache.dolphinscheduler.api.utils.PageInfo; import org.apache.dolphinscheduler.common.Constants; import org.apache.dolphinscheduler.common.enums.UserType; +import org.apache.dolphinscheduler.common.utils.CollectionUtils; import org.apache.dolphinscheduler.dao.entity.ProcessDefinition; import org.apache.dolphinscheduler.dao.entity.Project; import org.apache.dolphinscheduler.dao.entity.ProjectUser; @@ -293,7 +294,7 @@ public class ProjectServiceImpl extends BaseService implements ProjectService { */ public Map queryUnauthorizedProject(User loginUser, Integer userId) { Map result = new HashMap<>(); - if (checkAdmin(loginUser, result)) { + if (isNotAdmin(loginUser, result)) { return result; } /** @@ -344,7 +345,7 @@ public class ProjectServiceImpl extends BaseService implements ProjectService { public Map queryAuthorizedProject(User loginUser, Integer userId) { Map result = new HashMap<>(); - if (checkAdmin(loginUser, result)) { + if (isNotAdmin(loginUser, result)) { return result; } @@ -364,7 +365,7 @@ public class ProjectServiceImpl extends BaseService implements ProjectService { public Map queryProjectCreatedByUser(User loginUser) { Map result = new HashMap<>(); - if (checkAdmin(loginUser, result)) { + if (isNotAdmin(loginUser, result)) { return result; } @@ -442,21 +443,13 @@ public class ProjectServiceImpl extends BaseService implements ProjectService { */ public Map queryAllProjectList() { Map result = new HashMap<>(); - List projects = projectMapper.selectList(null); - List processDefinitions = processDefinitionMapper.selectList(null); - if (projects != null) { - Set set = new HashSet<>(); - for (ProcessDefinition processDefinition : processDefinitions) { - set.add(processDefinition.getProjectId()); - } - List tempDeletelist = new ArrayList<>(); - for (Project project : projects) { - if (!set.contains(project.getId())) { - tempDeletelist.add(project); - } - } - projects.removeAll(tempDeletelist); + List projects = new ArrayList<>(); + + List projectIds = processDefinitionMapper.listProjectIds(); + if (CollectionUtils.isNotEmpty(projectIds)) { + projects = projectMapper.selectBatchIds(projectIds); } + result.put(Constants.DATA_LIST, projects); putMsg(result, Status.SUCCESS); return result; diff --git a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/TenantServiceImpl.java b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/TenantServiceImpl.java index d27ce47122..8aafe9102e 100644 --- a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/TenantServiceImpl.java +++ b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/TenantServiceImpl.java @@ -89,7 +89,7 @@ public class TenantServiceImpl extends BaseService implements TenantService { Map result = new HashMap<>(5); result.put(Constants.STATUS, false); - if (checkAdmin(loginUser, result)) { + if (isNotAdmin(loginUser, result)) { return result; } @@ -134,14 +134,14 @@ public class TenantServiceImpl extends BaseService implements TenantService { * * @param loginUser login user * @param searchVal search value - * @param pageNo page number - * @param pageSize page size + * @param pageNo page number + * @param pageSize page size * @return tenant list page */ public Map queryTenantList(User loginUser, String searchVal, Integer pageNo, Integer pageSize) { Map result = new HashMap<>(5); - if (checkAdmin(loginUser, result)) { + if (isNotAdmin(loginUser, result)) { return result; } @@ -174,7 +174,7 @@ public class TenantServiceImpl extends BaseService implements TenantService { Map result = new HashMap<>(5); result.put(Constants.STATUS, false); - if (checkAdmin(loginUser, result)) { + if (isNotAdmin(loginUser, result)) { return result; } @@ -227,7 +227,7 @@ public class TenantServiceImpl extends BaseService implements TenantService { * delete tenant * * @param loginUser login user - * @param id tenant id + * @param id tenant id * @return delete result code * @throws Exception exception */ @@ -235,7 +235,7 @@ public class TenantServiceImpl extends BaseService implements TenantService { public Map deleteTenantById(User loginUser, int id) throws Exception { Map result = new HashMap<>(5); - if (checkAdmin(loginUser, result)) { + if (isNotAdmin(loginUser, result)) { return result; } diff --git a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/UiPluginServiceImpl.java b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/UiPluginServiceImpl.java new file mode 100644 index 0000000000..0c3cb5dfdb --- /dev/null +++ b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/UiPluginServiceImpl.java @@ -0,0 +1,85 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.dolphinscheduler.api.service.impl; + +import org.apache.dolphinscheduler.api.enums.Status; +import org.apache.dolphinscheduler.api.service.BaseService; +import org.apache.dolphinscheduler.api.service.UiPluginService; +import org.apache.dolphinscheduler.common.Constants; +import org.apache.dolphinscheduler.common.enums.PluginType; +import org.apache.dolphinscheduler.common.utils.CollectionUtils; +import org.apache.dolphinscheduler.dao.entity.PluginDefine; +import org.apache.dolphinscheduler.dao.mapper.PluginDefineMapper; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +/** + * UiPluginServiceImpl + */ +@Service +public class UiPluginServiceImpl extends BaseService implements UiPluginService { + + @Autowired + PluginDefineMapper pluginDefineMapper; + + private static final String LANGUAGE_REGEX = "\"([^\"]*)\""; + + private static final String LANGUAGE_SYMBOL = "$t"; + + private static final String ESCAPE_SYMBOL = "\\"; + + @Override + public Map queryUiPluginsByType(PluginType pluginType) { + Map result = new HashMap<>(); + if (!pluginType.getHasUi()) { + putMsg(result, Status.PLUGIN_NOT_A_UI_COMPONENT); + return result; + } + List pluginDefines = pluginDefineMapper.queryByPluginType(pluginType.getDesc()); + + if (CollectionUtils.isEmpty(pluginDefines)) { + putMsg(result, Status.QUERY_PLUGINS_RESULT_IS_NULL); + return result; + } + // pluginDefines=buildPluginParams(pluginDefines); + putMsg(result, Status.SUCCESS); + result.put(Constants.DATA_LIST, pluginDefines); + return result; + } + + @Override + public Map queryUiPluginDetailById(int id) { + Map result = new HashMap<>(); + PluginDefine pluginDefine = pluginDefineMapper.queryDetailById(id); + if (null == pluginDefine) { + putMsg(result, Status.QUERY_PLUGIN_DETAIL_RESULT_IS_NULL); + return result; + } + // String params=pluginDefine.getPluginParams(); + // pluginDefine.setPluginParams(parseParams(params)); + putMsg(result, Status.SUCCESS); + result.put(Constants.DATA_LIST, pluginDefine); + return result; + } + +} diff --git a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/vo/AlertPluginInstanceVO.java b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/vo/AlertPluginInstanceVO.java new file mode 100644 index 0000000000..d8b76f633d --- /dev/null +++ b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/vo/AlertPluginInstanceVO.java @@ -0,0 +1,117 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.dolphinscheduler.api.vo; + +import java.util.Date; + +/** + * AlertPluginInstanceVO + */ +public class AlertPluginInstanceVO { + + /** + * id + */ + private int id; + + /** + * plugin_define_id + */ + private int pluginDefineId; + + /** + * alert plugin instance name + */ + private String instanceName; + + /** + * plugin_instance_params + */ + private String pluginInstanceParams; + + /** + * create_time + */ + private Date createTime; + + /** + * update_time + */ + private Date updateTime; + + /** + * alert plugin name + */ + private String alertPluginName; + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public int getPluginDefineId() { + return pluginDefineId; + } + + public void setPluginDefineId(int pluginDefineId) { + this.pluginDefineId = pluginDefineId; + } + + public String getInstanceName() { + return instanceName; + } + + public void setInstanceName(String instanceName) { + this.instanceName = instanceName; + } + + public String getPluginInstanceParams() { + return pluginInstanceParams; + } + + public void setPluginInstanceParams(String pluginInstanceParams) { + this.pluginInstanceParams = pluginInstanceParams; + } + + public Date getCreateTime() { + return createTime; + } + + public void setCreateTime(Date createTime) { + this.createTime = createTime; + } + + public Date getUpdateTime() { + return updateTime; + } + + public void setUpdateTime(Date updateTime) { + this.updateTime = updateTime; + } + + public String getAlertPluginName() { + return alertPluginName; + } + + public void setAlertPluginName(String alertPluginName) { + this.alertPluginName = alertPluginName; + } +} diff --git a/dolphinscheduler-api/src/main/resources/i18n/messages.properties b/dolphinscheduler-api/src/main/resources/i18n/messages.properties index 5837cfa929..cae8e5fa59 100644 --- a/dolphinscheduler-api/src/main/resources/i18n/messages.properties +++ b/dolphinscheduler-api/src/main/resources/i18n/messages.properties @@ -38,6 +38,11 @@ VERIFY_ALERT_GROUP_NAME_NOTES=verify alert group name, check alert group exist o GRANT_ALERT_GROUP_NOTES=grant alert group USER_IDS=user id list ALERT_GROUP_TAG=alert group related operation +ALERT_PLUGIN_INSTANCE_TAG=alert plugin instance related operation +UPDATE_ALERT_PLUGIN_INSTANCE_NOTES=update alert plugin instance operation +CREATE_ALERT_PLUGIN_INSTANCE_NOTES=create alert plugin instance operation +DELETE_ALERT_PLUGIN_INSTANCE_NOTES=delete alert plugin instance operation +GET_ALERT_PLUGIN_INSTANCE_NOTES=get alert plugin instance operation CREATE_ALERT_GROUP_NOTES=create alert group WORKER_GROUP_TAG=worker group related operation SAVE_WORKER_GROUP_NOTES=create worker group diff --git a/dolphinscheduler-api/src/main/resources/i18n/messages_en_US.properties b/dolphinscheduler-api/src/main/resources/i18n/messages_en_US.properties index 6f4777f44d..18b7a10885 100644 --- a/dolphinscheduler-api/src/main/resources/i18n/messages_en_US.properties +++ b/dolphinscheduler-api/src/main/resources/i18n/messages_en_US.properties @@ -38,6 +38,11 @@ VERIFY_ALERT_GROUP_NAME_NOTES=verify alert group name, check alert group exist o GRANT_ALERT_GROUP_NOTES=grant alert group USER_IDS=user id list ALERT_GROUP_TAG=alert group related operation +ALERT_PLUGIN_INSTANCE_TAG=alert plugin instance related operation +UPDATE_ALERT_PLUGIN_INSTANCE_NOTES=update alert plugin instance operation +CREATE_ALERT_PLUGIN_INSTANCE_NOTES=create alert plugin instance operation +DELETE_ALERT_PLUGIN_INSTANCE_NOTES=delete alert plugin instance operation +GET_ALERT_PLUGIN_INSTANCE_NOTES=get alert plugin instance operation CREATE_ALERT_GROUP_NOTES=create alert group WORKER_GROUP_TAG=worker group related operation SAVE_WORKER_GROUP_NOTES=create worker group diff --git a/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/controller/ExecutorControllerTest.java b/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/controller/ExecutorControllerTest.java index 77d8f38df0..f0bd948766 100644 --- a/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/controller/ExecutorControllerTest.java +++ b/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/controller/ExecutorControllerTest.java @@ -14,14 +14,20 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.dolphinscheduler.api.controller; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + import org.apache.dolphinscheduler.api.enums.ExecuteType; import org.apache.dolphinscheduler.api.enums.Status; import org.apache.dolphinscheduler.api.utils.Result; import org.apache.dolphinscheduler.common.enums.FailureStrategy; import org.apache.dolphinscheduler.common.enums.WarningType; -import org.apache.dolphinscheduler.common.utils.*; +import org.apache.dolphinscheduler.common.utils.JSONUtils; + import org.junit.Assert; import org.junit.Ignore; import org.junit.Test; @@ -32,44 +38,39 @@ import org.springframework.test.web.servlet.MvcResult; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - /** * executor controller test */ -public class ExecutorControllerTest extends AbstractControllerTest{ +public class ExecutorControllerTest extends AbstractControllerTest { private static Logger logger = LoggerFactory.getLogger(ExecutorControllerTest.class); @Ignore @Test public void testStartProcessInstance() throws Exception { MultiValueMap paramsMap = new LinkedMultiValueMap<>(); - paramsMap.add("processDefinitionId","40"); - paramsMap.add("scheduleTime",""); + paramsMap.add("processDefinitionId", "40"); + paramsMap.add("scheduleTime", ""); paramsMap.add("failureStrategy", String.valueOf(FailureStrategy.CONTINUE)); - paramsMap.add("startNodeList",""); - paramsMap.add("taskDependType",""); - paramsMap.add("execType",""); + paramsMap.add("startNodeList", ""); + paramsMap.add("taskDependType", ""); + paramsMap.add("execType", ""); paramsMap.add("warningType", String.valueOf(WarningType.NONE)); - paramsMap.add("warningGroupId",""); - paramsMap.add("receivers",""); - paramsMap.add("receiversCc",""); - paramsMap.add("runMode",""); - paramsMap.add("processInstancePriority",""); - paramsMap.add("workerGroupId",""); - paramsMap.add("timeout",""); + paramsMap.add("warningGroupId", ""); + paramsMap.add("receivers", ""); + paramsMap.add("receiversCc", ""); + paramsMap.add("runMode", ""); + paramsMap.add("processInstancePriority", ""); + paramsMap.add("workerGroupId", ""); + paramsMap.add("timeout", ""); - MvcResult mvcResult = mockMvc.perform(post("/projects/{projectName}/executors/start-process-instance","cxc_1113") - .header("sessionId", sessionId) - .params(paramsMap)) - .andExpect(status().isOk()) - .andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8)) - .andReturn(); + MvcResult mvcResult = mockMvc.perform(post("/projects/{projectName}/executors/start-process-instance", "cxc_1113") + .header("sessionId", sessionId) + .params(paramsMap)) + .andExpect(status().isOk()) + .andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8)) + .andReturn(); Result result = JSONUtils.parseObject(mvcResult.getResponse().getContentAsString(), Result.class); - Assert.assertEquals(Status.SUCCESS.getCode(),result.getCode().intValue()); + Assert.assertEquals(Status.SUCCESS.getCode(), result.getCode().intValue()); logger.info(mvcResult.getResponse().getContentAsString()); } @@ -77,47 +78,32 @@ public class ExecutorControllerTest extends AbstractControllerTest{ @Test public void testExecute() throws Exception { MultiValueMap paramsMap = new LinkedMultiValueMap<>(); - paramsMap.add("processInstanceId","40"); - paramsMap.add("executeType",String.valueOf(ExecuteType.NONE)); + paramsMap.add("processInstanceId", "40"); + paramsMap.add("executeType", String.valueOf(ExecuteType.NONE)); - MvcResult mvcResult = mockMvc.perform(post("/projects/{projectName}/executors/execute","cxc_1113") - .header("sessionId", sessionId) - .params(paramsMap)) - .andExpect(status().isOk()) - .andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8)) - .andReturn(); + MvcResult mvcResult = mockMvc.perform(post("/projects/{projectName}/executors/execute", "cxc_1113") + .header("sessionId", sessionId) + .params(paramsMap)) + .andExpect(status().isOk()) + .andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8)) + .andReturn(); Result result = JSONUtils.parseObject(mvcResult.getResponse().getContentAsString(), Result.class); - Assert.assertEquals(Status.SUCCESS.getCode(),result.getCode().intValue()); + Assert.assertEquals(Status.SUCCESS.getCode(), result.getCode().intValue()); logger.info(mvcResult.getResponse().getContentAsString()); } - @Test public void testStartCheckProcessDefinition() throws Exception { - MvcResult mvcResult = mockMvc.perform(post("/projects/{projectName}/executors/start-check","cxc_1113") - .header(SESSION_ID, sessionId) - .param("processDefinitionId","40")) - .andExpect(status().isOk()) - .andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8)) - .andReturn(); + MvcResult mvcResult = mockMvc.perform(post("/projects/{projectName}/executors/start-check", "cxc_1113") + .header(SESSION_ID, sessionId) + .param("processDefinitionId", "40")) + .andExpect(status().isOk()) + .andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8)) + .andReturn(); Result result = JSONUtils.parseObject(mvcResult.getResponse().getContentAsString(), Result.class); - Assert.assertEquals(Status.SUCCESS.getCode(),result.getCode().intValue()); + Assert.assertEquals(Status.SUCCESS.getCode(), result.getCode().intValue()); logger.info(mvcResult.getResponse().getContentAsString()); } - @Test - public void testGetReceiverCc() throws Exception { - MultiValueMap paramsMap = new LinkedMultiValueMap<>(); - paramsMap.add("processInstanceId","13"); - MvcResult mvcResult = mockMvc.perform(get("/projects/{projectName}/executors/get-receiver-cc","cxc_1113") - .header(SESSION_ID, sessionId) - .params(paramsMap)) - .andExpect(status().isOk()) - .andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8)) - .andReturn(); - Result result = JSONUtils.parseObject(mvcResult.getResponse().getContentAsString(), Result.class); - Assert.assertEquals(Status.SUCCESS.getCode(),result.getCode().intValue()); - logger.info(mvcResult.getResponse().getContentAsString()); - } } diff --git a/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/controller/ProcessDefinitionControllerTest.java b/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/controller/ProcessDefinitionControllerTest.java index 692d28b56e..9719448ad8 100644 --- a/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/controller/ProcessDefinitionControllerTest.java +++ b/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/controller/ProcessDefinitionControllerTest.java @@ -94,7 +94,7 @@ public class ProcessDefinitionControllerTest { String connects = "[]"; Map result = new HashMap<>(); putMsg(result, Status.SUCCESS); - result.put("processDefinitionId", 1); + result.put(Constants.DATA_LIST, 1); Mockito.when(processDefinitionService.createProcessDefinition(user, projectName, name, json, description, locations, connects)).thenReturn(result); @@ -150,7 +150,7 @@ public class ProcessDefinitionControllerTest { description, locations, connects)).thenReturn(result); Result response = processDefinitionController.updateProcessDefinition(user, projectName, name, id, json, - locations, connects, description); + locations, connects, description,ReleaseState.OFFLINE); Assert.assertEquals(Status.SUCCESS.getCode(), response.getCode().intValue()); } @@ -161,8 +161,8 @@ public class ProcessDefinitionControllerTest { Map result = new HashMap<>(); putMsg(result, Status.SUCCESS); - Mockito.when(processDefinitionService.releaseProcessDefinition(user, projectName, id, ReleaseState.OFFLINE.ordinal())).thenReturn(result); - Result response = processDefinitionController.releaseProcessDefinition(user, projectName, id, ReleaseState.OFFLINE.ordinal()); + Mockito.when(processDefinitionService.releaseProcessDefinition(user, projectName, id, ReleaseState.OFFLINE)).thenReturn(result); + Result response = processDefinitionController.releaseProcessDefinition(user, projectName, id, ReleaseState.OFFLINE); Assert.assertEquals(Status.SUCCESS.getCode(), response.getCode().intValue()); } diff --git a/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/controller/TaskInstanceControllerTest.java b/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/controller/TaskInstanceControllerTest.java index b97c7c192f..ec47c5e4a1 100644 --- a/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/controller/TaskInstanceControllerTest.java +++ b/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/controller/TaskInstanceControllerTest.java @@ -18,8 +18,13 @@ package org.apache.dolphinscheduler.api.controller; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.when; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import org.apache.dolphinscheduler.api.enums.Status; import org.apache.dolphinscheduler.api.service.TaskInstanceService; @@ -27,24 +32,28 @@ import org.apache.dolphinscheduler.api.utils.PageInfo; import org.apache.dolphinscheduler.api.utils.Result; import org.apache.dolphinscheduler.common.Constants; import org.apache.dolphinscheduler.common.enums.ExecutionStatus; +import org.apache.dolphinscheduler.common.utils.JSONUtils; import org.apache.dolphinscheduler.dao.entity.TaskInstance; +import org.apache.dolphinscheduler.dao.entity.User; import java.util.HashMap; import java.util.Map; import org.junit.Assert; +import org.junit.Ignore; import org.junit.Test; -import org.junit.runner.RunWith; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.Mockito; -import org.mockito.junit.MockitoJUnitRunner; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.MvcResult; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; /** * task instance controller test */ -@RunWith(MockitoJUnitRunner.Silent.class) -public class TaskInstanceControllerTest { +public class TaskInstanceControllerTest extends AbstractControllerTest { @InjectMocks private TaskInstanceController taskInstanceController; @@ -67,7 +76,28 @@ public class TaskInstanceControllerTest { Result taskResult = taskInstanceController.queryTaskListPaging(null, "", 1, "", "", "", "", ExecutionStatus.SUCCESS,"192.168.xx.xx", "2020-01-01 00:00:00", "2020-01-02 00:00:00",pageNo, pageSize); Assert.assertEquals(Integer.valueOf(Status.SUCCESS.getCode()), taskResult.getCode()); + } + + @Ignore + @Test + public void testForceTaskSuccess() throws Exception { + MultiValueMap paramsMap = new LinkedMultiValueMap<>(); + paramsMap.add("taskInstanceId", "104"); + + Map mockResult = new HashMap<>(5); + mockResult.put(Constants.STATUS, Status.SUCCESS); + mockResult.put(Constants.MSG, Status.SUCCESS.getMsg()); + when(taskInstanceService.forceTaskSuccess(any(User.class), anyString(), anyInt())).thenReturn(mockResult); + + MvcResult mvcResult = mockMvc.perform(post("/projects/{projectName}/task-instance/force-success", "cxc_1113") + .header(SESSION_ID, sessionId) + .params(paramsMap)) + .andExpect(status().isOk()) + .andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8)) + .andReturn(); + Result result = JSONUtils.parseObject(mvcResult.getResponse().getContentAsString(), Result.class); + Assert.assertEquals(Status.SUCCESS.getCode(), result.getCode().intValue()); } } diff --git a/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/security/SecurityConfigLDAPTest.java~HEAD b/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/security/SecurityConfigLDAPTest.java~HEAD new file mode 100644 index 0000000000..a96cec9158 --- /dev/null +++ b/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/security/SecurityConfigLDAPTest.java~HEAD @@ -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.api.security; + +import org.apache.dolphinscheduler.api.ApiApplicationServer; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest(classes = ApiApplicationServer.class) +@TestPropertySource(properties = { + "security.authentication.type=LDAP", +}) +public class SecurityConfigLDAPTest { + + @Autowired + private SecurityConfig securityConfig; + + @Test + public void testAuthenticator() { + Authenticator authenticator = securityConfig.authenticator(); + Assert.assertNotNull(authenticator); + } +} diff --git a/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/security/SecurityConfigLDAPTest.java~dev b/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/security/SecurityConfigLDAPTest.java~dev new file mode 100644 index 0000000000..a96cec9158 --- /dev/null +++ b/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/security/SecurityConfigLDAPTest.java~dev @@ -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.api.security; + +import org.apache.dolphinscheduler.api.ApiApplicationServer; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest(classes = ApiApplicationServer.class) +@TestPropertySource(properties = { + "security.authentication.type=LDAP", +}) +public class SecurityConfigLDAPTest { + + @Autowired + private SecurityConfig securityConfig; + + @Test + public void testAuthenticator() { + Authenticator authenticator = securityConfig.authenticator(); + Assert.assertNotNull(authenticator); + } +} diff --git a/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/AlertGroupServiceTest.java b/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/AlertGroupServiceTest.java index 1b93e86773..b7b6575ed1 100644 --- a/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/AlertGroupServiceTest.java +++ b/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/AlertGroupServiceTest.java @@ -14,14 +14,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.dolphinscheduler.api.service; -import com.baomidou.mybatisplus.core.metadata.IPage; -import com.baomidou.mybatisplus.extension.plugins.pagination.Page; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; + import org.apache.dolphinscheduler.api.enums.Status; import org.apache.dolphinscheduler.api.utils.PageInfo; import org.apache.dolphinscheduler.common.Constants; @@ -31,15 +29,15 @@ import org.apache.dolphinscheduler.common.utils.CollectionUtils; import org.apache.dolphinscheduler.dao.entity.AlertGroup; import org.apache.dolphinscheduler.dao.entity.User; import org.apache.dolphinscheduler.dao.mapper.AlertGroupMapper; -import org.apache.dolphinscheduler.dao.mapper.UserAlertGroupMapper; -import org.junit.After; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + import org.junit.Assert; -import static org.junit.Assert.assertEquals; -import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; -import org.mockito.ArgumentCaptor; -import static org.mockito.ArgumentMatchers.*; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.Mockito; @@ -47,6 +45,9 @@ import org.mockito.junit.MockitoJUnitRunner; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; + @RunWith(MockitoJUnitRunner.class) public class AlertGroupServiceTest { @@ -56,128 +57,97 @@ public class AlertGroupServiceTest { private AlertGroupService alertGroupService; @Mock private AlertGroupMapper alertGroupMapper; - @Mock - private UserAlertGroupMapper userAlertGroupMapper; - @Mock - UserAlertGroupService userAlertGroupService; private String groupName = "AlertGroupServiceTest"; - @Before - public void setUp() { - } - - - @After - public void after(){ - - } - - - @Test - public void testQueryAlertGroup(){ + public void testQueryAlertGroup() { Mockito.when(alertGroupMapper.queryAllGroupList()).thenReturn(getList()); - HashMap result= alertGroupService.queryAlertgroup(); + HashMap result = alertGroupService.queryAlertgroup(); logger.info(result.toString()); List alertGroups = (List) result.get(Constants.DATA_LIST); Assert.assertTrue(CollectionUtils.isNotEmpty(alertGroups)); } + @Test - public void testListPaging(){ - IPage page = new Page<>(1,10); + public void testListPaging() { + IPage page = new Page<>(1, 10); page.setTotal(1L); page.setRecords(getList()); - Mockito.when(alertGroupMapper.queryAlertGroupPage(any(Page.class),eq(groupName))).thenReturn(page); + Mockito.when(alertGroupMapper.queryAlertGroupPage(any(Page.class), eq(groupName))).thenReturn(page); User user = new User(); // no operate - Map result = alertGroupService.listPaging(user,groupName,1,10); + Map result = alertGroupService.listPaging(user, groupName, 1, 10); logger.info(result.toString()); - Assert.assertEquals(Status.USER_NO_OPERATION_PERM,result.get(Constants.STATUS)); + Assert.assertEquals(Status.USER_NO_OPERATION_PERM, result.get(Constants.STATUS)); //success user.setUserType(UserType.ADMIN_USER); - result = alertGroupService.listPaging(user,groupName,1,10); + result = alertGroupService.listPaging(user, groupName, 1, 10); logger.info(result.toString()); PageInfo pageInfo = (PageInfo) result.get(Constants.DATA_LIST); Assert.assertTrue(CollectionUtils.isNotEmpty(pageInfo.getLists())); } - @Test - public void testCreateAlertgroup(){ + @Test + public void testCreateAlertgroup() { Mockito.when(alertGroupMapper.insert(any(AlertGroup.class))).thenReturn(2); User user = new User(); //no operate - Map result = alertGroupService.createAlertgroup(user,groupName, AlertType.EMAIL,groupName); + Map result = alertGroupService.createAlertgroup(user, groupName, groupName, null); logger.info(result.toString()); - Assert.assertEquals(Status.USER_NO_OPERATION_PERM,result.get(Constants.STATUS)); + Assert.assertEquals(Status.USER_NO_OPERATION_PERM, result.get(Constants.STATUS)); user.setUserType(UserType.ADMIN_USER); //success - result = alertGroupService.createAlertgroup(user,groupName, AlertType.EMAIL,groupName); + result = alertGroupService.createAlertgroup(user, groupName, groupName, null); logger.info(result.toString()); - Assert.assertEquals(Status.SUCCESS,result.get(Constants.STATUS)); + Assert.assertEquals(Status.SUCCESS, result.get(Constants.STATUS)); } + @Test - public void testUpdateAlertgroup(){ + public void testUpdateAlertgroup() { User user = new User(); // no operate - Map result = alertGroupService.updateAlertgroup(user,1,groupName, AlertType.SMS,groupName); + Map result = alertGroupService.updateAlertgroup(user, 1, groupName, groupName, null); logger.info(result.toString()); - Assert.assertEquals(Status.USER_NO_OPERATION_PERM,result.get(Constants.STATUS)); + Assert.assertEquals(Status.USER_NO_OPERATION_PERM, result.get(Constants.STATUS)); user.setUserType(UserType.ADMIN_USER); // not exist - result = alertGroupService.updateAlertgroup(user,1,groupName, AlertType.SMS,groupName); + result = alertGroupService.updateAlertgroup(user, 1, groupName, groupName, null); logger.info(result.toString()); - Assert.assertEquals(Status.ALERT_GROUP_NOT_EXIST,result.get(Constants.STATUS)); + Assert.assertEquals(Status.ALERT_GROUP_NOT_EXIST, result.get(Constants.STATUS)); //success Mockito.when(alertGroupMapper.selectById(2)).thenReturn(getEntity()); - result = alertGroupService.updateAlertgroup(user,2,groupName, AlertType.SMS,groupName); + result = alertGroupService.updateAlertgroup(user, 2, groupName, groupName, null); logger.info(result.toString()); - Assert.assertEquals(Status.SUCCESS,result.get(Constants.STATUS)); + Assert.assertEquals(Status.SUCCESS, result.get(Constants.STATUS)); } + @Test - public void testDelAlertgroupById(){ + public void testDelAlertgroupById() { User user = new User(); // no operate - Map result = alertGroupService.delAlertgroupById(user,1); + Map result = alertGroupService.delAlertgroupById(user, 1); logger.info(result.toString()); - Assert.assertEquals(Status.USER_NO_OPERATION_PERM,result.get(Constants.STATUS)); + Assert.assertEquals(Status.USER_NO_OPERATION_PERM, result.get(Constants.STATUS)); user.setUserType(UserType.ADMIN_USER); // not exist - result = alertGroupService.delAlertgroupById(user,2); + result = alertGroupService.delAlertgroupById(user, 2); logger.info(result.toString()); - Assert.assertEquals(Status.ALERT_GROUP_NOT_EXIST,result.get(Constants.STATUS)); + Assert.assertEquals(Status.ALERT_GROUP_NOT_EXIST, result.get(Constants.STATUS)); //success Mockito.when(alertGroupMapper.selectById(2)).thenReturn(getEntity()); - result = alertGroupService.delAlertgroupById(user,2); + result = alertGroupService.delAlertgroupById(user, 2); logger.info(result.toString()); - Assert.assertEquals(Status.SUCCESS,result.get(Constants.STATUS)); - + Assert.assertEquals(Status.SUCCESS, result.get(Constants.STATUS)); } - @Test - public void testGrantUser() { - - Integer groupId = 1; - - ArgumentCaptor groupArgument = ArgumentCaptor.forClass(Integer.class); - - Mockito.when(userAlertGroupService.deleteByAlertGroupId(anyInt())).thenReturn(true); - - Map result = alertGroupService.grantUser(getLoginUser(), groupId, "123,321"); - Mockito.verify(userAlertGroupService).deleteByAlertGroupId(groupArgument.capture()); - - logger.info(result.toString()); - assertEquals(groupArgument.getValue(), groupId); - assertEquals(Status.SUCCESS, result.get(Constants.STATUS)); - } - @Test public void testVerifyGroupName() { //group name not exist @@ -190,12 +160,10 @@ public class AlertGroupServiceTest { Assert.assertTrue(result); } - /** * create admin user - * @return */ - private User getLoginUser(){ + private User getLoginUser() { User loginUser = new User(); loginUser.setUserType(UserType.ADMIN_USER); @@ -205,9 +173,8 @@ public class AlertGroupServiceTest { /** * get list - * @return */ - private List getList(){ + private List getList() { List alertGroups = new ArrayList<>(); alertGroups.add(getEntity()); return alertGroups; @@ -215,13 +182,11 @@ public class AlertGroupServiceTest { /** * get entity - * @return */ - private AlertGroup getEntity(){ + private AlertGroup getEntity() { AlertGroup alertGroup = new AlertGroup(); alertGroup.setId(1); alertGroup.setGroupName(groupName); - alertGroup.setGroupType(AlertType.EMAIL); return alertGroup; } diff --git a/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/BaseServiceTest.java b/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/BaseServiceTest.java index 02086a8259..95083dd51b 100644 --- a/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/BaseServiceTest.java +++ b/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/BaseServiceTest.java @@ -72,6 +72,8 @@ public class BaseServiceTest { } + + @Test public void testPutMsg(){ diff --git a/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/DataSourceServiceTest.java b/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/DataSourceServiceTest.java index 789e5f6cc5..84ccd2e0a3 100644 --- a/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/DataSourceServiceTest.java +++ b/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/DataSourceServiceTest.java @@ -14,6 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.dolphinscheduler.api.service; import org.apache.dolphinscheduler.api.enums.Status; @@ -24,12 +25,19 @@ import org.apache.dolphinscheduler.common.enums.DbType; import org.apache.dolphinscheduler.common.enums.UserType; import org.apache.dolphinscheduler.common.utils.JSONUtils; import org.apache.dolphinscheduler.common.utils.PropertyUtils; +import org.apache.dolphinscheduler.dao.datasource.BaseDataSource; import org.apache.dolphinscheduler.dao.datasource.DataSourceFactory; import org.apache.dolphinscheduler.dao.datasource.MySQLDataSource; import org.apache.dolphinscheduler.dao.entity.DataSource; import org.apache.dolphinscheduler.dao.entity.User; import org.apache.dolphinscheduler.dao.mapper.DataSourceMapper; import org.apache.dolphinscheduler.dao.mapper.DataSourceUserMapper; + +import java.sql.Connection; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; @@ -38,16 +46,15 @@ import org.mockito.Mock; import org.mockito.Mockito; import org.powermock.api.mockito.PowerMockito; import org.powermock.core.classloader.annotations.PowerMockIgnore; +import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - @RunWith(PowerMockRunner.class) @PowerMockIgnore({"sun.security.*", "javax.net.*"}) +@PrepareForTest({DataSourceFactory.class}) public class DataSourceServiceTest { + @InjectMocks private DataSourceService dataSourceService; @Mock @@ -69,28 +76,31 @@ public class DataSourceServiceTest { dataSource.setName(dataSourceName); dataSourceList.add(dataSource); PowerMockito.when(dataSourceMapper.queryDataSourceByName(dataSourceName.trim())).thenReturn(dataSourceList); - Map dataSourceExitsResult = dataSourceService.createDataSource(loginUser, dataSourceName, dataSourceDesc, dataSourceType, parameter); - Assert.assertEquals(Status.DATASOURCE_EXIST, dataSourceExitsResult.get(Constants.STATUS)); + Result dataSourceExitsResult = dataSourceService.createDataSource(loginUser, dataSourceName, dataSourceDesc, dataSourceType, parameter); + Assert.assertEquals(Status.DATASOURCE_EXIST.getCode(), dataSourceExitsResult.getCode().intValue()); // data source exits PowerMockito.when(dataSourceMapper.queryDataSourceByName(dataSourceName.trim())).thenReturn(null); - PowerMockito.when(dataSourceService.checkConnection(dataSourceType, parameter)).thenReturn(false); - Map connectFailedResult = dataSourceService.createDataSource(loginUser, dataSourceName, dataSourceDesc, dataSourceType, parameter); - Assert.assertEquals(Status.DATASOURCE_CONNECT_FAILED, connectFailedResult.get(Constants.STATUS)); + Result connectionResult = new Result(Status.DATASOURCE_CONNECT_FAILED.getCode(),Status.DATASOURCE_CONNECT_FAILED.getMsg()); + //PowerMockito.when(dataSourceService.checkConnection(dataSourceType, parameter)).thenReturn(connectionResult); + PowerMockito.doReturn(connectionResult).when(dataSourceService).checkConnection(dataSourceType, parameter); + Result connectFailedResult = dataSourceService.createDataSource(loginUser, dataSourceName, dataSourceDesc, dataSourceType, parameter); + Assert.assertEquals(Status.DATASOURCE_CONNECT_FAILED.getCode(), connectFailedResult.getCode().intValue()); // data source exits PowerMockito.when(dataSourceMapper.queryDataSourceByName(dataSourceName.trim())).thenReturn(null); - PowerMockito.when(dataSourceService.checkConnection(dataSourceType, parameter)).thenReturn(true); + connectionResult = new Result(Status.SUCCESS.getCode(),Status.SUCCESS.getMsg()); + PowerMockito.when(dataSourceService.checkConnection(dataSourceType, parameter)).thenReturn(connectionResult); PowerMockito.when(DataSourceFactory.getDatasource(dataSourceType, parameter)).thenReturn(null); - Map notValidError = dataSourceService.createDataSource(loginUser, dataSourceName, dataSourceDesc, dataSourceType, parameter); - Assert.assertEquals(Status.REQUEST_PARAMS_NOT_VALID_ERROR, notValidError.get(Constants.STATUS)); + Result notValidError = dataSourceService.createDataSource(loginUser, dataSourceName, dataSourceDesc, dataSourceType, parameter); + Assert.assertEquals(Status.REQUEST_PARAMS_NOT_VALID_ERROR.getCode(), notValidError.getCode().intValue()); // success PowerMockito.when(dataSourceMapper.queryDataSourceByName(dataSourceName.trim())).thenReturn(null); - PowerMockito.when(dataSourceService.checkConnection(dataSourceType, parameter)).thenReturn(true); + PowerMockito.when(dataSourceService.checkConnection(dataSourceType, parameter)).thenReturn(connectionResult); PowerMockito.when(DataSourceFactory.getDatasource(dataSourceType, parameter)).thenReturn(JSONUtils.parseObject(parameter, MySQLDataSource.class)); - Map success = dataSourceService.createDataSource(loginUser, dataSourceName, dataSourceDesc, dataSourceType, parameter); - Assert.assertEquals(Status.SUCCESS, success.get(Constants.STATUS)); + Result success = dataSourceService.createDataSource(loginUser, dataSourceName, dataSourceDesc, dataSourceType, parameter); + Assert.assertEquals(Status.SUCCESS.getCode(), success.getCode().intValue()); } public void updateDataSourceTest() { @@ -104,14 +114,14 @@ public class DataSourceServiceTest { // data source not exits PowerMockito.when(dataSourceMapper.selectById(dataSourceId)).thenReturn(null); - Map resourceNotExits = dataSourceService.updateDataSource(dataSourceId, loginUser, dataSourceName, dataSourceDesc, dataSourceType, parameter); - Assert.assertEquals(Status.RESOURCE_NOT_EXIST, resourceNotExits.get(Constants.STATUS)); + Result resourceNotExits = dataSourceService.updateDataSource(dataSourceId, loginUser, dataSourceName, dataSourceDesc, dataSourceType, parameter); + Assert.assertEquals(Status.RESOURCE_NOT_EXIST.getCode(), resourceNotExits.getCode().intValue()); // user no operation perm DataSource dataSource = new DataSource(); dataSource.setUserId(0); PowerMockito.when(dataSourceMapper.selectById(dataSourceId)).thenReturn(dataSource); - Map userNoOperationPerm = dataSourceService.updateDataSource(dataSourceId, loginUser, dataSourceName, dataSourceDesc, dataSourceType, parameter); - Assert.assertEquals(Status.USER_NO_OPERATION_PERM, userNoOperationPerm.get(Constants.STATUS)); + Result userNoOperationPerm = dataSourceService.updateDataSource(dataSourceId, loginUser, dataSourceName, dataSourceDesc, dataSourceType, parameter); + Assert.assertEquals(Status.USER_NO_OPERATION_PERM.getCode(), userNoOperationPerm.getCode().intValue()); // data source name exits dataSource.setUserId(-1); @@ -119,22 +129,24 @@ public class DataSourceServiceTest { dataSourceList.add(dataSource); PowerMockito.when(dataSourceMapper.selectById(dataSourceId)).thenReturn(dataSource); PowerMockito.when(dataSourceMapper.queryDataSourceByName(dataSourceName)).thenReturn(dataSourceList); - Map dataSourceNameExist = dataSourceService.updateDataSource(dataSourceId, loginUser, dataSourceName, dataSourceDesc, dataSourceType, parameter); - Assert.assertEquals(Status.DATASOURCE_EXIST, dataSourceNameExist.get(Constants.STATUS)); + Result dataSourceNameExist = dataSourceService.updateDataSource(dataSourceId, loginUser, dataSourceName, dataSourceDesc, dataSourceType, parameter); + Assert.assertEquals(Status.DATASOURCE_EXIST.getCode(), dataSourceNameExist.getCode().intValue()); // data source connect failed PowerMockito.when(dataSourceMapper.selectById(dataSourceId)).thenReturn(dataSource); PowerMockito.when(dataSourceMapper.queryDataSourceByName(dataSourceName)).thenReturn(null); - PowerMockito.when(dataSourceService.checkConnection(dataSourceType, parameter)).thenReturn(true); - Map connectFailed = dataSourceService.updateDataSource(dataSourceId, loginUser, dataSourceName, dataSourceDesc, dataSourceType, parameter); - Assert.assertEquals(Status.DATASOURCE_CONNECT_FAILED, connectFailed.get(Constants.STATUS)); + Result connectionResult = new Result(Status.SUCCESS.getCode(),Status.SUCCESS.getMsg()); + PowerMockito.when(dataSourceService.checkConnection(dataSourceType, parameter)).thenReturn(connectionResult); + Result connectFailed = dataSourceService.updateDataSource(dataSourceId, loginUser, dataSourceName, dataSourceDesc, dataSourceType, parameter); + Assert.assertEquals(Status.DATASOURCE_CONNECT_FAILED.getCode(), connectFailed.getCode().intValue()); //success PowerMockito.when(dataSourceMapper.selectById(dataSourceId)).thenReturn(dataSource); PowerMockito.when(dataSourceMapper.queryDataSourceByName(dataSourceName)).thenReturn(null); - PowerMockito.when(dataSourceService.checkConnection(dataSourceType, parameter)).thenReturn(false); - Map success = dataSourceService.updateDataSource(dataSourceId, loginUser, dataSourceName, dataSourceDesc, dataSourceType, parameter); - Assert.assertEquals(Status.SUCCESS, connectFailed.get(Constants.STATUS)); + connectionResult = new Result(Status.DATASOURCE_CONNECT_FAILED.getCode(),Status.DATASOURCE_CONNECT_FAILED.getMsg()); + PowerMockito.when(dataSourceService.checkConnection(dataSourceType, parameter)).thenReturn(connectionResult); + Result success = dataSourceService.updateDataSource(dataSourceId, loginUser, dataSourceName, dataSourceDesc, dataSourceType, parameter); + Assert.assertEquals(Status.SUCCESS.getCode(), success.getCode().intValue()); } @@ -152,7 +164,8 @@ public class DataSourceServiceTest { public void connectionTest() { int dataSourceId = -1; PowerMockito.when(dataSourceMapper.selectById(dataSourceId)).thenReturn(null); - Assert.assertFalse(dataSourceService.connectionTest(dataSourceId)); + Result result = dataSourceService.connectionTest(dataSourceId); + Assert.assertEquals(Status.RESOURCE_NOT_EXIST.getCode(),result.getCode().intValue()); } @Test @@ -252,7 +265,8 @@ public class DataSourceServiceTest { dataSource.setName("test"); dataSource.setNote("Note"); dataSource.setType(DbType.ORACLE); - dataSource.setConnectionParams("{\"connectType\":\"ORACLE_SID\",\"address\":\"jdbc:oracle:thin:@192.168.xx.xx:49161\",\"database\":\"XE\",\"jdbcUrl\":\"jdbc:oracle:thin:@192.168.xx.xx:49161/XE\",\"user\":\"system\",\"password\":\"oracle\"}"); + dataSource.setConnectionParams("{\"connectType\":\"ORACLE_SID\",\"address\":\"jdbc:oracle:thin:@192.168.xx.xx:49161\",\"database\":\"XE\"," + + "\"jdbcUrl\":\"jdbc:oracle:thin:@192.168.xx.xx:49161/XE\",\"user\":\"system\",\"password\":\"oracle\"}"); return dataSource; } @@ -261,7 +275,8 @@ public class DataSourceServiceTest { public void buildParameter() { String param = dataSourceService.buildParameter(DbType.ORACLE, "192.168.9.1", "1521", "im" , "", "test", "test", DbConnectType.ORACLE_SERVICE_NAME, ""); - String expected = "{\"connectType\":\"ORACLE_SERVICE_NAME\",\"type\":\"ORACLE_SERVICE_NAME\",\"address\":\"jdbc:oracle:thin:@//192.168.9.1:1521\",\"database\":\"im\",\"jdbcUrl\":\"jdbc:oracle:thin:@//192.168.9.1:1521/im\",\"user\":\"test\",\"password\":\"test\"}"; + String expected = "{\"connectType\":\"ORACLE_SERVICE_NAME\",\"type\":\"ORACLE_SERVICE_NAME\",\"address\":\"jdbc:oracle:thin:@//192.168.9.1:1521\",\"database\":\"im\"," + + "\"jdbcUrl\":\"jdbc:oracle:thin:@//192.168.9.1:1521/im\",\"user\":\"test\",\"password\":\"test\"}"; Assert.assertEquals(expected, param); } @@ -270,10 +285,10 @@ public class DataSourceServiceTest { PropertyUtils.setValue(Constants.DATASOURCE_ENCRYPTION_ENABLE, "true"); String param = dataSourceService.buildParameter(DbType.MYSQL, "192.168.9.1", "1521", "im" , "", "test", "123456", null, ""); - String expected = "{\"type\":null,\"address\":\"jdbc:mysql://192.168.9.1:1521\",\"database\":\"im\",\"jdbcUrl\":\"jdbc:mysql://192.168.9.1:1521/im\",\"user\":\"test\",\"password\":\"IUAjJCVeJipNVEl6TkRVMg==\"}"; + String expected = "{\"type\":null,\"address\":\"jdbc:mysql://192.168.9.1:1521\",\"database\":\"im\",\"jdbcUrl\":\"jdbc:mysql://192.168.9.1:1521/im\"," + + "\"user\":\"test\",\"password\":\"IUAjJCVeJipNVEl6TkRVMg==\"}"; Assert.assertEquals(expected, param); - PropertyUtils.setValue(Constants.DATASOURCE_ENCRYPTION_ENABLE, "false"); param = dataSourceService.buildParameter(DbType.MYSQL, "192.168.9.1", "1521", "im" , "", "test", "123456", null, ""); @@ -294,4 +309,31 @@ public class DataSourceServiceTest { return loginUser; } -} \ No newline at end of file + /** + * test check connection + * @throws Exception + */ + @Test + public void testCheckConnection() throws Exception { + DbType dataSourceType = DbType.POSTGRESQL; + String parameter = dataSourceService.buildParameter(dataSourceType, "172.16.133.200", "5432", "dolphinscheduler", null, "postgres", "", null, null); + + PowerMockito.mockStatic(DataSourceFactory.class); + PowerMockito.when(DataSourceFactory.getDatasource(Mockito.any(), Mockito.anyString())).thenReturn(null); + Result result = dataSourceService.checkConnection(dataSourceType, parameter); + Assert.assertEquals(Status.DATASOURCE_TYPE_NOT_EXIST.getCode(), result.getCode().intValue()); + + BaseDataSource dataSource = PowerMockito.mock(BaseDataSource.class); + PowerMockito.when(DataSourceFactory.getDatasource(Mockito.any(), Mockito.anyString())).thenReturn(dataSource); + PowerMockito.when(dataSource.getConnection()).thenReturn(null); + result = dataSourceService.checkConnection(dataSourceType, parameter); + Assert.assertEquals(Status.CONNECTION_TEST_FAILURE.getCode(), result.getCode().intValue()); + + Connection connection = PowerMockito.mock(Connection.class); + PowerMockito.when(dataSource.getConnection()).thenReturn(connection); + result = dataSourceService.checkConnection(dataSourceType, parameter); + Assert.assertEquals(Status.SUCCESS.getCode(), result.getCode().intValue()); + + } + +} diff --git a/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/ExecutorService2Test.java b/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/ExecutorService2Test.java index 9f8d1b21f0..3f25fb84d4 100644 --- a/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/ExecutorService2Test.java +++ b/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/ExecutorService2Test.java @@ -25,12 +25,14 @@ import org.apache.dolphinscheduler.api.enums.Status; import org.apache.dolphinscheduler.api.service.impl.ProjectServiceImpl; import org.apache.dolphinscheduler.common.Constants; import org.apache.dolphinscheduler.common.enums.CommandType; +import org.apache.dolphinscheduler.common.enums.ExecutionStatus; import org.apache.dolphinscheduler.common.enums.Priority; import org.apache.dolphinscheduler.common.enums.ReleaseState; import org.apache.dolphinscheduler.common.enums.RunMode; import org.apache.dolphinscheduler.common.model.Server; import org.apache.dolphinscheduler.dao.entity.Command; import org.apache.dolphinscheduler.dao.entity.ProcessDefinition; +import org.apache.dolphinscheduler.dao.entity.ProcessInstance; import org.apache.dolphinscheduler.dao.entity.Project; import org.apache.dolphinscheduler.dao.entity.Schedule; import org.apache.dolphinscheduler.dao.entity.Tenant; @@ -82,12 +84,16 @@ public class ExecutorService2Test { private int processDefinitionId = 1; + private int processInstanceId = 1; + private int tenantId = 1; private int userId = 1; private ProcessDefinition processDefinition = new ProcessDefinition(); + private ProcessInstance processInstance = new ProcessInstance(); + private User loginUser = new User(); private String projectName = "projectName"; @@ -107,6 +113,13 @@ public class ExecutorService2Test { processDefinition.setTenantId(tenantId); processDefinition.setUserId(userId); + // processInstance + processInstance.setId(processInstanceId); + processInstance.setProcessDefinitionId(processDefinitionId); + processInstance.setState(ExecutionStatus.FAILURE); + processInstance.setExecutorId(userId); + processInstance.setTenantId(tenantId); + // project project.setName(projectName); @@ -120,6 +133,8 @@ public class ExecutorService2Test { Mockito.when(processService.getTenantForProcess(tenantId, userId)).thenReturn(new Tenant()); Mockito.when(processService.createCommand(any(Command.class))).thenReturn(1); Mockito.when(monitorService.getServerListFromZK(true)).thenReturn(getMasterServersList()); + Mockito.when(processService.findProcessInstanceDetailById(processInstanceId)).thenReturn(processInstance); + Mockito.when(processService.findProcessDefineById(processDefinitionId)).thenReturn(processDefinition); } /** @@ -127,19 +142,17 @@ public class ExecutorService2Test { */ @Test public void testNoComplement() throws ParseException { - try { - Mockito.when(processService.queryReleaseSchedulerListByProcessDefinitionId(processDefinitionId)).thenReturn(zeroSchedulerList()); - Map result = executorService.execProcessInstance(loginUser, projectName, - processDefinitionId, cronTime, CommandType.START_PROCESS, - null, null, - null, null, 0, - "", "", RunMode.RUN_MODE_SERIAL, - Priority.LOW, Constants.DEFAULT_WORKER_GROUP, 110); - Assert.assertEquals(Status.SUCCESS, result.get(Constants.STATUS)); - verify(processService, times(1)).createCommand(any(Command.class)); - } catch (Exception e) { - //ignore - } + + Mockito.when(processService.queryReleaseSchedulerListByProcessDefinitionId(processDefinitionId)).thenReturn(zeroSchedulerList()); + Map result = executorService.execProcessInstance(loginUser, projectName, + processDefinitionId, cronTime, CommandType.START_PROCESS, + null, null, + null, null, 0, + RunMode.RUN_MODE_SERIAL, + Priority.LOW, Constants.DEFAULT_WORKER_GROUP, 110, null); + Assert.assertEquals(Status.SUCCESS, result.get(Constants.STATUS)); + verify(processService, times(1)).createCommand(any(Command.class)); + } /** @@ -147,19 +160,17 @@ public class ExecutorService2Test { */ @Test public void testComplementWithStartNodeList() throws ParseException { - try { - Mockito.when(processService.queryReleaseSchedulerListByProcessDefinitionId(processDefinitionId)).thenReturn(zeroSchedulerList()); - Map result = executorService.execProcessInstance(loginUser, projectName, - processDefinitionId, cronTime, CommandType.START_PROCESS, - null, "n1,n2", - null, null, 0, - "", "", RunMode.RUN_MODE_SERIAL, - Priority.LOW, Constants.DEFAULT_WORKER_GROUP, 110); - Assert.assertEquals(Status.SUCCESS, result.get(Constants.STATUS)); - verify(processService, times(1)).createCommand(any(Command.class)); - } catch (Exception e) { - //ignore - } + + Mockito.when(processService.queryReleaseSchedulerListByProcessDefinitionId(processDefinitionId)).thenReturn(zeroSchedulerList()); + Map result = executorService.execProcessInstance(loginUser, projectName, + processDefinitionId, cronTime, CommandType.START_PROCESS, + null, "n1,n2", + null, null, 0, + RunMode.RUN_MODE_SERIAL, + Priority.LOW, Constants.DEFAULT_WORKER_GROUP, 110, null); + Assert.assertEquals(Status.SUCCESS, result.get(Constants.STATUS)); + verify(processService, times(1)).createCommand(any(Command.class)); + } @@ -168,19 +179,16 @@ public class ExecutorService2Test { */ @Test public void testDateError() throws ParseException { - try { - Mockito.when(processService.queryReleaseSchedulerListByProcessDefinitionId(processDefinitionId)).thenReturn(zeroSchedulerList()); - Map result = executorService.execProcessInstance(loginUser, projectName, - processDefinitionId, "2020-01-31 23:00:00,2020-01-01 00:00:00", CommandType.COMPLEMENT_DATA, - null, null, - null, null, 0, - "", "", RunMode.RUN_MODE_SERIAL, - Priority.LOW, Constants.DEFAULT_WORKER_GROUP, 110); - Assert.assertEquals(Status.START_PROCESS_INSTANCE_ERROR, result.get(Constants.STATUS)); - verify(processService, times(0)).createCommand(any(Command.class)); - } catch (Exception e) { - //ignore - } + + Mockito.when(processService.queryReleaseSchedulerListByProcessDefinitionId(processDefinitionId)).thenReturn(zeroSchedulerList()); + Map result = executorService.execProcessInstance(loginUser, projectName, + processDefinitionId, "2020-01-31 23:00:00,2020-01-01 00:00:00", CommandType.COMPLEMENT_DATA, + null, null, + null, null, 0, + RunMode.RUN_MODE_SERIAL, + Priority.LOW, Constants.DEFAULT_WORKER_GROUP, 110, null); + Assert.assertEquals(Status.START_PROCESS_INSTANCE_ERROR, result.get(Constants.STATUS)); + verify(processService, times(0)).createCommand(any(Command.class)); } /** @@ -188,19 +196,17 @@ public class ExecutorService2Test { */ @Test public void testSerial() throws ParseException { - try { - Mockito.when(processService.queryReleaseSchedulerListByProcessDefinitionId(processDefinitionId)).thenReturn(zeroSchedulerList()); - Map result = executorService.execProcessInstance(loginUser, projectName, - processDefinitionId, cronTime, CommandType.COMPLEMENT_DATA, - null, null, - null, null, 0, - "", "", RunMode.RUN_MODE_SERIAL, - Priority.LOW, Constants.DEFAULT_WORKER_GROUP, 110); - Assert.assertEquals(Status.SUCCESS, result.get(Constants.STATUS)); - verify(processService, times(1)).createCommand(any(Command.class)); - } catch (Exception e) { - //ignore - } + + Mockito.when(processService.queryReleaseSchedulerListByProcessDefinitionId(processDefinitionId)).thenReturn(zeroSchedulerList()); + Map result = executorService.execProcessInstance(loginUser, projectName, + processDefinitionId, cronTime, CommandType.COMPLEMENT_DATA, + null, null, + null, null, 0, + RunMode.RUN_MODE_SERIAL, + Priority.LOW, Constants.DEFAULT_WORKER_GROUP, 110, null); + Assert.assertEquals(Status.SUCCESS, result.get(Constants.STATUS)); + verify(processService, times(1)).createCommand(any(Command.class)); + } /** @@ -208,19 +214,17 @@ public class ExecutorService2Test { */ @Test public void testParallelWithOutSchedule() throws ParseException { - try { - Mockito.when(processService.queryReleaseSchedulerListByProcessDefinitionId(processDefinitionId)).thenReturn(zeroSchedulerList()); - Map result = executorService.execProcessInstance(loginUser, projectName, - processDefinitionId, cronTime, CommandType.COMPLEMENT_DATA, - null, null, - null, null, 0, - "", "", RunMode.RUN_MODE_PARALLEL, - Priority.LOW, Constants.DEFAULT_WORKER_GROUP, 110); - Assert.assertEquals(Status.SUCCESS, result.get(Constants.STATUS)); - verify(processService, times(31)).createCommand(any(Command.class)); - } catch (Exception e) { - //ignore - } + + Mockito.when(processService.queryReleaseSchedulerListByProcessDefinitionId(processDefinitionId)).thenReturn(zeroSchedulerList()); + Map result = executorService.execProcessInstance(loginUser, projectName, + processDefinitionId, cronTime, CommandType.COMPLEMENT_DATA, + null, null, + null, null, 0, + RunMode.RUN_MODE_PARALLEL, + Priority.LOW, Constants.DEFAULT_WORKER_GROUP, 110, null); + Assert.assertEquals(Status.SUCCESS, result.get(Constants.STATUS)); + verify(processService, times(31)).createCommand(any(Command.class)); + } /** @@ -228,31 +232,29 @@ public class ExecutorService2Test { */ @Test public void testParallelWithSchedule() throws ParseException { - try { - Mockito.when(processService.queryReleaseSchedulerListByProcessDefinitionId(processDefinitionId)).thenReturn(oneSchedulerList()); - Map result = executorService.execProcessInstance(loginUser, projectName, - processDefinitionId, cronTime, CommandType.COMPLEMENT_DATA, - null, null, - null, null, 0, - "", "", RunMode.RUN_MODE_PARALLEL, - Priority.LOW, Constants.DEFAULT_WORKER_GROUP, 110); - Assert.assertEquals(Status.SUCCESS, result.get(Constants.STATUS)); - verify(processService, times(15)).createCommand(any(Command.class)); - } catch (Exception e) { - //ignore - } + + Mockito.when(processService.queryReleaseSchedulerListByProcessDefinitionId(processDefinitionId)).thenReturn(oneSchedulerList()); + Map result = executorService.execProcessInstance(loginUser, projectName, + processDefinitionId, cronTime, CommandType.COMPLEMENT_DATA, + null, null, + null, null, 0, + RunMode.RUN_MODE_PARALLEL, + Priority.LOW, Constants.DEFAULT_WORKER_GROUP, 110, null); + Assert.assertEquals(Status.SUCCESS, result.get(Constants.STATUS)); + verify(processService, times(15)).createCommand(any(Command.class)); + } @Test public void testNoMsterServers() throws ParseException { - Mockito.when(monitorService.getServerListFromZK(true)).thenReturn(new ArrayList()); + Mockito.when(monitorService.getServerListFromZK(true)).thenReturn(new ArrayList<>()); Map result = executorService.execProcessInstance(loginUser, projectName, processDefinitionId, cronTime, CommandType.COMPLEMENT_DATA, null, null, null, null, 0, - "", "", RunMode.RUN_MODE_PARALLEL, - Priority.LOW, Constants.DEFAULT_WORKER_GROUP, 110); + RunMode.RUN_MODE_PARALLEL, + Priority.LOW, Constants.DEFAULT_WORKER_GROUP, 110, null); Assert.assertEquals(result.get(Constants.STATUS), Status.MASTER_NOT_EXISTS); } @@ -275,7 +277,7 @@ public class ExecutorService2Test { } - private List zeroSchedulerList() { + private List zeroSchedulerList() { return Collections.EMPTY_LIST; } diff --git a/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/ProcessDefinitionServiceTest.java b/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/ProcessDefinitionServiceTest.java index 89d8b86841..4db533838c 100644 --- a/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/ProcessDefinitionServiceTest.java +++ b/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/ProcessDefinitionServiceTest.java @@ -592,14 +592,14 @@ public class ProcessDefinitionServiceTest { putMsg(result, Status.PROJECT_NOT_FOUNT, projectName); Mockito.when(projectService.checkProjectAndAuth(loginUser, project, projectName)).thenReturn(result); Map map = processDefinitionService.releaseProcessDefinition(loginUser, "project_test1", - 6, ReleaseState.OFFLINE.getCode()); + 6, ReleaseState.OFFLINE); Assert.assertEquals(Status.PROJECT_NOT_FOUNT, map.get(Constants.STATUS)); // project check auth success, processs definition online putMsg(result, Status.SUCCESS, projectName); Mockito.when(processDefineMapper.selectById(46)).thenReturn(getProcessDefinition()); Map onlineRes = processDefinitionService.releaseProcessDefinition( - loginUser, "project_test1", 46, ReleaseState.ONLINE.getCode()); + loginUser, "project_test1", 46, ReleaseState.ONLINE); Assert.assertEquals(Status.SUCCESS, onlineRes.get(Constants.STATUS)); // project check auth success, processs definition online @@ -608,12 +608,12 @@ public class ProcessDefinitionServiceTest { Mockito.when(processDefineMapper.selectById(46)).thenReturn(processDefinition1); Mockito.when(processService.getUserById(1)).thenReturn(loginUser); Map onlineWithResourceRes = processDefinitionService.releaseProcessDefinition( - loginUser, "project_test1", 46, ReleaseState.ONLINE.getCode()); + loginUser, "project_test1", 46, ReleaseState.ONLINE); Assert.assertEquals(Status.SUCCESS, onlineWithResourceRes.get(Constants.STATUS)); // release error code Map failRes = processDefinitionService.releaseProcessDefinition( - loginUser, "project_test1", 46, 2); + loginUser, "project_test1", 46, ReleaseState.getEnum(2)); Assert.assertEquals(Status.REQUEST_PARAMS_NOT_VALID_ERROR, failRes.get(Constants.STATUS)); //FIXME has function exit code 1 when exception diff --git a/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/ProcessDefinitionVersionServiceTest.java b/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/ProcessDefinitionVersionServiceTest.java index 169ef2bcfe..5a8d09fdc5 100644 --- a/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/ProcessDefinitionVersionServiceTest.java +++ b/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/ProcessDefinitionVersionServiceTest.java @@ -216,18 +216,17 @@ public class ProcessDefinitionVersionServiceTest { */ private ProcessDefinitionVersion getProcessDefinitionVersion(ProcessDefinition processDefinition) { return ProcessDefinitionVersion - .newBuilder() - .processDefinitionId(processDefinition.getId()) - .version(1) - .processDefinitionJson(processDefinition.getProcessDefinitionJson()) - .description(processDefinition.getDescription()) - .locations(processDefinition.getLocations()) - .connects(processDefinition.getConnects()) - .timeout(processDefinition.getTimeout()) - .globalParams(processDefinition.getGlobalParams()) - .createTime(processDefinition.getUpdateTime()) - .receivers(processDefinition.getReceivers()) - .receiversCc(processDefinition.getReceiversCc()) + .newBuilder() + .processDefinitionId(processDefinition.getId()) + .version(1) + .processDefinitionJson(processDefinition.getProcessDefinitionJson()) + .description(processDefinition.getDescription()) + .locations(processDefinition.getLocations()) + .connects(processDefinition.getConnects()) + .timeout(processDefinition.getTimeout()) + .globalParams(processDefinition.getGlobalParams()) + .createTime(processDefinition.getUpdateTime()) + .warningGroupId(processDefinition.getWarningGroupId()) .resourceIds(processDefinition.getResourceIds()) .build(); } diff --git a/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/ProcessInstanceServiceTest.java b/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/ProcessInstanceServiceTest.java index 5511f69aeb..de23d7570e 100644 --- a/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/ProcessInstanceServiceTest.java +++ b/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/ProcessInstanceServiceTest.java @@ -211,8 +211,6 @@ public class ProcessInstanceServiceTest { //project auth success ProcessInstance processInstance = getProcessInstance(); - processInstance.setReceivers("xxx@qq.com"); - processInstance.setReceiversCc("xxx@qq.com"); processInstance.setProcessDefinitionId(46); putMsg(result, Status.SUCCESS, projectName); Project project = getProject(projectName); diff --git a/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/ProjectServiceTest.java b/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/ProjectServiceTest.java index cc39925aa5..076eb59b27 100644 --- a/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/ProjectServiceTest.java +++ b/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/ProjectServiceTest.java @@ -32,6 +32,7 @@ import org.apache.dolphinscheduler.dao.mapper.ProjectMapper; import org.apache.dolphinscheduler.dao.mapper.ProjectUserMapper; import java.util.ArrayList; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -319,9 +320,8 @@ public class ProjectServiceTest { @Test public void testQueryAllProjectList() { - - Mockito.when(projectMapper.selectList(null)).thenReturn(getList()); - Mockito.when(processDefinitionMapper.selectList(null)).thenReturn(getProcessDefinitions()); + Mockito.when(processDefinitionMapper.listProjectIds()).thenReturn(getProjectIds()); + Mockito.when(projectMapper.selectBatchIds(getProjectIds())).thenReturn(getList()); Map result = projectService.queryAllProjectList(); logger.info(result.toString()); @@ -387,6 +387,11 @@ public class ProjectServiceTest { return list; } + private List getProjectIds() { + return Collections.singletonList(1); + } + + private String getDesc() { return "projectUserMapper.deleteProjectRelation(projectId,userId)projectUserMappe" + ".deleteProjectRelation(projectId,userId)projectUserMappe" diff --git a/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/TaskInstanceServiceTest.java b/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/TaskInstanceServiceTest.java index 199b34cc1b..b1989b4e31 100644 --- a/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/TaskInstanceServiceTest.java +++ b/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/TaskInstanceServiceTest.java @@ -214,4 +214,48 @@ public class TaskInstanceServiceTest { result.put(Constants.MSG, status.getMsg()); } } -} \ No newline at end of file + + @Test + public void forceTaskSuccess() { + User user = getAdminUser(); + String projectName = "test"; + Project project = getProject(projectName); + int taskId = 1; + TaskInstance task = getTaskInstance(); + + Map mockSuccess = new HashMap<>(5); + putMsg(mockSuccess, Status.SUCCESS); + when(projectMapper.queryByName(projectName)).thenReturn(project); + + // user auth failed + Map mockFailure = new HashMap<>(5); + putMsg(mockFailure, Status.USER_NO_OPERATION_PROJECT_PERM, user.getUserName(), projectName); + when(projectService.checkProjectAndAuth(user, project, projectName)).thenReturn(mockFailure); + Map authFailRes = taskInstanceService.forceTaskSuccess(user, projectName, taskId); + Assert.assertNotSame(Status.SUCCESS, authFailRes.get(Constants.STATUS)); + + // test task not found + when(projectService.checkProjectAndAuth(user, project, projectName)).thenReturn(mockSuccess); + when(taskInstanceMapper.selectById(Mockito.anyInt())).thenReturn(null); + Map taskNotFoundRes = taskInstanceService.forceTaskSuccess(user, projectName, taskId); + Assert.assertEquals(Status.TASK_INSTANCE_NOT_FOUND, taskNotFoundRes.get(Constants.STATUS)); + + // test task instance state error + task.setState(ExecutionStatus.SUCCESS); + when(taskInstanceMapper.selectById(1)).thenReturn(task); + Map taskStateErrorRes = taskInstanceService.forceTaskSuccess(user, projectName, taskId); + Assert.assertEquals(Status.TASK_INSTANCE_STATE_OPERATION_ERROR, taskStateErrorRes.get(Constants.STATUS)); + + // test error + task.setState(ExecutionStatus.FAILURE); + when(taskInstanceMapper.updateById(task)).thenReturn(0); + Map errorRes = taskInstanceService.forceTaskSuccess(user, projectName, taskId); + Assert.assertEquals(Status.FORCE_TASK_SUCCESS_ERROR, errorRes.get(Constants.STATUS)); + + // test success + task.setState(ExecutionStatus.FAILURE); + when(taskInstanceMapper.updateById(task)).thenReturn(1); + Map successRes = taskInstanceService.forceTaskSuccess(user, projectName, taskId); + Assert.assertEquals(Status.SUCCESS, successRes.get(Constants.STATUS)); + } +} diff --git a/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/TenantServiceTest.java b/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/TenantServiceTest.java index 5310eabc1c..2fea76d93f 100644 --- a/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/TenantServiceTest.java +++ b/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/TenantServiceTest.java @@ -35,7 +35,6 @@ import org.apache.dolphinscheduler.dao.mapper.UserMapper; import java.util.ArrayList; import java.util.List; -import java.util.Locale; import java.util.Map; import org.junit.Assert; @@ -81,7 +80,7 @@ public class TenantServiceTest { try { //check tenantCode Map result = - tenantService.createTenant(getLoginUser(), "%!1111", 1, "TenantServiceTest"); + tenantService.createTenant(getLoginUser(), "%!1111", 1, "TenantServiceTest"); logger.info(result.toString()); Assert.assertEquals(Status.VERIFY_OS_TENANT_CODE_ERROR, result.get(Constants.STATUS)); @@ -109,7 +108,7 @@ public class TenantServiceTest { page.setRecords(getList()); page.setTotal(1L); Mockito.when(tenantMapper.queryTenantPaging(Mockito.any(Page.class), Mockito.eq("TenantServiceTest"))) - .thenReturn(page); + .thenReturn(page); Map result = tenantService.queryTenantList(getLoginUser(), "TenantServiceTest", 1, 10); logger.info(result.toString()); PageInfo pageInfo = (PageInfo) result.get(Constants.DATA_LIST); @@ -124,7 +123,7 @@ public class TenantServiceTest { try { // id not exist Map result = - tenantService.updateTenant(getLoginUser(), 912222, tenantCode, 1, "desc"); + tenantService.updateTenant(getLoginUser(), 912222, tenantCode, 1, "desc"); logger.info(result.toString()); // success Assert.assertEquals(Status.TENANT_NOT_EXIST, result.get(Constants.STATUS)); @@ -143,7 +142,7 @@ public class TenantServiceTest { Mockito.when(tenantMapper.queryById(1)).thenReturn(getTenant()); Mockito.when(processInstanceMapper.queryByTenantIdAndStatus(1, Constants.NOT_TERMINATED_STATES)) - .thenReturn(getInstanceList()); + .thenReturn(getInstanceList()); Mockito.when(processDefinitionMapper.queryDefinitionListByTenant(2)).thenReturn(getDefinitionsList()); Mockito.when(userMapper.queryUserListByTenant(3)).thenReturn(getUserList()); @@ -191,14 +190,7 @@ public class TenantServiceTest { Assert.assertEquals(Status.SUCCESS.getMsg(), result.getMsg()); // tenantCode exist result = tenantService.verifyTenantCode(getTenant().getTenantCode()); - String resultString; - if (Locale.SIMPLIFIED_CHINESE.getLanguage().equals(LocaleContextHolder.getLocale().getLanguage())) { - resultString = "操作系统租户[TenantServiceTest]已存在"; - } else { - resultString = "tenant code TenantServiceTest already exists"; - } - logger.info(result.toString()); - Assert.assertEquals(resultString, result.getMsg()); + Assert.assertEquals(Status.OS_TENANT_CODE_EXIST.getCode(), result.getCode().intValue()); } /** diff --git a/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/UiPluginServiceTest.java b/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/UiPluginServiceTest.java new file mode 100644 index 0000000000..95e38b2ab9 --- /dev/null +++ b/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/UiPluginServiceTest.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.api.service; + +import org.apache.dolphinscheduler.api.enums.Status; +import org.apache.dolphinscheduler.api.service.impl.UiPluginServiceImpl; +import org.apache.dolphinscheduler.common.enums.PluginType; +import org.apache.dolphinscheduler.dao.entity.PluginDefine; +import org.apache.dolphinscheduler.dao.mapper.PluginDefineMapper; + +import java.util.Collections; +import java.util.Map; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.MockitoJUnitRunner; + +/** + * UiPluginServiceTest + */ +@RunWith(MockitoJUnitRunner.class) +public class UiPluginServiceTest { + + @InjectMocks + UiPluginServiceImpl uiPluginService; + + @Mock + PluginDefineMapper pluginDefineMapper; + + private PluginDefine pluginDefine; + + @Before + public void before() { + String pluginParams = "[{\"field\":\"receivers\",\"props\":null,\"type\"}]"; + pluginDefine = new PluginDefine("email-alert", "alert", pluginParams); + } + + @Test + public void testQueryPlugins1() { + Map result = uiPluginService.queryUiPluginsByType(PluginType.REGISTER); + Assert.assertEquals(Status.PLUGIN_NOT_A_UI_COMPONENT, result.get("status")); + } + + @Test + public void testQueryPlugins2() { + Map result = uiPluginService.queryUiPluginsByType(PluginType.ALERT); + Mockito.when(pluginDefineMapper.queryByPluginType(PluginType.ALERT.getDesc())).thenReturn(null); + Assert.assertEquals(Status.QUERY_PLUGINS_RESULT_IS_NULL, result.get("status")); + + Mockito.when(pluginDefineMapper.queryByPluginType(PluginType.ALERT.getDesc())).thenReturn(Collections.singletonList(pluginDefine)); + result = uiPluginService.queryUiPluginsByType(PluginType.ALERT); + Assert.assertEquals(Status.SUCCESS, result.get("status")); + } + + @Test + public void testQueryPluginDetailById() { + Mockito.when(pluginDefineMapper.queryDetailById(1)).thenReturn(null); + Map result = uiPluginService.queryUiPluginDetailById(1); + Assert.assertEquals(Status.QUERY_PLUGIN_DETAIL_RESULT_IS_NULL, result.get("status")); + + Mockito.when(pluginDefineMapper.queryDetailById(1)).thenReturn(pluginDefine); + result = uiPluginService.queryUiPluginDetailById(1); + Assert.assertEquals(Status.SUCCESS, result.get("status")); + } + +} diff --git a/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/UserAlertGroupServiceTest.java b/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/UserAlertGroupServiceTest.java deleted file mode 100644 index 24b1d5a98b..0000000000 --- a/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/UserAlertGroupServiceTest.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.dolphinscheduler.api.service; - -import org.apache.dolphinscheduler.dao.mapper.UserAlertGroupMapper; -import static org.junit.Assert.assertEquals; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.ArgumentCaptor; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.Mockito; -import org.mockito.junit.MockitoJUnitRunner; - -/** - * - */ -@RunWith(MockitoJUnitRunner.class) -public class UserAlertGroupServiceTest { - - @InjectMocks - UserAlertGroupService userAlertGroupService; - - @Mock - UserAlertGroupMapper userAlertGroupMapper; - - @Test - public void deleteByAlertGroupId() { - - Integer groupId = 1; - userAlertGroupService.deleteByAlertGroupId(groupId); - ArgumentCaptor argumentCaptor = ArgumentCaptor.forClass(Integer.class); - - Mockito.verify(userAlertGroupMapper).deleteByAlertgroupId(argumentCaptor.capture()); - assertEquals(argumentCaptor.getValue(), groupId); - - } - -} \ No newline at end of file diff --git a/dolphinscheduler-common/pom.xml b/dolphinscheduler-common/pom.xml index 52f2361581..8aeca37e93 100644 --- a/dolphinscheduler-common/pom.xml +++ b/dolphinscheduler-common/pom.xml @@ -32,11 +32,6 @@ 3.1.0 - - org.apache.dolphinscheduler - dolphinscheduler-plugin-api - - org.apache.httpcomponents httpclient diff --git a/dolphinscheduler-common/src/main/java/org/apache/dolphinscheduler/common/Constants.java b/dolphinscheduler-common/src/main/java/org/apache/dolphinscheduler/common/Constants.java index cd6008df5a..02580e6749 100644 --- a/dolphinscheduler-common/src/main/java/org/apache/dolphinscheduler/common/Constants.java +++ b/dolphinscheduler-common/src/main/java/org/apache/dolphinscheduler/common/Constants.java @@ -401,13 +401,17 @@ public final class Constants { */ public static final int SEC_2_MINUTES_TIME_UNIT = 60; - /*** * * rpc port */ public static final int RPC_PORT = 50051; + /*** + * alert rpc port + */ + public static final int ALERT_RPC_PORT = 50052; + /** * forbid running task */ @@ -458,6 +462,8 @@ public final class Constants { public static final String CMD_PARAM_START_NODE_NAMES = "StartNodeNameList"; + public static final String CMD_PARAM_START_PARAMS = "StartParams"; + /** * complement data start date */ @@ -1006,6 +1012,8 @@ public final class Constants { public static final String DOLPHIN_SCHEDULER_PREFERRED_NETWORK_INTERFACE = "dolphin.scheduler.network.interface.preferred"; + public static final String EXCEL_SUFFIX_XLS = ".xls"; + /** * datasource encryption salt */ diff --git a/dolphinscheduler-common/src/main/java/org/apache/dolphinscheduler/common/enums/ExecutionStatus.java b/dolphinscheduler-common/src/main/java/org/apache/dolphinscheduler/common/enums/ExecutionStatus.java index f6ac2cf5ab..2f5c022333 100644 --- a/dolphinscheduler-common/src/main/java/org/apache/dolphinscheduler/common/enums/ExecutionStatus.java +++ b/dolphinscheduler-common/src/main/java/org/apache/dolphinscheduler/common/enums/ExecutionStatus.java @@ -41,6 +41,7 @@ public enum ExecutionStatus { * 10 waiting thread * 11 waiting depend node complete * 12 delay execution + * 13 forced success */ SUBMITTED_SUCCESS(0, "submit success"), RUNNING_EXECUTION(1, "running"), @@ -54,7 +55,8 @@ public enum ExecutionStatus { KILL(9, "kill"), WAITTING_THREAD(10, "waiting thread"), WAITTING_DEPEND(11, "waiting depend node complete"), - DELAY_EXECUTION(12, "delay execution"); + DELAY_EXECUTION(12, "delay execution"), + FORCED_SUCCESS(13, "forced success"); ExecutionStatus(int code, String descp) { this.code = code; @@ -79,7 +81,7 @@ public enum ExecutionStatus { * @return status */ public boolean typeIsSuccess() { - return this == SUCCESS; + return this == SUCCESS || this == FORCED_SUCCESS; } /** diff --git a/dolphinscheduler-common/src/main/java/org/apache/dolphinscheduler/common/enums/PluginType.java b/dolphinscheduler-common/src/main/java/org/apache/dolphinscheduler/common/enums/PluginType.java new file mode 100644 index 0000000000..958e4852d8 --- /dev/null +++ b/dolphinscheduler-common/src/main/java/org/apache/dolphinscheduler/common/enums/PluginType.java @@ -0,0 +1,70 @@ +/* + * 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.enums; + +import java.util.HashMap; + +import com.baomidou.mybatisplus.annotation.EnumValue; + +/** + * PluginType + */ +public enum PluginType { + + ALERT(1, "alert", true), + REGISTER(2, "register", false); + + PluginType(int code, String desc, boolean hasUi) { + this.code = code; + this.desc = desc; + this.hasUi = hasUi; + } + + @EnumValue + private final int code; + private final String desc; + private final boolean hasUi; + + public int getCode() { + return code; + } + + public String getDesc() { + return desc; + } + + public boolean getHasUi() { + return hasUi; + } + + + private static HashMap PLUGIN_TYPE_MAP = new HashMap<>(); + + static { + for (PluginType pluginType : PluginType.values()) { + PLUGIN_TYPE_MAP.put(pluginType.getCode(), pluginType); + } + } + + public static PluginType of(int type) { + if (PLUGIN_TYPE_MAP.containsKey(type)) { + return PLUGIN_TYPE_MAP.get(type); + } + throw new IllegalArgumentException("invalid type : " + type); + } +} diff --git a/dolphinscheduler-common/src/main/java/org/apache/dolphinscheduler/common/plugin/FilePluginManager.java b/dolphinscheduler-common/src/main/java/org/apache/dolphinscheduler/common/plugin/FilePluginManager.java deleted file mode 100644 index cde299f9dd..0000000000 --- a/dolphinscheduler-common/src/main/java/org/apache/dolphinscheduler/common/plugin/FilePluginManager.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.dolphinscheduler.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 pluginMap = new ConcurrentHashMap<>(); - - private Map> pluginLoaderMap = new ConcurrentHashMap<>(); - - private Map classLoaderMap = new ConcurrentHashMap<>(); - - private String[] whitePrefixes; - - private String[] excludePrefixes; - - public FilePluginManager(String dirPath, String[] whitePrefixes, String[] excludePrefixes) { - this.whitePrefixes = whitePrefixes; - this.excludePrefixes = excludePrefixes; - try { - load(dirPath); - } catch (MalformedURLException e) { - logger.error("load plugins failed.", e); - } - } - - private void load(String dirPath) throws MalformedURLException { - logger.info("start to load jar files in {}", dirPath); - if (dirPath == null) { - logger.error("not a valid path - {}", dirPath); - return; - } - File[] files = new File(dirPath).listFiles(); - if (files == null) { - logger.error("not a valid path - {}", dirPath); - return; - } - 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 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 pluginId) { - return pluginMap.get(pluginId); - } - - @Override - public Map findAll() { - return pluginMap; - } - - @Override - public void addPlugin(AlertPlugin plugin) { - pluginMap.put(plugin.getId(), plugin); - } - -} diff --git a/dolphinscheduler-common/src/main/java/org/apache/dolphinscheduler/common/plugin/PluginClassLoader.java b/dolphinscheduler-common/src/main/java/org/apache/dolphinscheduler/common/plugin/PluginClassLoader.java deleted file mode 100644 index 528e83a59c..0000000000 --- a/dolphinscheduler-common/src/main/java/org/apache/dolphinscheduler/common/plugin/PluginClassLoader.java +++ /dev/null @@ -1,154 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.dolphinscheduler.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) { - if (this.whitePrefixes == null) { - return false; - } - for (String whitePrefix : this.whitePrefixes) { - if (name.startsWith(whitePrefix)) { - return true; - } - } - return false; - } - - private boolean fromExcludePrefix(String name) { - if (this.excludePrefixes == null) { - return false; - } - for (String excludePrefix : this.excludePrefixes) { - if (name.startsWith(excludePrefix)) { - return true; - } - } - return false; - } - - @Override - public Enumeration getResources(String name) throws IOException { - List allRes = new LinkedList<>(); - - Enumeration thisRes = findResources(name); - if (thisRes != null) { - while (thisRes.hasMoreElements()) { - allRes.add(thisRes.nextElement()); - } - } - - Enumeration parentRes = super.findResources(name); - if (parentRes != null) { - while (parentRes.hasMoreElements()) { - allRes.add(parentRes.nextElement()); - } - } - - return new Enumeration() { - Iterator 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; - - res = findResource(name); - if (res == null) { - res = super.getResource(name); - } - return res; - } -} diff --git a/dolphinscheduler-common/src/main/java/org/apache/dolphinscheduler/common/shell/ShellExecutor.java b/dolphinscheduler-common/src/main/java/org/apache/dolphinscheduler/common/shell/ShellExecutor.java index 7267447718..8d2b768084 100644 --- a/dolphinscheduler-common/src/main/java/org/apache/dolphinscheduler/common/shell/ShellExecutor.java +++ b/dolphinscheduler-common/src/main/java/org/apache/dolphinscheduler/common/shell/ShellExecutor.java @@ -140,8 +140,8 @@ public class ShellExecutor extends AbstractShell { String line = ""; while ( (nRead = lines.read(buf, 0, buf.length)) > 0 ) { line = new String(buf,0,nRead); + output.append(line); } - output.append(line); } /** diff --git a/dolphinscheduler-common/src/main/java/org/apache/dolphinscheduler/common/task/sql/SqlParameters.java b/dolphinscheduler-common/src/main/java/org/apache/dolphinscheduler/common/task/sql/SqlParameters.java index 4604234e8f..3b5d39f274 100644 --- a/dolphinscheduler-common/src/main/java/org/apache/dolphinscheduler/common/task/sql/SqlParameters.java +++ b/dolphinscheduler-common/src/main/java/org/apache/dolphinscheduler/common/task/sql/SqlParameters.java @@ -14,11 +14,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.dolphinscheduler.common.task.sql; import org.apache.dolphinscheduler.common.process.ResourceInfo; import org.apache.dolphinscheduler.common.task.AbstractParameters; -import org.apache.commons.lang.StringUtils; +import org.apache.dolphinscheduler.common.utils.StringUtils; import java.util.ArrayList; import java.util.List; @@ -75,19 +76,13 @@ public class SqlParameters extends AbstractParameters { private List postStatements; /** - * title - */ - private String title; - - /** - * receivers + * groupId */ - private String receivers; - + private int groupId; /** - * receivers cc + * title */ - private String receiversCc; + private String title; public String getType() { return type; @@ -153,21 +148,6 @@ public class SqlParameters extends AbstractParameters { this.title = title; } - public String getReceivers() { - return receivers; - } - - public void setReceivers(String receivers) { - this.receivers = receivers; - } - - public String getReceiversCc() { - return receiversCc; - } - - public void setReceiversCc(String receiversCc) { - this.receiversCc = receiversCc; - } public List getPreStatements() { return preStatements; } @@ -184,6 +164,14 @@ public class SqlParameters extends AbstractParameters { this.postStatements = postStatements; } + public int getGroupId() { + return groupId; + } + + public void setGroupId(int groupId) { + this.groupId = groupId; + } + @Override public boolean checkParameters() { return datasource != 0 && StringUtils.isNotEmpty(type) && StringUtils.isNotEmpty(sql); @@ -196,19 +184,18 @@ public class SqlParameters extends AbstractParameters { @Override public String toString() { - return "SqlParameters{" + - "type='" + type + '\'' + - ", datasource=" + datasource + - ", sql='" + sql + '\'' + - ", sqlType=" + sqlType + - ", udfs='" + udfs + '\'' + - ", showType='" + showType + '\'' + - ", connParams='" + connParams + '\'' + - ", title='" + title + '\'' + - ", receivers='" + receivers + '\'' + - ", receiversCc='" + receiversCc + '\'' + - ", preStatements=" + preStatements + - ", postStatements=" + postStatements + - '}'; + return "SqlParameters{" + + "type='" + type + '\'' + + ", datasource=" + datasource + + ", sql='" + sql + '\'' + + ", sqlType=" + sqlType + + ", udfs='" + udfs + '\'' + + ", showType='" + showType + '\'' + + ", connParams='" + connParams + '\'' + + ", groupId='" + groupId + '\'' + + ", title='" + title + '\'' + + ", preStatements=" + preStatements + + ", postStatements=" + postStatements + + '}'; } } diff --git a/dolphinscheduler-common/src/main/java/org/apache/dolphinscheduler/common/utils/HiveConfUtils.java b/dolphinscheduler-common/src/main/java/org/apache/dolphinscheduler/common/utils/HiveConfUtils.java new file mode 100644 index 0000000000..b231b4e4b1 --- /dev/null +++ b/dolphinscheduler-common/src/main/java/org/apache/dolphinscheduler/common/utils/HiveConfUtils.java @@ -0,0 +1,87 @@ +/* + * 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.utils; + +import org.apache.hadoop.hive.conf.HiveConf; +import org.apache.hadoop.hive.conf.HiveConf.ConfVars; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * hive conf utils + */ +public class HiveConfUtils { + + private HiveConfUtils() { + throw new UnsupportedOperationException("Construct HiveConfUtils"); + } + + private static class HiveConfHandler { + private static HiveConf singleton; + + private static Map hiveConfVars; + + static { + singleton = new HiveConf(); + hiveConfVars = new HashMap<>(); + Arrays.stream(ConfVars.values()).forEach(confVar -> hiveConfVars.put(confVar.varname,confVar)); + } + } + + /** + * get HiveConf instance + * @return HiveConf hiveConf + */ + public static HiveConf getInstance() { + return HiveConfHandler.singleton; + } + + /** + * get hive conf vars + * @return + */ + public static Map getHiveConfVars() { + return HiveConfHandler.hiveConfVars; + } + + /** + * Determine if it belongs to a hive conf property + * @param conf config + * @return boolean result + */ + public static boolean isHiveConfVar(String conf) { + // the default hive conf var name + String confKey = conf.split("=")[0]; + Map hiveConfVars = HiveConfUtils.getHiveConfVars(); + if (hiveConfVars.get(confKey) != null) { + return true; + } + + // the security authorization hive conf var name + HiveConf hiveConf = HiveConfUtils.getInstance(); + String hiveAuthorizationSqlStdAuthConfigWhitelist = hiveConf.getVar(HiveConf.ConfVars.HIVE_AUTHORIZATION_SQL_STD_AUTH_CONFIG_WHITELIST); + Pattern modWhiteListPattern = Pattern.compile(hiveAuthorizationSqlStdAuthConfigWhitelist); + Matcher matcher = modWhiteListPattern.matcher(confKey); + return matcher.matches(); + } + +} diff --git a/dolphinscheduler-common/src/main/java/org/apache/dolphinscheduler/common/utils/JSONUtils.java b/dolphinscheduler-common/src/main/java/org/apache/dolphinscheduler/common/utils/JSONUtils.java index fc11a2add2..4ab04997d8 100644 --- a/dolphinscheduler-common/src/main/java/org/apache/dolphinscheduler/common/utils/JSONUtils.java +++ b/dolphinscheduler-common/src/main/java/org/apache/dolphinscheduler/common/utils/JSONUtils.java @@ -294,7 +294,11 @@ public class JSONUtils { public static ObjectNode parseObject(String text) { try { - return (ObjectNode) objectMapper.readTree(text); + if (text.isEmpty()) { + return parseObject(text, ObjectNode.class); + } else { + return (ObjectNode) objectMapper.readTree(text); + } } catch (Exception e) { throw new RuntimeException("String json deserialization exception.", e); } diff --git a/dolphinscheduler-common/src/main/java/org/apache/dolphinscheduler/common/utils/StringUtils.java b/dolphinscheduler-common/src/main/java/org/apache/dolphinscheduler/common/utils/StringUtils.java index 256f19905c..6e32d12df3 100644 --- a/dolphinscheduler-common/src/main/java/org/apache/dolphinscheduler/common/utils/StringUtils.java +++ b/dolphinscheduler-common/src/main/java/org/apache/dolphinscheduler/common/utils/StringUtils.java @@ -33,11 +33,17 @@ public class StringUtils { return !isEmpty(cs); } - public static boolean isBlank(String s) { - if (isEmpty(s)) { - return true; + public static boolean isBlank(String str) { + int strLen; + if (str != null && (strLen = str.length()) != 0) { + for (int i = 0; i < strLen; ++i) { + if (!Character.isWhitespace(str.charAt(i))) { + return false; + } + } } - return s.trim().length() == 0; + return true; + } public static boolean isNotBlank(String s) { diff --git a/dolphinscheduler-common/src/main/java/org/apache/dolphinscheduler/common/utils/VarPoolUtils.java b/dolphinscheduler-common/src/main/java/org/apache/dolphinscheduler/common/utils/VarPoolUtils.java index 89a8605a99..3d4f65ab50 100644 --- a/dolphinscheduler-common/src/main/java/org/apache/dolphinscheduler/common/utils/VarPoolUtils.java +++ b/dolphinscheduler-common/src/main/java/org/apache/dolphinscheduler/common/utils/VarPoolUtils.java @@ -63,7 +63,7 @@ public class VarPoolUtils { * @throws ParseException ParseException */ public static void convertVarPoolToMap(Map propToValue, String varPool) throws ParseException { - if (varPool == null || propToValue == null) { + if (propToValue == null || StringUtils.isEmpty(varPool)) { return; } String[] splits = varPool.split("\\$VarPool\\$"); diff --git a/dolphinscheduler-common/src/test/java/org/apache/dolphinscheduler/common/plugin/FilePluginManagerTest.java b/dolphinscheduler-common/src/test/java/org/apache/dolphinscheduler/common/plugin/FilePluginManagerTest.java deleted file mode 100644 index 1a57cb10fa..0000000000 --- a/dolphinscheduler-common/src/test/java/org/apache/dolphinscheduler/common/plugin/FilePluginManagerTest.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.dolphinscheduler.common.plugin; - -import org.apache.dolphinscheduler.plugin.api.AlertPlugin; -import org.apache.dolphinscheduler.plugin.model.AlertInfo; -import org.apache.dolphinscheduler.plugin.model.PluginName; -import org.junit.Before; -import org.junit.Test; - -import java.util.HashMap; -import java.util.Map; - -import static org.junit.Assert.*; - -public class FilePluginManagerTest { - - private FilePluginManager filePluginManager; - private AlertPlugin alertPlugin; - - @Before - public void before() { - filePluginManager = new FilePluginManager(null, null, null); - alertPlugin = new AlertPlugin() { - @Override - public String getId() { - return "test"; - } - - @Override - public PluginName getName() { - return new PluginName().setChinese("ch").setEnglish("en"); - } - - @Override - public Map process(AlertInfo info) { - return new HashMap<>(); - } - }; - } - - @Test - public void findOne() { - filePluginManager.addPlugin(alertPlugin); - assertEquals(alertPlugin, filePluginManager.findOne(alertPlugin.getId())); - } - - @Test - public void findAll() { - assertNotNull(filePluginManager.findAll()); - } - - @Test - public void addPlugin() { - filePluginManager.addPlugin(alertPlugin); - assertNotNull(filePluginManager.findAll()); - } -} \ No newline at end of file diff --git a/dolphinscheduler-common/src/test/java/org/apache/dolphinscheduler/common/plugin/PluginClassLoaderTest.java b/dolphinscheduler-common/src/test/java/org/apache/dolphinscheduler/common/plugin/PluginClassLoaderTest.java deleted file mode 100644 index 8a6bfaee13..0000000000 --- a/dolphinscheduler-common/src/test/java/org/apache/dolphinscheduler/common/plugin/PluginClassLoaderTest.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.dolphinscheduler.common.plugin; - -import org.junit.Before; -import org.junit.Test; - -import java.net.URL; - -import static org.junit.Assert.*; - -public class PluginClassLoaderTest { - - private PluginClassLoader pluginClassLoader; - private ClassLoader parent; - - @Before - public void setUp() { - parent = Thread.currentThread().getContextClassLoader(); - pluginClassLoader = new PluginClassLoader( - new URL[]{}, parent, - null, null); - } - - @Test - public void loadClassNull() { - Class clazz = null; - try { - clazz = pluginClassLoader.loadClass("java.lang.Object"); - } catch (ClassNotFoundException e) { - e.printStackTrace(); - } - assertEquals(null, clazz.getClassLoader()); - } - - @Test - public void loadClassApp() { - Class clazz = null; - try { - clazz = pluginClassLoader.loadClass("org.apache.dolphinscheduler.common.Constants"); - } catch (ClassNotFoundException e) { - e.printStackTrace(); - } - assertEquals(parent, clazz.getClassLoader()); - } - -} \ No newline at end of file diff --git a/dolphinscheduler-common/src/test/java/org/apache/dolphinscheduler/common/utils/HiveConfUtilsTest.java b/dolphinscheduler-common/src/test/java/org/apache/dolphinscheduler/common/utils/HiveConfUtilsTest.java new file mode 100644 index 0000000000..85912d5ff6 --- /dev/null +++ b/dolphinscheduler-common/src/test/java/org/apache/dolphinscheduler/common/utils/HiveConfUtilsTest.java @@ -0,0 +1,47 @@ +/* + * 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.utils; + +import org.junit.Assert; +import org.junit.Test; + +/** + * hive conf utils test + */ +public class HiveConfUtilsTest { + + /** + * test is hive conf var + */ + @Test + public void testIsHiveConfVar() { + + String conf = "hive.exec.script.wrapper=123"; + boolean hiveConfVar = HiveConfUtils.isHiveConfVar(conf); + Assert.assertTrue(hiveConfVar); + + conf = "hive.test.v1=v1"; + hiveConfVar = HiveConfUtils.isHiveConfVar(conf); + Assert.assertFalse(hiveConfVar); + + conf = "tez.queue.name=tezQueue"; + hiveConfVar = HiveConfUtils.isHiveConfVar(conf); + Assert.assertTrue(hiveConfVar); + + } +} diff --git a/dolphinscheduler-common/src/test/java/org/apache/dolphinscheduler/common/utils/HiveConfUtilsTest.java~HEAD b/dolphinscheduler-common/src/test/java/org/apache/dolphinscheduler/common/utils/HiveConfUtilsTest.java~HEAD new file mode 100644 index 0000000000..85912d5ff6 --- /dev/null +++ b/dolphinscheduler-common/src/test/java/org/apache/dolphinscheduler/common/utils/HiveConfUtilsTest.java~HEAD @@ -0,0 +1,47 @@ +/* + * 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.utils; + +import org.junit.Assert; +import org.junit.Test; + +/** + * hive conf utils test + */ +public class HiveConfUtilsTest { + + /** + * test is hive conf var + */ + @Test + public void testIsHiveConfVar() { + + String conf = "hive.exec.script.wrapper=123"; + boolean hiveConfVar = HiveConfUtils.isHiveConfVar(conf); + Assert.assertTrue(hiveConfVar); + + conf = "hive.test.v1=v1"; + hiveConfVar = HiveConfUtils.isHiveConfVar(conf); + Assert.assertFalse(hiveConfVar); + + conf = "tez.queue.name=tezQueue"; + hiveConfVar = HiveConfUtils.isHiveConfVar(conf); + Assert.assertTrue(hiveConfVar); + + } +} diff --git a/dolphinscheduler-common/src/test/java/org/apache/dolphinscheduler/common/utils/HiveConfUtilsTest.java~dev b/dolphinscheduler-common/src/test/java/org/apache/dolphinscheduler/common/utils/HiveConfUtilsTest.java~dev new file mode 100644 index 0000000000..85912d5ff6 --- /dev/null +++ b/dolphinscheduler-common/src/test/java/org/apache/dolphinscheduler/common/utils/HiveConfUtilsTest.java~dev @@ -0,0 +1,47 @@ +/* + * 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.utils; + +import org.junit.Assert; +import org.junit.Test; + +/** + * hive conf utils test + */ +public class HiveConfUtilsTest { + + /** + * test is hive conf var + */ + @Test + public void testIsHiveConfVar() { + + String conf = "hive.exec.script.wrapper=123"; + boolean hiveConfVar = HiveConfUtils.isHiveConfVar(conf); + Assert.assertTrue(hiveConfVar); + + conf = "hive.test.v1=v1"; + hiveConfVar = HiveConfUtils.isHiveConfVar(conf); + Assert.assertFalse(hiveConfVar); + + conf = "tez.queue.name=tezQueue"; + hiveConfVar = HiveConfUtils.isHiveConfVar(conf); + Assert.assertTrue(hiveConfVar); + + } +} diff --git a/dolphinscheduler-common/src/test/java/org/apache/dolphinscheduler/common/utils/ParameterUtilsTest.java b/dolphinscheduler-common/src/test/java/org/apache/dolphinscheduler/common/utils/ParameterUtilsTest.java index 796a5faa45..9ebfd69430 100644 --- a/dolphinscheduler-common/src/test/java/org/apache/dolphinscheduler/common/utils/ParameterUtilsTest.java +++ b/dolphinscheduler-common/src/test/java/org/apache/dolphinscheduler/common/utils/ParameterUtilsTest.java @@ -132,6 +132,26 @@ public class ParameterUtilsTest { String result5 = ParameterUtils.curingGlobalParams(globalParamMap, globalParamList, CommandType.START_CURRENT_TASK_PROCESS, scheduleTime); Assert.assertEquals(result5, JSONUtils.toJsonString(globalParamList)); + + Property testStartParamProperty = new Property("testStartParam", Direct.IN, DataType.VARCHAR, ""); + globalParamList.add(testStartParamProperty); + Property testStartParam2Property = new Property("testStartParam2", Direct.IN, DataType.VARCHAR, "$[yyyy-MM-dd+1]"); + globalParamList.add(testStartParam2Property); + globalParamMap.put("testStartParam", ""); + globalParamMap.put("testStartParam2", "$[yyyy-MM-dd+1]"); + + Map startParamMap = new HashMap<>(2); + startParamMap.put("testStartParam", "$[yyyyMMdd]"); + + for (Map.Entry param : globalParamMap.entrySet()) { + String val = startParamMap.get(param.getKey()); + if (val != null) { + param.setValue(val); + } + } + + String result6 = ParameterUtils.curingGlobalParams(globalParamMap, globalParamList, CommandType.START_CURRENT_TASK_PROCESS, scheduleTime); + Assert.assertTrue(result6.contains("20191220")); } /** diff --git a/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/AlertDao.java b/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/AlertDao.java index cd101f06b6..5b66932a36 100644 --- a/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/AlertDao.java +++ b/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/AlertDao.java @@ -19,24 +19,25 @@ package org.apache.dolphinscheduler.dao; import org.apache.dolphinscheduler.common.enums.AlertEvent; import org.apache.dolphinscheduler.common.enums.AlertStatus; -import org.apache.dolphinscheduler.common.enums.AlertType; import org.apache.dolphinscheduler.common.enums.AlertWarnLevel; -import org.apache.dolphinscheduler.common.enums.ShowType; import org.apache.dolphinscheduler.common.utils.JSONUtils; import org.apache.dolphinscheduler.common.utils.StringUtils; import org.apache.dolphinscheduler.dao.datasource.ConnectionFactory; import org.apache.dolphinscheduler.dao.entity.Alert; +import org.apache.dolphinscheduler.dao.entity.AlertPluginInstance; import org.apache.dolphinscheduler.dao.entity.ProcessAlertContent; import org.apache.dolphinscheduler.dao.entity.ProcessDefinition; import org.apache.dolphinscheduler.dao.entity.ProcessInstance; import org.apache.dolphinscheduler.dao.entity.ServerAlertContent; -import org.apache.dolphinscheduler.dao.entity.User; +import org.apache.dolphinscheduler.dao.mapper.AlertGroupMapper; import org.apache.dolphinscheduler.dao.mapper.AlertMapper; -import org.apache.dolphinscheduler.dao.mapper.UserAlertGroupMapper; +import org.apache.dolphinscheduler.dao.mapper.AlertPluginInstanceMapper; import java.util.ArrayList; +import java.util.Arrays; import java.util.Date; import java.util.List; +import java.util.stream.Collectors; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -52,12 +53,16 @@ public class AlertDao extends AbstractBaseDao { private AlertMapper alertMapper; @Autowired - private UserAlertGroupMapper userAlertGroupMapper; + private AlertPluginInstanceMapper alertPluginInstanceMapper; + + @Autowired + private AlertGroupMapper alertGroupMapper; @Override protected void init() { alertMapper = ConnectionFactory.getInstance().getMapper(AlertMapper.class); - userAlertGroupMapper = ConnectionFactory.getInstance().getMapper(UserAlertGroupMapper.class); + alertPluginInstanceMapper = ConnectionFactory.getInstance().getMapper(AlertPluginInstanceMapper.class); + alertGroupMapper = ConnectionFactory.getInstance().getMapper(AlertGroupMapper.class); } /** @@ -86,25 +91,14 @@ public class AlertDao extends AbstractBaseDao { return alertMapper.updateById(alert); } - /** - * query user list by alert group id - * - * @param alerGroupId alerGroupId - * @return user list - */ - public List queryUserByAlertGroupId(int alerGroupId) { - - return userAlertGroupMapper.listUserByAlertgroupId(alerGroupId); - } - /** * MasterServer or WorkerServer stoped * - * @param alertgroupId alertgroupId + * @param alertGroupId alertGroupId * @param host host * @param serverType serverType */ - public void sendServerStopedAlert(int alertgroupId, String host, String serverType) { + public void sendServerStopedAlert(int alertGroupId, String host, String serverType) { Alert alert = new Alert(); List serverAlertContents = new ArrayList<>(1); ServerAlertContent serverStopAlertContent = ServerAlertContent.newBuilder(). @@ -113,7 +107,7 @@ public class AlertDao extends AbstractBaseDao { serverAlertContents.add(serverStopAlertContent); String content = JSONUtils.toJsonString(serverAlertContents); alert.setTitle("Fault tolerance warning"); - saveTaskTimeoutAlert(alert, content, alertgroupId, null, null); + saveTaskTimeoutAlert(alert, content, alertGroupId); } /** @@ -123,9 +117,7 @@ public class AlertDao extends AbstractBaseDao { * @param processDefinition processDefinition */ public void sendProcessTimeoutAlert(ProcessInstance processInstance, ProcessDefinition processDefinition) { - int alertgroupId = processInstance.getWarningGroupId(); - String receivers = processDefinition.getReceivers(); - String receiversCc = processDefinition.getReceiversCc(); + int alertGroupId = processInstance.getWarningGroupId(); Alert alert = new Alert(); List processAlertContentList = new ArrayList<>(1); ProcessAlertContent processAlertContent = ProcessAlertContent.newBuilder() @@ -137,21 +129,12 @@ public class AlertDao extends AbstractBaseDao { processAlertContentList.add(processAlertContent); String content = JSONUtils.toJsonString(processAlertContentList); alert.setTitle("Process Timeout Warn"); - saveTaskTimeoutAlert(alert, content, alertgroupId, receivers, receiversCc); + saveTaskTimeoutAlert(alert, content, alertGroupId); } - private void saveTaskTimeoutAlert(Alert alert, String content, int alertgroupId, - String receivers, String receiversCc) { - alert.setShowType(ShowType.TABLE); + private void saveTaskTimeoutAlert(Alert alert, String content, int alertGroupId) { + alert.setAlertGroupId(alertGroupId); alert.setContent(content); - alert.setAlertType(AlertType.EMAIL); - alert.setAlertGroupId(alertgroupId); - if (StringUtils.isNotEmpty(receivers)) { - alert.setReceivers(receivers); - } - if (StringUtils.isNotEmpty(receiversCc)) { - alert.setReceiversCc(receiversCc); - } alert.setCreateTime(new Date()); alert.setUpdateTime(new Date()); alertMapper.insert(alert); @@ -160,15 +143,13 @@ public class AlertDao extends AbstractBaseDao { /** * task timeout warn * - * @param alertgroupId alertgroupId - * @param receivers receivers - * @param receiversCc receiversCc + * @param alertGroupId alertGroupId * @param processInstanceId processInstanceId * @param processInstanceName processInstanceName * @param taskId taskId * @param taskName taskName */ - public void sendTaskTimeoutAlert(int alertgroupId, String receivers, String receiversCc, int processInstanceId, + public void sendTaskTimeoutAlert(int alertGroupId, int processInstanceId, String processInstanceName, int taskId, String taskName) { Alert alert = new Alert(); List processAlertContentList = new ArrayList<>(1); @@ -183,7 +164,7 @@ public class AlertDao extends AbstractBaseDao { processAlertContentList.add(processAlertContent); String content = JSONUtils.toJsonString(processAlertContentList); alert.setTitle("Task Timeout Warn"); - saveTaskTimeoutAlert(alert, content, alertgroupId, receivers, receiversCc); + saveTaskTimeoutAlert(alert, content, alertGroupId); } /** @@ -196,22 +177,45 @@ public class AlertDao extends AbstractBaseDao { } /** - * list user information by alert group id + * for test * - * @param alertgroupId alertgroupId - * @return user list + * @return AlertMapper */ - public List listUserByAlertgroupId(int alertgroupId) { - return userAlertGroupMapper.listUserByAlertgroupId(alertgroupId); + public AlertMapper getAlertMapper() { + return alertMapper; } /** - * for test + * list all alert plugin instance by alert group id * - * @return AlertMapper + * @param alertGroupId alert group id + * @return AlertPluginInstance list */ - public AlertMapper getAlertMapper() { - return alertMapper; + public List listInstanceByAlertGroupId(int alertGroupId) { + String alertInstanceIdsParam = alertGroupMapper.queryAlertGroupInstanceIdsById(alertGroupId); + if (StringUtils.isNotBlank(alertInstanceIdsParam)) { + String[] idsArray = alertInstanceIdsParam.split(","); + List ids = Arrays.stream(idsArray) + .map(s -> Integer.parseInt(s.trim())) + .collect(Collectors.toList()); + return alertPluginInstanceMapper.queryByIds(ids); + } + return null; } + public AlertPluginInstanceMapper getAlertPluginInstanceMapper() { + return alertPluginInstanceMapper; + } + + public void setAlertPluginInstanceMapper(AlertPluginInstanceMapper alertPluginInstanceMapper) { + this.alertPluginInstanceMapper = alertPluginInstanceMapper; + } + + public AlertGroupMapper getAlertGroupMapper() { + return alertGroupMapper; + } + + public void setAlertGroupMapper(AlertGroupMapper alertGroupMapper) { + this.alertGroupMapper = alertGroupMapper; + } } diff --git a/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/PluginDao.java b/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/PluginDao.java new file mode 100644 index 0000000000..ab82997bc2 --- /dev/null +++ b/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/PluginDao.java @@ -0,0 +1,96 @@ +/* + * 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.dao; + +import static java.util.Objects.requireNonNull; + +import org.apache.dolphinscheduler.dao.datasource.ConnectionFactory; +import org.apache.dolphinscheduler.dao.entity.PluginDefine; +import org.apache.dolphinscheduler.dao.mapper.PluginDefineMapper; + +import java.util.List; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Component +public class PluginDao extends AbstractBaseDao { + + private final Logger logger = LoggerFactory.getLogger(getClass()); + + @Autowired + private PluginDefineMapper pluginDefineMapper; + + @Override + protected void init() { + pluginDefineMapper = ConnectionFactory.getInstance().getMapper(PluginDefineMapper.class); + } + + /** + * add pluginDefine + * + * @param pluginDefine plugin define entiy + * @return plugin define id + */ + public int addPluginDefine(PluginDefine pluginDefine) { + return pluginDefineMapper.insert(pluginDefine); + } + + /** + * add or update plugin define + * + * @param pluginDefine new pluginDefine + */ + public void addOrUpdatePluginDefine(PluginDefine pluginDefine) { + requireNonNull(pluginDefine, "pluginDefine is null"); + requireNonNull(pluginDefine.getPluginName(), "pluginName is null"); + requireNonNull(pluginDefine.getPluginType(), "pluginType is null"); + + List pluginDefineList = pluginDefineMapper.queryByNameAndType(pluginDefine.getPluginName(), pluginDefine.getPluginType()); + if (pluginDefineList == null || pluginDefineList.size() == 0) { + pluginDefineMapper.insert(pluginDefine); + } else { + PluginDefine currPluginDefine = pluginDefineList.get(0); + if (!currPluginDefine.getPluginParams().equals(pluginDefine.getPluginParams())) { + currPluginDefine.setUpdateTime(pluginDefine.getUpdateTime()); + currPluginDefine.setPluginParams(pluginDefine.getPluginParams()); + pluginDefineMapper.updateById(currPluginDefine); + } + } + } + + /** + * query plugin define by id + * + * @param pluginDefineId plugin define id + * @return PluginDefine + */ + public PluginDefine getPluginDefineById(int pluginDefineId) { + return pluginDefineMapper.selectById(pluginDefineId); + } + + public PluginDefineMapper getPluginDefineMapper() { + return pluginDefineMapper; + } + + public void setPluginDefineMapper(PluginDefineMapper pluginDefineMapper) { + this.pluginDefineMapper = pluginDefineMapper; + } +} diff --git a/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/datasource/BaseDataSource.java b/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/datasource/BaseDataSource.java index 729a17f27b..bb3825fbf9 100644 --- a/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/datasource/BaseDataSource.java +++ b/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/datasource/BaseDataSource.java @@ -14,14 +14,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.dolphinscheduler.dao.datasource; -import java.sql.Connection; -import java.sql.DriverManager; -import java.sql.SQLException; import org.apache.dolphinscheduler.common.enums.DbType; import org.apache.dolphinscheduler.common.utils.CommonUtils; import org.apache.dolphinscheduler.common.utils.StringUtils; + +import java.sql.Connection; +import java.sql.DriverManager; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -30,194 +32,183 @@ import org.slf4j.LoggerFactory; */ public abstract class BaseDataSource { - private static final Logger logger = LoggerFactory.getLogger(BaseDataSource.class); - - /** - * user name - */ - protected String user; - - /** - * user password - */ - protected String password; - - /** - * data source address - */ - private String address; - - /** - * database name - */ - private String database; - - /** - * other connection parameters for the data source - */ - private String other; - - /** - * principal - */ - private String principal; - - public String getPrincipal() { - return principal; - } - - public void setPrincipal(String principal) { - this.principal = principal; - } - - /** - * @return driver class - */ - public abstract String driverClassSelector(); - - /** - * @return db type - */ - public abstract DbType dbTypeSelector(); - - /** - * gets the JDBC url for the data source connection - * @return getJdbcUrl - */ - public String getJdbcUrl() { - StringBuilder jdbcUrl = new StringBuilder(getAddress()); - - appendDatabase(jdbcUrl); - appendPrincipal(jdbcUrl); - appendOther(jdbcUrl); - - return jdbcUrl.toString(); - } - - /** - * append database - * @param jdbcUrl jdbc url - */ - protected void appendDatabase(StringBuilder jdbcUrl) { - if (dbTypeSelector() == DbType.SQLSERVER) { - jdbcUrl.append(";databaseName=").append(getDatabase()); - } else { - if (getAddress().lastIndexOf('/') != (jdbcUrl.length() - 1)) { - jdbcUrl.append("/"); - } - jdbcUrl.append(getDatabase()); - } - } - - /** - * append principal - * @param jdbcUrl jdbc url - */ - private void appendPrincipal(StringBuilder jdbcUrl) { - boolean tag = dbTypeSelector() == DbType.HIVE || dbTypeSelector() == DbType.SPARK; - if (tag && StringUtils.isNotEmpty(getPrincipal())) { - jdbcUrl.append(";principal=").append(getPrincipal()); - } - } - - /** - * append other - * @param jdbcUrl jdbc url - */ - private void appendOther(StringBuilder jdbcUrl) { - String otherParams = filterOther(getOther()); - if (StringUtils.isNotEmpty(otherParams)) { - String separator = ""; - switch (dbTypeSelector()) { - case CLICKHOUSE: - case MYSQL: - case ORACLE: - case POSTGRESQL: - case PRESTO: - separator = "?"; - break; - case DB2: - separator = ":"; - break; - case HIVE: - case SPARK: - case SQLSERVER: - separator = ";"; - break; - default: - logger.error("Db type mismatch!"); - } - jdbcUrl.append(separator).append(otherParams); - } - } - - protected String filterOther(String otherParams){ - return otherParams; - } - - /** - * test whether the data source can be connected successfully - */ - public void isConnectable() { - Connection con = null; - try { - Class.forName(driverClassSelector()); - con = DriverManager.getConnection(getJdbcUrl(), getUser(), getPassword()); - } catch (ClassNotFoundException | SQLException e) { - logger.error("Get connection error: {}", e.getMessage()); - } finally { - if (con != null) { - try { - con.close(); - } catch (SQLException e) { - logger.error(e.getMessage(), e); + private static final Logger logger = LoggerFactory.getLogger(BaseDataSource.class); + + /** + * user name + */ + protected String user; + + /** + * user password + */ + protected String password; + + /** + * data source address + */ + private String address; + + /** + * database name + */ + private String database; + + /** + * other connection parameters for the data source + */ + private String other; + + /** + * principal + */ + private String principal; + + public String getPrincipal() { + return principal; + } + + public void setPrincipal(String principal) { + this.principal = principal; + } + + /** + * @return driver class + */ + public abstract String driverClassSelector(); + + /** + * @return db type + */ + public abstract DbType dbTypeSelector(); + + /** + * gets the JDBC url for the data source connection + * @return getJdbcUrl + */ + public String getJdbcUrl() { + StringBuilder jdbcUrl = new StringBuilder(getAddress()); + + appendDatabase(jdbcUrl); + appendPrincipal(jdbcUrl); + appendOther(jdbcUrl); + + return jdbcUrl.toString(); + } + + /** + * append database + * @param jdbcUrl jdbc url + */ + protected void appendDatabase(StringBuilder jdbcUrl) { + if (dbTypeSelector() == DbType.SQLSERVER) { + jdbcUrl.append(";databaseName=").append(getDatabase()); + } else { + if (getAddress().lastIndexOf('/') != (jdbcUrl.length() - 1)) { + jdbcUrl.append("/"); + } + jdbcUrl.append(getDatabase()); + } + } + + /** + * append principal + * @param jdbcUrl jdbc url + */ + private void appendPrincipal(StringBuilder jdbcUrl) { + boolean tag = dbTypeSelector() == DbType.HIVE || dbTypeSelector() == DbType.SPARK; + if (tag && StringUtils.isNotEmpty(getPrincipal())) { + jdbcUrl.append(";principal=").append(getPrincipal()); } - } } - } - public String getUser() { - return user; - } + /** + * append other + * @param jdbcUrl jdbc url + */ + private void appendOther(StringBuilder jdbcUrl) { + String otherParams = filterOther(getOther()); + if (StringUtils.isNotEmpty(otherParams)) { + String separator = ""; + switch (dbTypeSelector()) { + case CLICKHOUSE: + case MYSQL: + case ORACLE: + case POSTGRESQL: + case PRESTO: + separator = "?"; + break; + case DB2: + separator = ":"; + break; + case HIVE: + case SPARK: + case SQLSERVER: + separator = ";"; + break; + default: + logger.error("Db type mismatch!"); + } + jdbcUrl.append(separator).append(otherParams); + } + } + + /** + * the data source test connection + * @return Connection Connection + * @throws Exception Exception + */ + public Connection getConnection() throws Exception { + Class.forName(driverClassSelector()); + return DriverManager.getConnection(getJdbcUrl(), getUser(), getPassword()); + } + + protected String filterOther(String otherParams) { + return otherParams; + } + + public String getUser() { + return user; + } - public void setUser(String user) { - this.user = user; - } + public void setUser(String user) { + this.user = user; + } - /** - * password need decode - * @return - */ - public String getPassword() { - return CommonUtils.decodePassword(password); - } + /** + * password need decode + * @return + */ + public String getPassword() { + return CommonUtils.decodePassword(password); + } - public void setPassword(String password) { - this.password = password; - } + public void setPassword(String password) { + this.password = password; + } - public void setAddress(String address) { - this.address = address; - } + public void setAddress(String address) { + this.address = address; + } - public String getAddress() { - return address; - } + public String getAddress() { + return address; + } - public String getDatabase() { - return database; - } + public String getDatabase() { + return database; + } - public void setDatabase(String database) { - this.database = database; - } + public void setDatabase(String database) { + this.database = database; + } - public String getOther() { - return other; - } + public String getOther() { + return other; + } - public void setOther(String other) { - this.other = other; - } + public void setOther(String other) { + this.other = other; + } } diff --git a/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/datasource/HiveDataSource.java b/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/datasource/HiveDataSource.java index e64b0395ec..3c087e7f31 100644 --- a/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/datasource/HiveDataSource.java +++ b/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/datasource/HiveDataSource.java @@ -19,78 +19,85 @@ package org.apache.dolphinscheduler.dao.datasource; import org.apache.dolphinscheduler.common.Constants; import org.apache.dolphinscheduler.common.enums.DbType; +import org.apache.dolphinscheduler.common.utils.CommonUtils; +import org.apache.dolphinscheduler.common.utils.HiveConfUtils; import org.apache.dolphinscheduler.common.utils.StringUtils; -import java.util.Set; -import java.util.stream.Collectors; -import java.util.stream.Stream; -import org.apache.hadoop.hive.conf.HiveConf.ConfVars; + +import java.sql.Connection; /** * data source of hive */ public class HiveDataSource extends BaseDataSource { - /** - * gets the JDBC url for the data source connection - * @return jdbc url - */ - @Override - public String driverClassSelector() { - return Constants.ORG_APACHE_HIVE_JDBC_HIVE_DRIVER; - } - - /** - * @return db type - */ - @Override - public DbType dbTypeSelector() { - return DbType.HIVE; - } + /** + * gets the JDBC url for the data source connection + * @return jdbc url + */ + @Override + public String driverClassSelector() { + return Constants.ORG_APACHE_HIVE_JDBC_HIVE_DRIVER; + } - /** - * build hive jdbc params,append : ?hive_conf_list - * - * hive jdbc url template: - * - * jdbc:hive2://:,:/dbName;initFile=;sess_var_list?hive_conf_list#hive_var_list - * - * @param otherParams otherParams - * @return filter otherParams - */ - @Override - protected String filterOther(String otherParams) { - if (StringUtils.isBlank(otherParams)) { - return ""; + /** + * @return db type + */ + @Override + public DbType dbTypeSelector() { + return DbType.HIVE; } - StringBuilder hiveConfListSb = new StringBuilder(); - hiveConfListSb.append("?"); - StringBuilder sessionVarListSb = new StringBuilder(); + /** + * build hive jdbc params,append : ?hive_conf_list + * + * hive jdbc url template: + * + * jdbc:hive2://:,:/dbName;initFile=;sess_var_list?hive_conf_list#hive_var_list + * + * @param otherParams otherParams + * @return filter otherParams + */ + @Override + protected String filterOther(String otherParams) { + if (StringUtils.isBlank(otherParams)) { + return ""; + } - String[] otherArray = otherParams.split(";", -1); + StringBuilder hiveConfListSb = new StringBuilder(); + hiveConfListSb.append("?"); + StringBuilder sessionVarListSb = new StringBuilder(); - // get the default hive conf var name - Set hiveConfSet = Stream.of(ConfVars.values()).map(confVars -> confVars.varname) - .collect(Collectors.toSet()); + String[] otherArray = otherParams.split(";", -1); - for (String conf : otherArray) { - if (hiveConfSet.contains(conf.split("=")[0])) { - hiveConfListSb.append(conf).append(";"); - } else { - sessionVarListSb.append(conf).append(";"); - } - } + for (String conf : otherArray) { + if (HiveConfUtils.isHiveConfVar(conf)) { + hiveConfListSb.append(conf).append(";"); + } else { + sessionVarListSb.append(conf).append(";"); + } + } + + // remove the last ";" + if (sessionVarListSb.length() > 0) { + sessionVarListSb.deleteCharAt(sessionVarListSb.length() - 1); + } + + if (hiveConfListSb.length() > 0) { + hiveConfListSb.deleteCharAt(hiveConfListSb.length() - 1); + } - // remove the last ";" - if (sessionVarListSb.length() > 0) { - sessionVarListSb.deleteCharAt(sessionVarListSb.length() - 1); + return sessionVarListSb.toString() + hiveConfListSb.toString(); } - if (hiveConfListSb.length() > 0) { - hiveConfListSb.deleteCharAt(hiveConfListSb.length() - 1); + /** + * the data source test connection + * @return Connection Connection + * @throws Exception Exception + */ + @Override + public Connection getConnection() throws Exception { + CommonUtils.loadKerberosConf(); + return super.getConnection(); } - return sessionVarListSb.toString() + hiveConfListSb.toString(); - } - } diff --git a/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/datasource/SQLServerDataSource.java b/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/datasource/SQLServerDataSource.java index e4b8f4bf13..78062357e2 100644 --- a/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/datasource/SQLServerDataSource.java +++ b/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/datasource/SQLServerDataSource.java @@ -14,25 +14,18 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.dolphinscheduler.dao.datasource; import org.apache.dolphinscheduler.common.Constants; import org.apache.dolphinscheduler.common.enums.DbType; import org.apache.dolphinscheduler.common.utils.StringUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.sql.Connection; -import java.sql.DriverManager; -import java.sql.SQLException; /** * data source of SQL Server */ public class SQLServerDataSource extends BaseDataSource { - private static final Logger logger = LoggerFactory.getLogger(SQLServerDataSource.class); - /** * gets the JDBC url for the data source connection * @return jdbc url @@ -50,39 +43,18 @@ public class SQLServerDataSource extends BaseDataSource { } /** - * test whether the data source can be connected successfully - */ + * @return driver class + */ @Override - public void isConnectable() { - Connection con = null; - try { - Class.forName(Constants.COM_SQLSERVER_JDBC_DRIVER); - con = DriverManager.getConnection(getJdbcUrl(), getUser(), getPassword()); - } catch (Exception e) { - logger.error("error", e); - } finally { - if (con != null) { - try { - con.close(); - } catch (SQLException e) { - logger.error("SQL Server datasource try conn close conn error", e); - } - } - } + public String driverClassSelector() { + return Constants.COM_SQLSERVER_JDBC_DRIVER; } - /** - * @return driver class - */ - @Override - public String driverClassSelector() { - return Constants.COM_SQLSERVER_JDBC_DRIVER; - } - /** - * @return db type - */ - @Override - public DbType dbTypeSelector() { - return DbType.SQLSERVER; - } + /** + * @return db type + */ + @Override + public DbType dbTypeSelector() { + return DbType.SQLSERVER; + } } diff --git a/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/datasource/SparkDataSource.java b/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/datasource/SparkDataSource.java index 0329ef8400..207ed43942 100644 --- a/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/datasource/SparkDataSource.java +++ b/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/datasource/SparkDataSource.java @@ -14,30 +14,45 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.dolphinscheduler.dao.datasource; import org.apache.dolphinscheduler.common.Constants; import org.apache.dolphinscheduler.common.enums.DbType; +import org.apache.dolphinscheduler.common.utils.CommonUtils; + +import java.sql.Connection; /** * data source of spark */ public class SparkDataSource extends BaseDataSource { - /** - * gets the JDBC url for the data source connection - * @return jdbc url - */ - @Override - public String driverClassSelector() { - return Constants.ORG_APACHE_HIVE_JDBC_HIVE_DRIVER; - } + /** + * gets the JDBC url for the data source connection + * @return jdbc url + */ + @Override + public String driverClassSelector() { + return Constants.ORG_APACHE_HIVE_JDBC_HIVE_DRIVER; + } + + /** + * @return db type + */ + @Override + public DbType dbTypeSelector() { + return DbType.SPARK; + } - /** - * @return db type - */ - @Override - public DbType dbTypeSelector() { - return DbType.SPARK; - } + /** + * the data source test connection + * @return Connection Connection + * @throws Exception Exception + */ + @Override + public Connection getConnection() throws Exception { + CommonUtils.loadKerberosConf(); + return super.getConnection(); + } } diff --git a/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/entity/Alert.java b/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/entity/Alert.java index cfd4995a2b..752ab9d8f9 100644 --- a/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/entity/Alert.java +++ b/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/entity/Alert.java @@ -14,20 +14,20 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.dolphinscheduler.dao.entity; -import com.baomidou.mybatisplus.annotation.IdType; -import com.baomidou.mybatisplus.annotation.TableField; -import com.baomidou.mybatisplus.annotation.TableId; -import com.baomidou.mybatisplus.annotation.TableName; import org.apache.dolphinscheduler.common.enums.AlertStatus; -import org.apache.dolphinscheduler.common.enums.AlertType; -import org.apache.dolphinscheduler.common.enums.ShowType; import java.util.Date; import java.util.HashMap; import java.util.Map; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; + @TableName("t_ds_alert") public class Alert { /** @@ -40,21 +40,13 @@ public class Alert { */ @TableField(value = "title") private String title; - /** - * show_type - */ - @TableField(value = "show_type") - private ShowType showType; + /** * content */ @TableField(value = "content") private String content; - /** - * alert_type - */ - @TableField(value = "alert_type") - private AlertType alertType; + /** * alert_status */ @@ -70,16 +62,7 @@ public class Alert { */ @TableField("alertgroup_id") private int alertGroupId; - /** - * receivers - */ - @TableField("receivers") - private String receivers; - /** - * receivers_cc - */ - @TableField("receivers_cc") - private String receiversCc; + /** * create_time */ @@ -112,14 +95,6 @@ public class Alert { this.title = title; } - public ShowType getShowType() { - return showType; - } - - public void setShowType(ShowType showType) { - this.showType = showType; - } - public String getContent() { return content; } @@ -128,14 +103,6 @@ public class Alert { this.content = content; } - public AlertType getAlertType() { - return alertType; - } - - public void setAlertType(AlertType alertType) { - this.alertType = alertType; - } - public AlertStatus getAlertStatus() { return alertStatus; } @@ -160,22 +127,6 @@ public class Alert { this.alertGroupId = alertGroupId; } - public String getReceivers() { - return receivers; - } - - public void setReceivers(String receivers) { - this.receivers = receivers; - } - - public String getReceiversCc() { - return receiversCc; - } - - public void setReceiversCc(String receiversCc) { - this.receiversCc = receiversCc; - } - public Date getCreateTime() { return createTime; } @@ -220,27 +171,15 @@ public class Alert { if (!title.equals(alert.title)) { return false; } - if (showType != alert.showType) { - return false; - } if (!content.equals(alert.content)) { return false; } - if (alertType != alert.alertType) { - return false; - } if (alertStatus != alert.alertStatus) { return false; } if (!log.equals(alert.log)) { return false; } - if (!receivers.equals(alert.receivers)) { - return false; - } - if (!receiversCc.equals(alert.receiversCc)) { - return false; - } if (!createTime.equals(alert.createTime)) { return false; } @@ -252,14 +191,10 @@ public class Alert { public int hashCode() { int result = id; result = 31 * result + title.hashCode(); - result = 31 * result + showType.hashCode(); result = 31 * result + content.hashCode(); - result = 31 * result + alertType.hashCode(); result = 31 * result + alertStatus.hashCode(); result = 31 * result + log.hashCode(); result = 31 * result + alertGroupId; - result = 31 * result + receivers.hashCode(); - result = 31 * result + receiversCc.hashCode(); result = 31 * result + createTime.hashCode(); result = 31 * result + updateTime.hashCode(); result = 31 * result + info.hashCode(); @@ -268,20 +203,28 @@ public class Alert { @Override public String toString() { - return "Alert{" + - "id=" + id + - ", title='" + title + '\'' + - ", showType=" + showType + - ", content='" + content + '\'' + - ", alertType=" + alertType + - ", alertStatus=" + alertStatus + - ", log='" + log + '\'' + - ", alertGroupId=" + alertGroupId + - ", receivers='" + receivers + '\'' + - ", receiversCc='" + receiversCc + '\'' + - ", createTime=" + createTime + - ", updateTime=" + updateTime + - ", info=" + info + - '}'; + return "Alert{" + + "id=" + + id + + ", title='" + + title + '\'' + + ", content='" + + content + + '\'' + + ", alertStatus=" + + alertStatus + + ", log='" + + log + + '\'' + + ", alertGroupId=" + + alertGroupId + + '\'' + + ", createTime=" + + createTime + + ", updateTime=" + + updateTime + + ", info=" + + info + + '}'; } } diff --git a/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/entity/AlertGroup.java b/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/entity/AlertGroup.java index e35e2f759c..174eb55a3a 100644 --- a/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/entity/AlertGroup.java +++ b/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/entity/AlertGroup.java @@ -14,16 +14,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.dolphinscheduler.dao.entity; -import com.baomidou.mybatisplus.annotation.TableField; -import org.apache.dolphinscheduler.common.enums.AlertType; +import java.util.Date; + import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; -import java.util.Date; - @TableName("t_ds_alertgroup") public class AlertGroup { /** @@ -36,11 +36,10 @@ public class AlertGroup { */ @TableField(value = "group_name") private String groupName; - /** - * group_type - */ - @TableField(value = "group_type") - private AlertType groupType; + + @TableField(value = "alert_instance_ids") + private String alertInstanceIds; + /** * description */ @@ -57,6 +56,12 @@ public class AlertGroup { @TableField(value = "update_time") private Date updateTime; + /** + * create_user_id + */ + @TableField(value = "create_user_id") + private int createUserId; + public int getId() { return id; } @@ -73,14 +78,6 @@ public class AlertGroup { this.groupName = groupName; } - public AlertType getGroupType() { - return groupType; - } - - public void setGroupType(AlertType groupType) { - this.groupType = groupType; - } - public Date getCreateTime() { return createTime; } @@ -105,6 +102,22 @@ public class AlertGroup { this.description = description; } + public int getCreateUserId() { + return createUserId; + } + + public void setCreateUserId(int createUserId) { + this.createUserId = createUserId; + } + + public String getAlertInstanceIds() { + return alertInstanceIds; + } + + public void setAlertInstanceIds(String alertInstanceIds) { + this.alertInstanceIds = alertInstanceIds; + } + @Override public boolean equals(Object o) { if (this == o) { @@ -119,10 +132,13 @@ public class AlertGroup { if (id != that.id) { return false; } + if (createUserId != that.createUserId) { + return false; + } if (groupName != null ? !groupName.equals(that.groupName) : that.groupName != null) { return false; } - if (groupType != that.groupType) { + if (alertInstanceIds != null ? !alertInstanceIds.equals(that.alertInstanceIds) : that.alertInstanceIds != null) { return false; } if (description != null ? !description.equals(that.description) : that.description != null) { @@ -135,8 +151,9 @@ public class AlertGroup { @Override public int hashCode() { int result = id; + result = 31 * result + createUserId; result = 31 * result + (groupName != null ? groupName.hashCode() : 0); - result = 31 * result + (groupType != null ? groupType.hashCode() : 0); + result = 31 * result + (alertInstanceIds != null ? alertInstanceIds.hashCode() : 0); result = 31 * result + (description != null ? description.hashCode() : 0); result = 31 * result + (createTime != null ? createTime.hashCode() : 0); result = 31 * result + (updateTime != null ? updateTime.hashCode() : 0); @@ -145,13 +162,13 @@ public class AlertGroup { @Override public String toString() { - return "AlertGroup{" + - "id=" + id + - ", groupName='" + groupName + '\'' + - ", groupType=" + groupType + - ", description='" + description + '\'' + - ", createTime=" + createTime + - ", updateTime=" + updateTime + - '}'; + return "AlertGroup{" + + "id=" + id + + "createUserId=" + createUserId + + ", groupName='" + groupName + '\'' + + ", description='" + description + '\'' + + ", createTime=" + createTime + + ", updateTime=" + updateTime + + '}'; } } diff --git a/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/entity/UserAlertGroup.java b/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/entity/AlertPluginInstance.java similarity index 51% rename from dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/entity/UserAlertGroup.java rename to dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/entity/AlertPluginInstance.java index 902196d186..5993697a56 100644 --- a/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/entity/UserAlertGroup.java +++ b/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/entity/AlertPluginInstance.java @@ -14,63 +14,71 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.dolphinscheduler.dao.entity; +import java.util.Date; + import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; -import com.fasterxml.jackson.annotation.JsonFormat; - -import java.util.Date; /** - * user alert group + * t_ds_alert_plugin_instance */ -@TableName("t_ds_relation_user_alertgroup") -public class UserAlertGroup { +@TableName("t_ds_alert_plugin_instance") +public class AlertPluginInstance { /** * id */ - @TableId(value="id", type=IdType.AUTO) + @TableId(value = "id", type = IdType.AUTO) private int id; /** - * id + * plugin_define_id */ - @TableField("alertgroup_id") - private int alertgroupId; + @TableField("plugin_define_id") + private int pluginDefineId; /** - * alert group name + * alert plugin instance name */ - @TableField(exist = false) - private String alertgroupName; + @TableField("instance_name") + private String instanceName; /** - * user id + * plugin_instance_params */ - private int userId; + @TableField("plugin_instance_params") + private String pluginInstanceParams; /** - * user name + * create_time */ - @TableField(exist = false) - private String userName; - - /** - * create time - */ - @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone="GMT+8") + @TableField("create_time") private Date createTime; /** - * update time + * update_time */ - @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone="GMT+8") + @TableField("update_time") private Date updateTime; + public AlertPluginInstance() { + this.createTime = new Date(); + this.updateTime = new Date(); + } + + public AlertPluginInstance(int pluginDefineId, String pluginInstanceParams, String instanceName) { + this.pluginDefineId = pluginDefineId; + this.pluginInstanceParams = pluginInstanceParams; + this.createTime = new Date(); + this.updateTime = new Date(); + this.instanceName = instanceName; + } + public int getId() { return id; } @@ -79,20 +87,20 @@ public class UserAlertGroup { this.id = id; } - public int getAlertgroupId() { - return alertgroupId; + public int getPluginDefineId() { + return pluginDefineId; } - public void setAlertgroupId(int alertgroupId) { - this.alertgroupId = alertgroupId; + public void setPluginDefineId(int pluginDefineId) { + this.pluginDefineId = pluginDefineId; } - public int getUserId() { - return userId; + public String getPluginInstanceParams() { + return pluginInstanceParams; } - public void setUserId(int userId) { - this.userId = userId; + public void setPluginInstanceParams(String pluginInstanceParams) { + this.pluginInstanceParams = pluginInstanceParams; } public Date getCreateTime() { @@ -111,32 +119,12 @@ public class UserAlertGroup { this.updateTime = updateTime; } - public String getAlertgroupName() { - return alertgroupName; - } - - public void setAlertgroupName(String alertgroupName) { - this.alertgroupName = alertgroupName; + public String getInstanceName() { + return instanceName; } - public String getUserName() { - return userName; - } - - public void setUserName(String userName) { - this.userName = userName; - } - - @Override - public String toString() { - return "UserAlertGroup{" + - "id=" + id + - ", alertgroupId=" + alertgroupId + - ", alertgroupName='" + alertgroupName + '\'' + - ", userId=" + userId + - ", userName='" + userName + '\'' + - ", createTime=" + createTime + - ", updateTime=" + updateTime + - '}'; + public void setInstanceName(String instanceName) { + this.instanceName = instanceName; } } + diff --git a/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/entity/PluginDefine.java b/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/entity/PluginDefine.java new file mode 100644 index 0000000000..2be8988a08 --- /dev/null +++ b/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/entity/PluginDefine.java @@ -0,0 +1,125 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.dolphinscheduler.dao.entity; + +import java.util.Date; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; + +/** + * t_ds_plugin_define + */ +@TableName("t_ds_plugin_define") +public class PluginDefine { + + /** + * id + */ + @TableId(value = "id", type = IdType.AUTO) + private int id; + + /** + * plugin name + */ + @TableField("plugin_name") + private String pluginName; + + /** + * plugin_type + */ + @TableField("plugin_type") + private String pluginType; + + /** + * plugin_params + */ + @TableField("plugin_params") + private String pluginParams; + + /** + * create_time + */ + @TableField("create_time") + private Date createTime; + + /** + * update_time + */ + @TableField("update_time") + private Date updateTime; + + public PluginDefine(String pluginName, String pluginType, String pluginParams) { + this.pluginName = pluginName; + this.pluginType = pluginType; + this.pluginParams = pluginParams; + this.createTime = new Date(); + this.updateTime = new Date(); + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getPluginName() { + return pluginName; + } + + public void setPluginName(String pluginName) { + this.pluginName = pluginName; + } + + public String getPluginType() { + return pluginType; + } + + public void setPluginType(String pluginType) { + this.pluginType = pluginType; + } + + public String getPluginParams() { + return pluginParams; + } + + public void setPluginParams(String pluginParams) { + this.pluginParams = pluginParams; + } + + public Date getCreateTime() { + return createTime; + } + + public void setCreateTime(Date createTime) { + this.createTime = createTime; + } + + public Date getUpdateTime() { + return updateTime; + } + + public void setUpdateTime(Date updateTime) { + this.updateTime = updateTime; + } +} + diff --git a/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/entity/ProcessAlertContent.java b/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/entity/ProcessAlertContent.java index 71058f4af8..4f46140c21 100644 --- a/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/entity/ProcessAlertContent.java +++ b/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/entity/ProcessAlertContent.java @@ -33,6 +33,12 @@ import com.fasterxml.jackson.annotation.JsonProperty; @JsonInclude(Include.NON_NULL) public class ProcessAlertContent implements Serializable { + @JsonProperty("projectId") + private int projectId; + @JsonProperty("projectName") + private String projectName; + @JsonProperty("owner") + private String owner; @JsonProperty("processId") private int processId; @JsonProperty("processName") @@ -79,6 +85,9 @@ public class ProcessAlertContent implements Serializable { private String logPath; private ProcessAlertContent(Builder builder) { + this.projectId = builder.projectId; + this.projectName = builder.projectName; + this.owner = builder.owner; this.processId = builder.processId; this.processName = builder.processName; this.processType = builder.processType; @@ -107,7 +116,9 @@ public class ProcessAlertContent implements Serializable { } public static class Builder { - + private int projectId; + private String projectName; + private String owner; private int processId; private String processName; private CommandType processType; @@ -129,6 +140,21 @@ public class ProcessAlertContent implements Serializable { private String taskHost; private String logPath; + public Builder projectId(int projectId) { + this.projectId = projectId; + return this; + } + + public Builder projectName(String projectName) { + this.projectName = projectName; + return this; + } + + public Builder owner(String owner) { + this.owner = owner; + return this; + } + public Builder processId(int processId) { this.processId = processId; return this; diff --git a/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/entity/ProcessDefinition.java b/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/entity/ProcessDefinition.java index 56f6cfe905..0c2b844fd1 100644 --- a/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/entity/ProcessDefinition.java +++ b/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/entity/ProcessDefinition.java @@ -139,16 +139,6 @@ public class ProcessDefinition { */ private String connects; - /** - * receivers - */ - private String receivers; - - /** - * receivers cc - */ - private String receiversCc; - /** * schedule release state : online/offline */ @@ -175,6 +165,11 @@ public class ProcessDefinition { */ private String resourceIds; + /** + * warningGroupId + */ + @TableField(exist = false) + private int warningGroupId; public String getName() { return name; @@ -272,7 +267,6 @@ public class ProcessDefinition { this.projectName = projectName; } - public String getGlobalParams() { return globalParams; } @@ -324,22 +318,6 @@ public class ProcessDefinition { this.connects = connects; } - public String getReceivers() { - return receivers; - } - - public void setReceivers(String receivers) { - this.receivers = receivers; - } - - public String getReceiversCc() { - return receiversCc; - } - - public void setReceiversCc(String receiversCc) { - this.receiversCc = receiversCc; - } - public ReleaseState getScheduleReleaseState() { return scheduleReleaseState; } @@ -388,35 +366,42 @@ public class ProcessDefinition { this.modifyBy = modifyBy; } + public int getWarningGroupId() { + return warningGroupId; + } + + public void setWarningGroupId(int warningGroupId) { + this.warningGroupId = warningGroupId; + } + @Override public String toString() { - return "ProcessDefinition{" + - "id=" + id + - ", name='" + name + '\'' + - ", version=" + version + - ", releaseState=" + releaseState + - ", projectId=" + projectId + - ", processDefinitionJson='" + processDefinitionJson + '\'' + - ", description='" + description + '\'' + - ", globalParams='" + globalParams + '\'' + - ", globalParamList=" + globalParamList + - ", globalParamMap=" + globalParamMap + - ", createTime=" + createTime + - ", updateTime=" + updateTime + - ", flag=" + flag + - ", userId=" + userId + - ", userName='" + userName + '\'' + - ", projectName='" + projectName + '\'' + - ", locations='" + locations + '\'' + - ", connects='" + connects + '\'' + - ", receivers='" + receivers + '\'' + - ", receiversCc='" + receiversCc + '\'' + - ", scheduleReleaseState=" + scheduleReleaseState + - ", timeout=" + timeout + - ", tenantId=" + tenantId + - ", modifyBy='" + modifyBy + '\'' + - ", resourceIds='" + resourceIds + '\'' + - '}'; + return "ProcessDefinition{" + + "id=" + id + + ", name='" + name + '\'' + + ", version=" + version + + ", releaseState=" + releaseState + + ", projectId=" + projectId + + ", processDefinitionJson='" + processDefinitionJson + '\'' + + ", description='" + description + '\'' + + ", globalParams='" + globalParams + '\'' + + ", globalParamList=" + globalParamList + + ", globalParamMap=" + globalParamMap + + ", createTime=" + createTime + + ", updateTime=" + updateTime + + ", flag=" + flag + + ", userId=" + userId + + ", userName='" + userName + '\'' + + ", projectName='" + projectName + '\'' + + ", locations='" + locations + '\'' + + ", connects='" + connects + '\'' + + ", scheduleReleaseState=" + scheduleReleaseState + + ", timeout=" + timeout + + ", warningGroupId=" + warningGroupId + + ", tenantId=" + tenantId + + ", modifyBy='" + modifyBy + '\'' + + ", resourceIds='" + resourceIds + '\'' + + '}'; } } diff --git a/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/entity/ProcessDefinitionVersion.java b/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/entity/ProcessDefinitionVersion.java index 26779ba925..1c4d979415 100644 --- a/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/entity/ProcessDefinitionVersion.java +++ b/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/entity/ProcessDefinitionVersion.java @@ -20,6 +20,7 @@ package org.apache.dolphinscheduler.dao.entity; import java.util.Date; import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import com.fasterxml.jackson.annotation.JsonFormat; @@ -57,16 +58,6 @@ public class ProcessDefinitionVersion { */ private String description; - /** - * receivers - */ - private String receivers; - - /** - * receivers cc - */ - private String receiversCc; - /** * process warning time out. unit: minute */ @@ -98,6 +89,13 @@ public class ProcessDefinitionVersion { */ private String connects; + + /** + * warningGroupId + */ + @TableField(exist = false) + private int warningGroupId; + public String getGlobalParams() { return globalParams; } @@ -170,22 +168,6 @@ public class ProcessDefinitionVersion { this.connects = connects; } - public String getReceivers() { - return receivers; - } - - public void setReceivers(String receivers) { - this.receivers = receivers; - } - - public String getReceiversCc() { - return receiversCc; - } - - public void setReceiversCc(String receiversCc) { - this.receiversCc = receiversCc; - } - public int getTimeout() { return timeout; } @@ -202,23 +184,30 @@ public class ProcessDefinitionVersion { this.resourceIds = resourceIds; } + public int getWarningGroupId() { + return warningGroupId; + } + + public void setWarningGroupId(int warningGroupId) { + this.warningGroupId = warningGroupId; + } + @Override public String toString() { return "ProcessDefinitionVersion{" - + "id=" + id - + ", processDefinitionId=" + processDefinitionId - + ", version=" + version - + ", processDefinitionJson='" + processDefinitionJson + '\'' - + ", description='" + description + '\'' - + ", globalParams='" + globalParams + '\'' - + ", createTime=" + createTime - + ", locations='" + locations + '\'' - + ", connects='" + connects + '\'' - + ", receivers='" + receivers + '\'' - + ", receiversCc='" + receiversCc + '\'' - + ", timeout=" + timeout - + ", resourceIds='" + resourceIds + '\'' - + '}'; + + "id=" + id + + ", processDefinitionId=" + processDefinitionId + + ", version=" + version + + ", processDefinitionJson='" + processDefinitionJson + '\'' + + ", description='" + description + '\'' + + ", globalParams='" + globalParams + '\'' + + ", createTime=" + createTime + + ", locations='" + locations + '\'' + + ", connects='" + connects + '\'' + + ", timeout=" + timeout + + ", warningGroupId=" + warningGroupId + + ", resourceIds='" + resourceIds + '\'' + + '}'; } public static Builder newBuilder() { @@ -235,9 +224,8 @@ public class ProcessDefinitionVersion { private Date createTime; private String locations; private String connects; - private String receivers; - private String receiversCc; private int timeout; + private int warningGroupId; private String resourceIds; private Builder() { @@ -288,18 +276,13 @@ public class ProcessDefinitionVersion { return this; } - public Builder receivers(String receivers) { - this.receivers = receivers; - return this; - } - - public Builder receiversCc(String receiversCc) { - this.receiversCc = receiversCc; + public Builder timeout(int timeout) { + this.timeout = timeout; return this; } - public Builder timeout(int timeout) { - this.timeout = timeout; + public Builder warningGroupId(int warningGroupId) { + this.warningGroupId = warningGroupId; return this; } @@ -319,9 +302,8 @@ public class ProcessDefinitionVersion { processDefinitionVersion.setCreateTime(createTime); processDefinitionVersion.setLocations(locations); processDefinitionVersion.setConnects(connects); - processDefinitionVersion.setReceivers(receivers); - processDefinitionVersion.setReceiversCc(receiversCc); processDefinitionVersion.setTimeout(timeout); + processDefinitionVersion.setWarningGroupId(warningGroupId); processDefinitionVersion.setResourceIds(resourceIds); return processDefinitionVersion; } diff --git a/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/entity/ProcessInstance.java b/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/entity/ProcessInstance.java index e3a3f11386..f1d43a353b 100644 --- a/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/entity/ProcessInstance.java +++ b/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/entity/ProcessInstance.java @@ -228,18 +228,6 @@ public class ProcessInstance { * varPool string */ private String varPool; - - /** - * receivers for api - */ - @TableField(exist = false) - private String receivers; - - /** - * receivers cc for api - */ - @TableField(exist = false) - private String receiversCc; public ProcessInstance() { @@ -268,7 +256,7 @@ public class ProcessInstance { public void setVarPool(String varPool) { this.varPool = varPool; } - + public ProcessDefinition getProcessDefinition() { return processDefinition; } @@ -591,22 +579,6 @@ public class ProcessInstance { this.tenantId = tenantId; } - public String getReceivers() { - return receivers; - } - - public void setReceivers(String receivers) { - this.receivers = receivers; - } - - public String getReceiversCc() { - return receiversCc; - } - - public void setReceiversCc(String receiversCc) { - this.receiversCc = receiversCc; - } - @Override public String toString() { return "ProcessInstance{" @@ -679,12 +651,6 @@ public class ProcessInstance { + timeout + ", tenantId=" + tenantId - + ", receivers='" - + receivers - + '\'' - + ", receiversCc='" - + receiversCc - + '\'' + '}'; } diff --git a/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/mapper/AlertGroupMapper.java b/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/mapper/AlertGroupMapper.java index 0fd26b9f79..b206a787b6 100644 --- a/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/mapper/AlertGroupMapper.java +++ b/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/mapper/AlertGroupMapper.java @@ -55,17 +55,16 @@ public interface AlertGroupMapper extends BaseMapper { */ List queryByUserId(@Param("userId") int userId); - /** - * query by alert type - * @param alertType alertType + * query all group list * @return alertgroup list */ - List queryByAlertType(@Param("alertType") AlertType alertType); + List queryAllGroupList(); /** - * query all group list - * @return alertgroup list + * queryAlertGroupInstanceIdsById + * @param alertGroupId + * @return */ - List queryAllGroupList(); + String queryAlertGroupInstanceIdsById(@Param("alertGroupId") int alertGroupId); } diff --git a/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/mapper/UserAlertGroupMapper.java b/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/mapper/AlertPluginInstanceMapper.java similarity index 62% rename from dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/mapper/UserAlertGroupMapper.java rename to dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/mapper/AlertPluginInstanceMapper.java index f374c202cd..618a8774c7 100644 --- a/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/mapper/UserAlertGroupMapper.java +++ b/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/mapper/AlertPluginInstanceMapper.java @@ -14,32 +14,34 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.dolphinscheduler.dao.mapper; -import org.apache.dolphinscheduler.dao.entity.User; -import org.apache.dolphinscheduler.dao.entity.UserAlertGroup; -import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.dolphinscheduler.dao.entity.AlertPluginInstance; + import org.apache.ibatis.annotations.Param; import java.util.List; -/** - * user alertgroup relation mapper interface - */ -public interface UserAlertGroupMapper extends BaseMapper { +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +public interface AlertPluginInstanceMapper extends BaseMapper { /** - * delete user alertgroup relation by alertgroupId - * @param alertgroupId alertgroupId - * @return delete result + * query all alert plugin instance + * + * @return AlertPluginInstance list */ - int deleteByAlertgroupId(@Param("alertgroupId") int alertgroupId); + List queryAllAlertPluginInstanceList(); /** - * list user by alertgroupId - * @param alertgroupId alertgroupId - * @return user list + * query by alert group id + * + * @param ids + * @return AlertPluginInstance list */ - List listUserByAlertgroupId(@Param("alertgroupId") int alertgroupId); + List queryByIds(@Param("ids") List ids); + + List queryByInstanceName(@Param("instanceName")String instanceName); } diff --git a/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/mapper/PluginDefineMapper.java b/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/mapper/PluginDefineMapper.java new file mode 100644 index 0000000000..e2d08b5222 --- /dev/null +++ b/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/mapper/PluginDefineMapper.java @@ -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.dao.mapper; + +import org.apache.dolphinscheduler.dao.entity.PluginDefine; + +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +public interface PluginDefineMapper extends BaseMapper { + + /** + * query all plugin define + * + * @return PluginDefine list + */ + List queryAllPluginDefineList(); + + /** + * query by plugin type + * + * @param pluginType pluginType + * @return PluginDefine list + */ + List queryByPluginType(@Param("pluginType") String pluginType); + + /** + * query detail by id + * + * @param id id + * @return PluginDefineDetail + */ + PluginDefine queryDetailById(@Param("id") int id); + + /** + * query by name and type + * + * @param pluginName + * @param pluginType + * @return + */ + List queryByNameAndType(@Param("pluginName") String pluginName, @Param("pluginType") String pluginType); +} diff --git a/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/mapper/ProcessDefinitionMapper.java b/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/mapper/ProcessDefinitionMapper.java index 621ec43c27..36c988776f 100644 --- a/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/mapper/ProcessDefinitionMapper.java +++ b/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/mapper/ProcessDefinitionMapper.java @@ -138,4 +138,10 @@ public interface ProcessDefinitionMapper extends BaseMapper { * @param version version */ void updateVersionByProcessDefinitionId(@Param("processDefinitionId") int processDefinitionId, @Param("version") long version); + + /** + * list all project ids + * @return project ids list + */ + List listProjectIds(); } diff --git a/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/mapper/ProjectMapper.java b/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/mapper/ProjectMapper.java index b24fd2ede4..872d53fd92 100644 --- a/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/mapper/ProjectMapper.java +++ b/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/mapper/ProjectMapper.java @@ -14,15 +14,19 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.dolphinscheduler.dao.mapper; import org.apache.dolphinscheduler.dao.entity.Project; -import com.baomidou.mybatisplus.core.mapper.BaseMapper; -import com.baomidou.mybatisplus.core.metadata.IPage; +import org.apache.dolphinscheduler.dao.entity.ProjectUser; + import org.apache.ibatis.annotations.Param; import java.util.List; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.core.metadata.IPage; + /** * project mapper interface */ @@ -81,4 +85,11 @@ public interface ProjectMapper extends BaseMapper { */ List queryProjectCreatedAndAuthorizedByUserId(@Param("userId") int userId); + /** + * query project name and user name by processInstanceId. + * @param processInstanceId processInstanceId + * @return projectName and userName + */ + ProjectUser queryProjectWithUserByProcessInstanceId(@Param("processInstanceId") int processInstanceId); + } diff --git a/dolphinscheduler-dao/src/main/resources/datasource.properties b/dolphinscheduler-dao/src/main/resources/datasource.properties index f8fe97bcea..fa07c6a6d3 100644 --- a/dolphinscheduler-dao/src/main/resources/datasource.properties +++ b/dolphinscheduler-dao/src/main/resources/datasource.properties @@ -15,9 +15,15 @@ # limitations under the License. # +# mysql +#spring.datasource.driver-class-name=com.mysql.jdbc.Driver +#spring.datasource.url=jdbc:mysql://localhost:3306/dolphinscheduler?useUnicode=true&characterEncoding=UTF-8 +#spring.datasource.username=root +#spring.datasource.password=123456 + # postgresql spring.datasource.driver-class-name=org.postgresql.Driver -spring.datasource.url=jdbc:postgresql://localhost:5432/dolphinscheduler +spring.datasource.url=jdbc:postgresql://127.0.0.1:5432/dolphinscheduler spring.datasource.username=test spring.datasource.password=test diff --git a/dolphinscheduler-dao/src/main/resources/org/apache/dolphinscheduler/dao/mapper/AlertGroupMapper.xml b/dolphinscheduler-dao/src/main/resources/org/apache/dolphinscheduler/dao/mapper/AlertGroupMapper.xml index 08d1ea365f..e60dedfd6c 100644 --- a/dolphinscheduler-dao/src/main/resources/org/apache/dolphinscheduler/dao/mapper/AlertGroupMapper.xml +++ b/dolphinscheduler-dao/src/main/resources/org/apache/dolphinscheduler/dao/mapper/AlertGroupMapper.xml @@ -19,7 +19,8 @@ - id, group_name, group_type, description, create_time, update_time + id + , group_name, description,alert_instance_ids, create_user_id,create_time, update_time - + - + + + \ No newline at end of file diff --git a/dolphinscheduler-dao/src/main/resources/org/apache/dolphinscheduler/dao/mapper/AlertMapper.xml b/dolphinscheduler-dao/src/main/resources/org/apache/dolphinscheduler/dao/mapper/AlertMapper.xml index 036e0ed0fe..9be5c7c784 100644 --- a/dolphinscheduler-dao/src/main/resources/org/apache/dolphinscheduler/dao/mapper/AlertMapper.xml +++ b/dolphinscheduler-dao/src/main/resources/org/apache/dolphinscheduler/dao/mapper/AlertMapper.xml @@ -19,8 +19,9 @@ - id, title, show_type, content, alert_type, alert_status, log, - alertgroup_id, receivers, receivers_cc, create_time, update_time + id + , title, content, alert_status, log, + alertgroup_id, create_time, update_time - SELECT - - - - FROM t_ds_relation_user_alertgroup g_u - JOIN t_ds_user u on g_u.user_id = u.id - WHERE g_u.alertgroup_id = #{alertgroupId} + + + + + - + + + + \ No newline at end of file diff --git a/dolphinscheduler-dao/src/main/resources/org/apache/dolphinscheduler/dao/mapper/DataSourceMapper.xml b/dolphinscheduler-dao/src/main/resources/org/apache/dolphinscheduler/dao/mapper/DataSourceMapper.xml index b4606db00a..337c41e4b2 100644 --- a/dolphinscheduler-dao/src/main/resources/org/apache/dolphinscheduler/dao/mapper/DataSourceMapper.xml +++ b/dolphinscheduler-dao/src/main/resources/org/apache/dolphinscheduler/dao/mapper/DataSourceMapper.xml @@ -40,11 +40,14 @@ + select * + from t_ds_plugin_define + where 1=1 + + + + + + + + + \ No newline at end of file diff --git a/dolphinscheduler-dao/src/main/resources/org/apache/dolphinscheduler/dao/mapper/ProcessDefinitionMapper.xml b/dolphinscheduler-dao/src/main/resources/org/apache/dolphinscheduler/dao/mapper/ProcessDefinitionMapper.xml index f1179c2b33..a24fd294a7 100644 --- a/dolphinscheduler-dao/src/main/resources/org/apache/dolphinscheduler/dao/mapper/ProcessDefinitionMapper.xml +++ b/dolphinscheduler-dao/src/main/resources/org/apache/dolphinscheduler/dao/mapper/ProcessDefinitionMapper.xml @@ -19,13 +19,14 @@ - id, name, version, release_state, project_id, user_id, process_definition_json, description, - global_params, flag, locations, connects, receivers, receivers_cc, create_time, timeout, + id + , name, version, release_state, project_id, user_id, process_definition_json, description, + global_params, flag, locations, connects, warning_group_id, create_time, timeout, tenant_id, update_time, modify_by, resource_ids SELECT td.id, td.name, td.version, td.release_state, td.project_id, td.user_id, td.description, td.global_params, - td.flag, td.receivers, td.receivers_cc, td.timeout, td.tenant_id, td.modify_by, td.update_time, td.create_time, + td.flag, td.warning_group_id, td.timeout, td.tenant_id, td.modify_by, td.update_time, td.create_time, sc.schedule_release_state, tu.user_name FROM t_ds_process_definition td left join (select process_definition_id,release_state as schedule_release_state from t_ds_schedules group by @@ -101,7 +102,7 @@ + + + update t_ds_process_definition set version = #{version} diff --git a/dolphinscheduler-dao/src/main/resources/org/apache/dolphinscheduler/dao/mapper/ProcessDefinitionVersionMapper.xml b/dolphinscheduler-dao/src/main/resources/org/apache/dolphinscheduler/dao/mapper/ProcessDefinitionVersionMapper.xml index 6c5b029373..ff20e23246 100644 --- a/dolphinscheduler-dao/src/main/resources/org/apache/dolphinscheduler/dao/mapper/ProcessDefinitionVersionMapper.xml +++ b/dolphinscheduler-dao/src/main/resources/org/apache/dolphinscheduler/dao/mapper/ProcessDefinitionVersionMapper.xml @@ -19,8 +19,9 @@ - id, process_definition_id, version, process_definition_json, description, global_params,locations,connects, receivers, - receivers_cc, create_time, timeout, resource_ids + id + , process_definition_id, version, process_definition_json, description, global_params,locations,connects, + warning_group_id, create_time, timeout, resource_ids + + diff --git a/dolphinscheduler-dao/src/main/resources/org/apache/dolphinscheduler/dao/mapper/ResourceMapper.xml b/dolphinscheduler-dao/src/main/resources/org/apache/dolphinscheduler/dao/mapper/ResourceMapper.xml index 6ad350835f..6f53979b1e 100644 --- a/dolphinscheduler-dao/src/main/resources/org/apache/dolphinscheduler/dao/mapper/ResourceMapper.xml +++ b/dolphinscheduler-dao/src/main/resources/org/apache/dolphinscheduler/dao/mapper/ResourceMapper.xml @@ -60,17 +60,20 @@