Browse Source
* [Improvement][dao]When I search for the keyword description, the web UI shows empty (#5952) * [Bug][WorkerServer] SqlTask NullPointerException #5549 * [Improvement][dao]When I search for the keyword Modify User, the web UI shows empty #5428 * [Improvement][dao]When I search for the keyword Modify User, the web UI shows empty #5428 * [Improvement][dao]When I search for the keyword Modify User, the web UI shows empty #5428 * [Improvement][dao]When I search for the keyword Modify User, the web UI shows empty #5428 * [Improvement][dao]When I search for the keyword Modify User, the web UI shows empty #5428 * [Improvement][dao]When I search for the keyword Modify User, the web UI shows empty #5428 * [Improvement][dao]When I search for the keyword description, the web UI shows empty #5428 * fix the readme typing issue (#5998) * Fix unchecked type conversions * Use indentation level reported by checkstyle * Reorganize CI workflows to fasten the wasted time and resources (#6011) * Add standalone server module to make it easier to develop (#6022) * Task node of SWITCH (#5939) * [Feature-#5273][server-master] Task node of SWITCH (#5922) Co-authored-by: wangxj <wangxj31> * remove description of bonecp (#6030) Co-authored-by: shaojwu <shaojwu@ebay.com> * [Improvement][Api Module]split alert group list-paging interface (#5941) * [Improvement][Api Module]split alert group list-paging interface * [FIX-#6007]Wrong complement date (#6026) * [FIX-#6007]Wrong complement date * [style]Wrong complement date * [Improvement-6024][dist] Remove useless packaging commands (#6029) ·Remove useless packaging commands in dolphinscheduler-bin.xml This closes #6024 Co-authored-by: mask <liuhu@zhiyoutec.com> * [FIX-5908][MasterServer] When executing an compensation task, the execution thread would have a NPE (#5909) * fix the npe in MasterExec * fix the compile error * Add `.asf.yaml` to easily set the GitHub metadata (#6035) * fix dead server cannot stop (#6046) * Enhancement Translation (#6042) * replaced Loading... with i18n * modified Edit zh_CN translation * Delete zh_CN.js Co-authored-by: David <dailidong66@gmail.com> * fix bug #6053 zh_CN.js is lost * [Feature][Plugin]Task * fix license head * fix code style * fix code style * fix build err Co-authored-by: didiaode18 <563646039@qq.com> Co-authored-by: Roy <yongjuncao1213@gmail.com> Co-authored-by: lyxell <alyxell@kth.se> Co-authored-by: Wenjun Ruan <wenjun@apache.org> Co-authored-by: kezhenxu94 <kezhenxu94@apache.org> Co-authored-by: myangle1120 <942542838@qq.com> Co-authored-by: wangxj3 <857234426@qq.com> Co-authored-by: gabry.wu <gabrywu@apache.org> Co-authored-by: shaojwu <shaojwu@ebay.com> Co-authored-by: Shukun Zhang <60541766+andream7@users.noreply.github.com> Co-authored-by: linquan <1175687813@qq.com> Co-authored-by: mask <39329477+Narcasserun@users.noreply.github.com> Co-authored-by: mask <liuhu@zhiyoutec.com> Co-authored-by: kyoty <echohlne@gmail.com> Co-authored-by: RichardStark <49977764+RichardStark@users.noreply.github.com> Co-authored-by: David <dailidong66@gmail.com> Co-authored-by: lenboo <baoliang.leon@gmail.com>2.0.7-release
Kirs
3 years ago
committed by
GitHub
176 changed files with 3004 additions and 8502 deletions
@ -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. |
||||
# |
||||
|
||||
github: |
||||
description: | |
||||
Apache DolphinScheduler is a distributed and extensible workflow scheduler platform with powerful DAG |
||||
visual interfaces, dedicated to solving complex job dependencies in the data pipeline and providing |
||||
various types of jobs available `out of the box`. |
||||
homepage: https://dolphinscheduler.apache.org/ |
||||
labels: |
||||
- airflow |
||||
- schedule |
||||
- job-scheduler |
||||
- oozie |
||||
- task-scheduler |
||||
- azkaban |
||||
- distributed-schedule-system |
||||
- workflow-scheduling-system |
||||
- etl-dependency |
||||
- workflow-platform |
||||
- cronjob-schedule |
||||
- job-schedule |
||||
- task-schedule |
||||
- workflow-schedule |
||||
- data-schedule |
||||
enabled_merge_buttons: |
||||
squash: true |
||||
merge: false |
||||
rebase: false |
||||
protected_branches: |
||||
dev: |
||||
required_status_checks: |
||||
strict: true |
@ -0,0 +1 @@
|
||||
Subproject commit 2fc905b1875f2e6b91c4201a4dc6eaa21b86547e |
@ -0,0 +1,53 @@
|
||||
# |
||||
# 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. |
||||
# |
||||
|
||||
name: "Sanity Check" |
||||
|
||||
description: | |
||||
Action to perform some very basic lightweight checks, like code styles, license headers, etc., |
||||
and fail fast to avoid wasting resources running heavyweight checks, like unit tests, e2e tests. |
||||
|
||||
inputs: |
||||
token: |
||||
description: 'The GitHub API token' |
||||
required: false |
||||
|
||||
runs: |
||||
using: "composite" |
||||
steps: |
||||
- name: Check License Header |
||||
uses: apache/skywalking-eyes@a63f4afcc287dfb3727ecc45a4afc55a5e69c15f |
||||
|
||||
- uses: ./.github/actions/reviewdog-setup |
||||
with: |
||||
reviewdog_version: v0.10.2 |
||||
|
||||
- shell: bash |
||||
run: ./mvnw -B -q checkstyle:checkstyle-aggregate |
||||
|
||||
- shell: bash |
||||
env: |
||||
REVIEWDOG_GITHUB_API_TOKEN: ${{ inputs.token }} |
||||
run: | |
||||
if [[ -n "${{ inputs.token }}" ]]; then |
||||
reviewdog -f=checkstyle \ |
||||
-reporter="github-pr-check" \ |
||||
-filter-mode="added" \ |
||||
-fail-on-error="true" < target/checkstyle-result.xml |
||||
fi |
@ -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.common.task.switchtask; |
||||
|
||||
import org.apache.dolphinscheduler.common.enums.DependentRelation; |
||||
import org.apache.dolphinscheduler.common.process.ResourceInfo; |
||||
import org.apache.dolphinscheduler.common.task.AbstractParameters; |
||||
|
||||
import java.util.ArrayList; |
||||
import java.util.List; |
||||
|
||||
public class SwitchParameters extends AbstractParameters { |
||||
|
||||
private DependentRelation dependRelation; |
||||
private String relation; |
||||
private List<String> nextNode; |
||||
|
||||
@Override |
||||
public boolean checkParameters() { |
||||
return true; |
||||
} |
||||
|
||||
@Override |
||||
public List<ResourceInfo> getResourceFilesList() { |
||||
return new ArrayList<>(); |
||||
} |
||||
|
||||
private int resultConditionLocation; |
||||
private List<SwitchResultVo> dependTaskList; |
||||
|
||||
public DependentRelation getDependRelation() { |
||||
return dependRelation; |
||||
} |
||||
|
||||
public void setDependRelation(DependentRelation dependRelation) { |
||||
this.dependRelation = dependRelation; |
||||
} |
||||
|
||||
public int getResultConditionLocation() { |
||||
return resultConditionLocation; |
||||
} |
||||
|
||||
public void setResultConditionLocation(int resultConditionLocation) { |
||||
this.resultConditionLocation = resultConditionLocation; |
||||
} |
||||
|
||||
public String getRelation() { |
||||
return relation; |
||||
} |
||||
|
||||
public void setRelation(String relation) { |
||||
this.relation = relation; |
||||
} |
||||
|
||||
public List<SwitchResultVo> getDependTaskList() { |
||||
return dependTaskList; |
||||
} |
||||
|
||||
public void setDependTaskList(List<SwitchResultVo> dependTaskList) { |
||||
this.dependTaskList = dependTaskList; |
||||
} |
||||
|
||||
public List<String> getNextNode() { |
||||
return nextNode; |
||||
} |
||||
|
||||
public void setNextNode(Object nextNode) { |
||||
if (nextNode instanceof String) { |
||||
List<String> nextNodeList = new ArrayList<>(); |
||||
nextNodeList.add(String.valueOf(nextNode)); |
||||
this.nextNode = nextNodeList; |
||||
} else { |
||||
this.nextNode = (ArrayList) nextNode; |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,49 @@
|
||||
/* |
||||
* 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.task.switchtask; |
||||
|
||||
import java.util.ArrayList; |
||||
import java.util.List; |
||||
|
||||
public class SwitchResultVo { |
||||
|
||||
private String condition; |
||||
private List<String> nextNode; |
||||
|
||||
public String getCondition() { |
||||
return condition; |
||||
} |
||||
|
||||
public void setCondition(String condition) { |
||||
this.condition = condition; |
||||
} |
||||
|
||||
public List<String> getNextNode() { |
||||
return nextNode; |
||||
} |
||||
|
||||
public void setNextNode(Object nextNode) { |
||||
if (nextNode instanceof String) { |
||||
List<String> nextNodeList = new ArrayList<>(); |
||||
nextNodeList.add(String.valueOf(nextNode)); |
||||
this.nextNode = nextNodeList; |
||||
} else { |
||||
this.nextNode = (ArrayList) nextNode; |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,180 @@
|
||||
/* |
||||
* 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.server.master.runner; |
||||
|
||||
import org.apache.dolphinscheduler.common.enums.DependResult; |
||||
import org.apache.dolphinscheduler.common.enums.ExecutionStatus; |
||||
import org.apache.dolphinscheduler.common.process.Property; |
||||
import org.apache.dolphinscheduler.common.task.switchtask.SwitchParameters; |
||||
import org.apache.dolphinscheduler.common.task.switchtask.SwitchResultVo; |
||||
import org.apache.dolphinscheduler.common.utils.JSONUtils; |
||||
import org.apache.dolphinscheduler.common.utils.NetUtils; |
||||
import org.apache.dolphinscheduler.common.utils.StringUtils; |
||||
import org.apache.dolphinscheduler.dao.entity.TaskInstance; |
||||
import org.apache.dolphinscheduler.server.utils.LogUtils; |
||||
import org.apache.dolphinscheduler.server.utils.SwitchTaskUtils; |
||||
|
||||
import java.util.Date; |
||||
import java.util.List; |
||||
import java.util.Map; |
||||
import java.util.concurrent.ConcurrentHashMap; |
||||
import java.util.regex.Matcher; |
||||
import java.util.regex.Pattern; |
||||
import java.util.stream.Collectors; |
||||
|
||||
public class SwitchTaskExecThread extends MasterBaseTaskExecThread { |
||||
|
||||
protected final String rgex = "['\"]*\\$\\{(.*?)\\}['\"]*"; |
||||
|
||||
/** |
||||
* complete task map |
||||
*/ |
||||
private Map<String, ExecutionStatus> completeTaskList = new ConcurrentHashMap<>(); |
||||
|
||||
/** |
||||
* switch result |
||||
*/ |
||||
private DependResult conditionResult; |
||||
|
||||
/** |
||||
* constructor of MasterBaseTaskExecThread |
||||
* |
||||
* @param taskInstance task instance |
||||
*/ |
||||
public SwitchTaskExecThread(TaskInstance taskInstance) { |
||||
super(taskInstance); |
||||
taskInstance.setStartTime(new Date()); |
||||
} |
||||
|
||||
@Override |
||||
public Boolean submitWaitComplete() { |
||||
try { |
||||
this.taskInstance = submit(); |
||||
logger.info("taskInstance submit end"); |
||||
Thread.currentThread().setName(getThreadName()); |
||||
initTaskParameters(); |
||||
logger.info("switch task start"); |
||||
waitTaskQuit(); |
||||
updateTaskState(); |
||||
} catch (Exception e) { |
||||
logger.error("switch task run exception", e); |
||||
} |
||||
return true; |
||||
} |
||||
|
||||
private void waitTaskQuit() { |
||||
List<TaskInstance> taskInstances = processService.findValidTaskListByProcessId( |
||||
taskInstance.getProcessInstanceId() |
||||
); |
||||
for (TaskInstance task : taskInstances) { |
||||
completeTaskList.putIfAbsent(task.getName(), task.getState()); |
||||
} |
||||
|
||||
SwitchParameters switchParameters = taskInstance.getSwitchDependency(); |
||||
List<SwitchResultVo> switchResultVos = switchParameters.getDependTaskList(); |
||||
SwitchResultVo switchResultVo = new SwitchResultVo(); |
||||
switchResultVo.setNextNode(switchParameters.getNextNode()); |
||||
switchResultVos.add(switchResultVo); |
||||
int finalConditionLocation = switchResultVos.size() - 1; |
||||
int i = 0; |
||||
conditionResult = DependResult.SUCCESS; |
||||
for (SwitchResultVo info : switchResultVos) { |
||||
logger.info("the {} execution ", (i + 1)); |
||||
logger.info("original condition sentence:{}", info.getCondition()); |
||||
if (StringUtils.isEmpty(info.getCondition())) { |
||||
finalConditionLocation = i; |
||||
break; |
||||
} |
||||
String content = setTaskParams(info.getCondition().replaceAll("'", "\""), rgex); |
||||
logger.info("format condition sentence::{}", content); |
||||
Boolean result = null; |
||||
try { |
||||
result = SwitchTaskUtils.evaluate(content); |
||||
} catch (Exception e) { |
||||
logger.info("error sentence : {}", content); |
||||
conditionResult = DependResult.FAILED; |
||||
//result = false;
|
||||
break; |
||||
} |
||||
logger.info("condition result : {}", result); |
||||
if (result) { |
||||
finalConditionLocation = i; |
||||
break; |
||||
} |
||||
i++; |
||||
} |
||||
switchParameters.setDependTaskList(switchResultVos); |
||||
switchParameters.setResultConditionLocation(finalConditionLocation); |
||||
taskInstance.setSwitchDependency(switchParameters); |
||||
|
||||
//conditionResult = DependResult.SUCCESS;
|
||||
logger.info("the switch task depend result : {}", conditionResult); |
||||
} |
||||
|
||||
/** |
||||
* update task state |
||||
*/ |
||||
private void updateTaskState() { |
||||
ExecutionStatus status; |
||||
if (this.cancel) { |
||||
status = ExecutionStatus.KILL; |
||||
} else { |
||||
status = (conditionResult == DependResult.SUCCESS) ? ExecutionStatus.SUCCESS : ExecutionStatus.FAILURE; |
||||
} |
||||
taskInstance.setEndTime(new Date()); |
||||
taskInstance.setState(status); |
||||
processService.updateTaskInstance(taskInstance); |
||||
} |
||||
|
||||
private void initTaskParameters() { |
||||
taskInstance.setLogPath(LogUtils.getTaskLogPath(processInstance.getProcessDefinitionCode(), |
||||
processInstance.getProcessDefinitionVersion(), |
||||
taskInstance.getProcessInstanceId(), |
||||
taskInstance.getId())); |
||||
this.taskInstance.setStartTime(new Date()); |
||||
this.taskInstance.setHost(NetUtils.getAddr(masterConfig.getListenPort())); |
||||
this.taskInstance.setState(ExecutionStatus.RUNNING_EXECUTION); |
||||
this.processService.saveTaskInstance(taskInstance); |
||||
} |
||||
|
||||
public String setTaskParams(String content, String rgex) { |
||||
Pattern pattern = Pattern.compile(rgex); |
||||
Matcher m = pattern.matcher(content); |
||||
Map<String, Property> globalParams = JSONUtils.toList(processInstance.getGlobalParams(), Property.class).stream().collect(Collectors.toMap(Property::getProp, Property -> Property)); |
||||
Map<String, Property> varParams = JSONUtils.toList(taskInstance.getVarPool(), Property.class).stream().collect(Collectors.toMap(Property::getProp, Property -> Property)); |
||||
if (varParams.size() > 0) { |
||||
varParams.putAll(globalParams); |
||||
globalParams = varParams; |
||||
} |
||||
while (m.find()) { |
||||
String paramName = m.group(1); |
||||
Property property = globalParams.get(paramName); |
||||
if (property == null) { |
||||
return ""; |
||||
} |
||||
String value = property.getValue(); |
||||
if (!org.apache.commons.lang.math.NumberUtils.isNumber(value)) { |
||||
value = "\"" + value + "\""; |
||||
} |
||||
logger.info("paramName:{},paramValue{}", paramName, value); |
||||
content = content.replace("${" + paramName + "}", value); |
||||
} |
||||
return content; |
||||
} |
||||
|
||||
} |
@ -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.server.utils; |
||||
|
||||
import javax.script.ScriptEngine; |
||||
import javax.script.ScriptEngineManager; |
||||
import javax.script.ScriptException; |
||||
|
||||
public class SwitchTaskUtils { |
||||
private static ScriptEngineManager manager; |
||||
private static ScriptEngine engine; |
||||
|
||||
static { |
||||
manager = new ScriptEngineManager(); |
||||
engine = manager.getEngineByName("js"); |
||||
} |
||||
|
||||
public static boolean evaluate(String expression) throws ScriptException { |
||||
Object result = engine.eval(expression); |
||||
return (Boolean) result; |
||||
} |
||||
|
||||
} |
@ -1,553 +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.server.worker.task; |
||||
|
||||
import static org.apache.dolphinscheduler.common.Constants.EXIT_CODE_FAILURE; |
||||
import static org.apache.dolphinscheduler.common.Constants.EXIT_CODE_KILL; |
||||
import static org.apache.dolphinscheduler.common.Constants.EXIT_CODE_SUCCESS; |
||||
|
||||
import org.apache.dolphinscheduler.common.Constants; |
||||
import org.apache.dolphinscheduler.common.enums.ExecutionStatus; |
||||
import org.apache.dolphinscheduler.common.thread.Stopper; |
||||
import org.apache.dolphinscheduler.common.thread.ThreadUtils; |
||||
import org.apache.dolphinscheduler.common.utils.CommonUtils; |
||||
import org.apache.dolphinscheduler.common.utils.HadoopUtils; |
||||
import org.apache.dolphinscheduler.common.utils.LoggerUtils; |
||||
import org.apache.dolphinscheduler.common.utils.OSUtils; |
||||
import org.apache.dolphinscheduler.common.utils.StringUtils; |
||||
import org.apache.dolphinscheduler.server.entity.TaskExecutionContext; |
||||
import org.apache.dolphinscheduler.server.utils.ProcessUtils; |
||||
import org.apache.dolphinscheduler.server.worker.cache.TaskExecutionContextCacheManager; |
||||
import org.apache.dolphinscheduler.server.worker.cache.impl.TaskExecutionContextCacheManagerImpl; |
||||
import org.apache.dolphinscheduler.service.bean.SpringApplicationContext; |
||||
|
||||
import java.io.BufferedReader; |
||||
import java.io.File; |
||||
import java.io.FileInputStream; |
||||
import java.io.IOException; |
||||
import java.io.InputStreamReader; |
||||
import java.lang.reflect.Field; |
||||
import java.nio.charset.StandardCharsets; |
||||
import java.util.ArrayList; |
||||
import java.util.Collections; |
||||
import java.util.LinkedList; |
||||
import java.util.List; |
||||
import java.util.concurrent.ExecutorService; |
||||
import java.util.concurrent.LinkedBlockingQueue; |
||||
import java.util.concurrent.TimeUnit; |
||||
import java.util.function.Consumer; |
||||
import java.util.regex.Matcher; |
||||
import java.util.regex.Pattern; |
||||
|
||||
import org.slf4j.Logger; |
||||
|
||||
/** |
||||
* abstract command executor |
||||
*/ |
||||
public abstract class AbstractCommandExecutor { |
||||
/** |
||||
* rules for extracting application ID |
||||
*/ |
||||
protected static final Pattern APPLICATION_REGEX = Pattern.compile(Constants.APPLICATION_REGEX); |
||||
|
||||
protected StringBuilder varPool = new StringBuilder(); |
||||
/** |
||||
* process |
||||
*/ |
||||
private Process process; |
||||
|
||||
/** |
||||
* log handler |
||||
*/ |
||||
protected Consumer<LinkedBlockingQueue<String>> logHandler; |
||||
|
||||
/** |
||||
* logger |
||||
*/ |
||||
protected Logger logger; |
||||
|
||||
/** |
||||
* log collection |
||||
*/ |
||||
protected final LinkedBlockingQueue<String> logBuffer; |
||||
|
||||
protected boolean logOutputIsScuccess = false; |
||||
|
||||
/** |
||||
* taskExecutionContext |
||||
*/ |
||||
protected TaskExecutionContext taskExecutionContext; |
||||
|
||||
/** |
||||
* taskExecutionContextCacheManager |
||||
*/ |
||||
private TaskExecutionContextCacheManager taskExecutionContextCacheManager; |
||||
|
||||
public AbstractCommandExecutor(Consumer<LinkedBlockingQueue<String>> logHandler, |
||||
TaskExecutionContext taskExecutionContext, |
||||
Logger logger) { |
||||
this.logHandler = logHandler; |
||||
this.taskExecutionContext = taskExecutionContext; |
||||
this.logger = logger; |
||||
this.logBuffer = new LinkedBlockingQueue<>(); |
||||
this.taskExecutionContextCacheManager = SpringApplicationContext.getBean(TaskExecutionContextCacheManagerImpl.class); |
||||
} |
||||
|
||||
/** |
||||
* build process |
||||
* |
||||
* @param commandFile command file |
||||
* @throws IOException IO Exception |
||||
*/ |
||||
private void buildProcess(String commandFile) throws IOException { |
||||
// setting up user to run commands
|
||||
List<String> command = new LinkedList<>(); |
||||
|
||||
//init process builder
|
||||
ProcessBuilder processBuilder = new ProcessBuilder(); |
||||
// setting up a working directory
|
||||
processBuilder.directory(new File(taskExecutionContext.getExecutePath())); |
||||
// merge error information to standard output stream
|
||||
processBuilder.redirectErrorStream(true); |
||||
|
||||
// setting up user to run commands
|
||||
if (!OSUtils.isWindows() && CommonUtils.isSudoEnable()) { |
||||
command.add("sudo"); |
||||
command.add("-u"); |
||||
command.add(taskExecutionContext.getTenantCode()); |
||||
} |
||||
command.add(commandInterpreter()); |
||||
command.addAll(commandOptions()); |
||||
command.add(commandFile); |
||||
|
||||
// setting commands
|
||||
processBuilder.command(command); |
||||
process = processBuilder.start(); |
||||
|
||||
// print command
|
||||
printCommand(command); |
||||
} |
||||
|
||||
/** |
||||
* task specific execution logic |
||||
* |
||||
* @param execCommand execCommand |
||||
* @return CommandExecuteResult |
||||
* @throws Exception if error throws Exception |
||||
*/ |
||||
public CommandExecuteResult run(String execCommand) throws Exception { |
||||
|
||||
CommandExecuteResult result = new CommandExecuteResult(); |
||||
|
||||
int taskInstanceId = taskExecutionContext.getTaskInstanceId(); |
||||
// If the task has been killed, then the task in the cache is null
|
||||
if (null == taskExecutionContextCacheManager.getByTaskInstanceId(taskInstanceId)) { |
||||
result.setExitStatusCode(EXIT_CODE_KILL); |
||||
return result; |
||||
} |
||||
if (StringUtils.isEmpty(execCommand)) { |
||||
taskExecutionContextCacheManager.removeByTaskInstanceId(taskInstanceId); |
||||
return result; |
||||
} |
||||
|
||||
String commandFilePath = buildCommandFilePath(); |
||||
|
||||
// create command file if not exists
|
||||
createCommandFileIfNotExists(execCommand, commandFilePath); |
||||
|
||||
//build process
|
||||
buildProcess(commandFilePath); |
||||
|
||||
// parse process output
|
||||
parseProcessOutput(process); |
||||
|
||||
Integer processId = getProcessId(process); |
||||
|
||||
result.setProcessId(processId); |
||||
|
||||
// cache processId
|
||||
taskExecutionContext.setProcessId(processId); |
||||
boolean updateTaskExecutionContextStatus = taskExecutionContextCacheManager.updateTaskExecutionContext(taskExecutionContext); |
||||
if (Boolean.FALSE.equals(updateTaskExecutionContextStatus)) { |
||||
ProcessUtils.kill(taskExecutionContext); |
||||
result.setExitStatusCode(EXIT_CODE_KILL); |
||||
return result; |
||||
} |
||||
|
||||
// print process id
|
||||
logger.info("process start, process id is: {}", processId); |
||||
|
||||
// if timeout occurs, exit directly
|
||||
long remainTime = getRemaintime(); |
||||
|
||||
// waiting for the run to finish
|
||||
boolean status = process.waitFor(remainTime, TimeUnit.SECONDS); |
||||
|
||||
// if SHELL task exit
|
||||
if (status) { |
||||
// set appIds
|
||||
List<String> appIds = getAppIds(taskExecutionContext.getLogPath()); |
||||
result.setAppIds(String.join(Constants.COMMA, appIds)); |
||||
|
||||
// SHELL task state
|
||||
result.setExitStatusCode(process.exitValue()); |
||||
|
||||
// if yarn task , yarn state is final state
|
||||
if (process.exitValue() == 0) { |
||||
result.setExitStatusCode(isSuccessOfYarnState(appIds) ? EXIT_CODE_SUCCESS : EXIT_CODE_FAILURE); |
||||
} |
||||
} else { |
||||
logger.error("process has failure , exitStatusCode:{}, processExitValue:{}, ready to kill ...", |
||||
result.getExitStatusCode(), process.exitValue()); |
||||
ProcessUtils.kill(taskExecutionContext); |
||||
result.setExitStatusCode(EXIT_CODE_FAILURE); |
||||
} |
||||
|
||||
logger.info("process has exited, execute path:{}, processId:{} ,exitStatusCode:{} ,processWaitForStatus:{} ,processExitValue:{}", |
||||
taskExecutionContext.getExecutePath(), processId, result.getExitStatusCode(), status, process.exitValue()); |
||||
|
||||
return result; |
||||
} |
||||
|
||||
public String getVarPool() { |
||||
return varPool.toString(); |
||||
} |
||||
|
||||
/** |
||||
* cancel application |
||||
* |
||||
* @throws Exception exception |
||||
*/ |
||||
public void cancelApplication() throws Exception { |
||||
if (process == null) { |
||||
return; |
||||
} |
||||
|
||||
// clear log
|
||||
clear(); |
||||
|
||||
int processId = getProcessId(process); |
||||
|
||||
logger.info("cancel process: {}", processId); |
||||
|
||||
// kill , waiting for completion
|
||||
boolean killed = softKill(processId); |
||||
|
||||
if (!killed) { |
||||
// hard kill
|
||||
hardKill(processId); |
||||
|
||||
// destory
|
||||
process.destroy(); |
||||
|
||||
process = null; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* soft kill |
||||
* |
||||
* @param processId process id |
||||
* @return process is alive |
||||
* @throws InterruptedException interrupted exception |
||||
*/ |
||||
private boolean softKill(int processId) { |
||||
|
||||
if (processId != 0 && process.isAlive()) { |
||||
try { |
||||
// sudo -u user command to run command
|
||||
String cmd = String.format("kill %d", processId); |
||||
cmd = OSUtils.getSudoCmd(taskExecutionContext.getTenantCode(), cmd); |
||||
logger.info("soft kill task:{}, process id:{}, cmd:{}", taskExecutionContext.getTaskAppId(), processId, cmd); |
||||
|
||||
Runtime.getRuntime().exec(cmd); |
||||
} catch (IOException e) { |
||||
logger.info("kill attempt failed", e); |
||||
} |
||||
} |
||||
|
||||
return !process.isAlive(); |
||||
} |
||||
|
||||
/** |
||||
* hard kill |
||||
* |
||||
* @param processId process id |
||||
*/ |
||||
private void hardKill(int processId) { |
||||
if (processId != 0 && process.isAlive()) { |
||||
try { |
||||
String cmd = String.format("kill -9 %d", processId); |
||||
cmd = OSUtils.getSudoCmd(taskExecutionContext.getTenantCode(), cmd); |
||||
logger.info("hard kill task:{}, process id:{}, cmd:{}", taskExecutionContext.getTaskAppId(), processId, cmd); |
||||
|
||||
Runtime.getRuntime().exec(cmd); |
||||
} catch (IOException e) { |
||||
logger.error("kill attempt failed ", e); |
||||
} |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* print command |
||||
* |
||||
* @param commands process builder |
||||
*/ |
||||
private void printCommand(List<String> commands) { |
||||
String cmdStr; |
||||
|
||||
try { |
||||
cmdStr = ProcessUtils.buildCommandStr(commands); |
||||
logger.info("task run command:\n{}", cmdStr); |
||||
} catch (Exception e) { |
||||
logger.error(e.getMessage(), e); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* clear |
||||
*/ |
||||
private void clear() { |
||||
|
||||
LinkedBlockingQueue<String> markerLog = new LinkedBlockingQueue<>(); |
||||
markerLog.add(ch.qos.logback.classic.ClassicConstants.FINALIZE_SESSION_MARKER.toString()); |
||||
|
||||
if (!logBuffer.isEmpty()) { |
||||
// log handle
|
||||
logHandler.accept(logBuffer); |
||||
} |
||||
logHandler.accept(markerLog); |
||||
} |
||||
|
||||
/** |
||||
* get the standard output of the process |
||||
* |
||||
* @param process process |
||||
*/ |
||||
private void parseProcessOutput(Process process) { |
||||
String threadLoggerInfoName = String.format(LoggerUtils.TASK_LOGGER_THREAD_NAME + "-%s", taskExecutionContext.getTaskAppId()); |
||||
ExecutorService getOutputLogService = ThreadUtils.newDaemonSingleThreadExecutor(threadLoggerInfoName + "-" + "getOutputLogService"); |
||||
getOutputLogService.submit(() -> { |
||||
try (BufferedReader inReader = new BufferedReader(new InputStreamReader(process.getInputStream()))) { |
||||
String line; |
||||
logBuffer.add("welcome to use bigdata scheduling system..."); |
||||
while ((line = inReader.readLine()) != null) { |
||||
if (line.startsWith("${setValue(")) { |
||||
varPool.append(line.substring("${setValue(".length(), line.length() - 2)); |
||||
varPool.append("$VarPool$"); |
||||
} else { |
||||
logBuffer.add(line); |
||||
} |
||||
} |
||||
} catch (Exception e) { |
||||
logger.error(e.getMessage(), e); |
||||
} finally { |
||||
logOutputIsScuccess = true; |
||||
} |
||||
}); |
||||
getOutputLogService.shutdown(); |
||||
|
||||
ExecutorService parseProcessOutputExecutorService = ThreadUtils.newDaemonSingleThreadExecutor(threadLoggerInfoName); |
||||
parseProcessOutputExecutorService.submit(() -> { |
||||
try { |
||||
long lastFlushTime = System.currentTimeMillis(); |
||||
while (logBuffer.size() > 0 || !logOutputIsScuccess) { |
||||
if (logBuffer.size() > 0) { |
||||
lastFlushTime = flush(lastFlushTime); |
||||
} else { |
||||
Thread.sleep(Constants.DEFAULT_LOG_FLUSH_INTERVAL); |
||||
} |
||||
} |
||||
} catch (Exception e) { |
||||
logger.error(e.getMessage(), e); |
||||
} finally { |
||||
clear(); |
||||
} |
||||
}); |
||||
parseProcessOutputExecutorService.shutdown(); |
||||
} |
||||
|
||||
/** |
||||
* check yarn state |
||||
* |
||||
* @param appIds application id list |
||||
* @return is success of yarn task state |
||||
*/ |
||||
public boolean isSuccessOfYarnState(List<String> appIds) { |
||||
boolean result = true; |
||||
try { |
||||
for (String appId : appIds) { |
||||
logger.info("check yarn application status, appId:{}", appId); |
||||
while (Stopper.isRunning()) { |
||||
ExecutionStatus applicationStatus = HadoopUtils.getInstance().getApplicationStatus(appId); |
||||
if (logger.isDebugEnabled()) { |
||||
logger.debug("check yarn application status, appId:{}, final state:{}", appId, applicationStatus.name()); |
||||
} |
||||
if (applicationStatus.equals(ExecutionStatus.FAILURE) |
||||
|| applicationStatus.equals(ExecutionStatus.KILL)) { |
||||
return false; |
||||
} |
||||
|
||||
if (applicationStatus.equals(ExecutionStatus.SUCCESS)) { |
||||
break; |
||||
} |
||||
ThreadUtils.sleep(Constants.SLEEP_TIME_MILLIS); |
||||
} |
||||
} |
||||
} catch (Exception e) { |
||||
logger.error("yarn applications: {} , query status failed, exception:{}", StringUtils.join(appIds, ","), e); |
||||
result = false; |
||||
} |
||||
return result; |
||||
|
||||
} |
||||
|
||||
public int getProcessId() { |
||||
return getProcessId(process); |
||||
} |
||||
|
||||
/** |
||||
* get app links |
||||
* |
||||
* @param logPath log path |
||||
* @return app id list |
||||
*/ |
||||
private List<String> getAppIds(String logPath) { |
||||
List<String> logs = convertFile2List(logPath); |
||||
|
||||
List<String> appIds = new ArrayList<>(); |
||||
/** |
||||
* analysis log?get submited yarn application id |
||||
*/ |
||||
for (String log : logs) { |
||||
String appId = findAppId(log); |
||||
if (StringUtils.isNotEmpty(appId) && !appIds.contains(appId)) { |
||||
logger.info("find app id: {}", appId); |
||||
appIds.add(appId); |
||||
} |
||||
} |
||||
return appIds; |
||||
} |
||||
|
||||
/** |
||||
* convert file to list |
||||
* |
||||
* @param filename file name |
||||
* @return line list |
||||
*/ |
||||
private List<String> convertFile2List(String filename) { |
||||
List<String> lineList = new ArrayList<>(100); |
||||
File file = new File(filename); |
||||
|
||||
if (!file.exists()) { |
||||
return lineList; |
||||
} |
||||
|
||||
try (BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(filename), StandardCharsets.UTF_8))) { |
||||
String line = null; |
||||
while ((line = br.readLine()) != null) { |
||||
lineList.add(line); |
||||
} |
||||
} catch (Exception e) { |
||||
logger.error(String.format("read file: %s failed : ", filename), e); |
||||
} |
||||
return lineList; |
||||
} |
||||
|
||||
/** |
||||
* find app id |
||||
* |
||||
* @param line line |
||||
* @return appid |
||||
*/ |
||||
private String findAppId(String line) { |
||||
Matcher matcher = APPLICATION_REGEX.matcher(line); |
||||
if (matcher.find()) { |
||||
return matcher.group(); |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
/** |
||||
* get remain time(s) |
||||
* |
||||
* @return remain time |
||||
*/ |
||||
private long getRemaintime() { |
||||
long usedTime = (System.currentTimeMillis() - taskExecutionContext.getStartTime().getTime()) / 1000; |
||||
long remainTime = taskExecutionContext.getTaskTimeout() - usedTime; |
||||
|
||||
if (remainTime < 0) { |
||||
throw new RuntimeException("task execution time out"); |
||||
} |
||||
|
||||
return remainTime; |
||||
} |
||||
|
||||
/** |
||||
* get process id |
||||
* |
||||
* @param process process |
||||
* @return process id |
||||
*/ |
||||
private int getProcessId(Process process) { |
||||
int processId = 0; |
||||
|
||||
try { |
||||
Field f = process.getClass().getDeclaredField(Constants.PID); |
||||
f.setAccessible(true); |
||||
|
||||
processId = f.getInt(process); |
||||
} catch (Throwable e) { |
||||
logger.error(e.getMessage(), e); |
||||
} |
||||
|
||||
return processId; |
||||
} |
||||
|
||||
/** |
||||
* when log buffer siz or flush time reach condition , then flush |
||||
* |
||||
* @param lastFlushTime last flush time |
||||
* @return last flush time |
||||
*/ |
||||
private long flush(long lastFlushTime) { |
||||
long now = System.currentTimeMillis(); |
||||
|
||||
/** |
||||
* when log buffer siz or flush time reach condition , then flush |
||||
*/ |
||||
if (logBuffer.size() >= Constants.DEFAULT_LOG_ROWS_NUM || now - lastFlushTime > Constants.DEFAULT_LOG_FLUSH_INTERVAL) { |
||||
lastFlushTime = now; |
||||
/** log handle */ |
||||
logHandler.accept(logBuffer); |
||||
} |
||||
return lastFlushTime; |
||||
} |
||||
|
||||
protected List<String> commandOptions() { |
||||
return Collections.emptyList(); |
||||
} |
||||
|
||||
protected abstract String buildCommandFilePath(); |
||||
|
||||
protected abstract String commandInterpreter(); |
||||
|
||||
protected abstract void createCommandFileIfNotExists(String execCommand, String commandFile) throws IOException; |
||||
|
||||
} |
@ -1,193 +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.server.worker.task; |
||||
|
||||
import static ch.qos.logback.classic.ClassicConstants.FINALIZE_SESSION_MARKER; |
||||
|
||||
import org.apache.dolphinscheduler.common.Constants; |
||||
import org.apache.dolphinscheduler.common.enums.ExecutionStatus; |
||||
import org.apache.dolphinscheduler.common.enums.TaskType; |
||||
import org.apache.dolphinscheduler.common.task.AbstractParameters; |
||||
import org.apache.dolphinscheduler.server.entity.TaskExecutionContext; |
||||
|
||||
import java.util.StringJoiner; |
||||
import java.util.concurrent.LinkedBlockingQueue; |
||||
|
||||
import org.slf4j.Logger; |
||||
|
||||
/** |
||||
* executive task |
||||
*/ |
||||
public abstract class AbstractTask { |
||||
|
||||
/** |
||||
* taskExecutionContext |
||||
**/ |
||||
TaskExecutionContext taskExecutionContext; |
||||
|
||||
/** |
||||
* log record |
||||
*/ |
||||
protected Logger logger; |
||||
|
||||
|
||||
/** |
||||
* SHELL process pid |
||||
*/ |
||||
protected int processId; |
||||
|
||||
/** |
||||
* other resource manager appId , for example : YARN etc |
||||
*/ |
||||
protected String appIds; |
||||
|
||||
|
||||
/** |
||||
* cancel |
||||
*/ |
||||
protected volatile boolean cancel = false; |
||||
|
||||
/** |
||||
* exit code |
||||
*/ |
||||
protected volatile int exitStatusCode = -1; |
||||
|
||||
/** |
||||
* constructor |
||||
* |
||||
* @param taskExecutionContext taskExecutionContext |
||||
* @param logger logger |
||||
*/ |
||||
protected AbstractTask(TaskExecutionContext taskExecutionContext, Logger logger) { |
||||
this.taskExecutionContext = taskExecutionContext; |
||||
this.logger = logger; |
||||
} |
||||
|
||||
/** |
||||
* init task |
||||
* |
||||
* @throws Exception exception |
||||
*/ |
||||
public void init() throws Exception { |
||||
} |
||||
|
||||
/** |
||||
* task handle |
||||
* |
||||
* @throws Exception exception |
||||
*/ |
||||
public abstract void handle() throws Exception; |
||||
|
||||
/** |
||||
* result processing |
||||
* |
||||
* @throws Exception exception |
||||
*/ |
||||
public void after() throws Exception { |
||||
} |
||||
|
||||
/** |
||||
* cancel application |
||||
* |
||||
* @param status status |
||||
* @throws Exception exception |
||||
*/ |
||||
public void cancelApplication(boolean status) throws Exception { |
||||
this.cancel = status; |
||||
} |
||||
|
||||
/** |
||||
* log handle |
||||
* |
||||
* @param logs log list |
||||
*/ |
||||
public void logHandle(LinkedBlockingQueue<String> logs) { |
||||
// note that the "new line" is added here to facilitate log parsing
|
||||
if (logs.contains(FINALIZE_SESSION_MARKER.toString())) { |
||||
logger.info(FINALIZE_SESSION_MARKER, FINALIZE_SESSION_MARKER.toString()); |
||||
} else { |
||||
StringJoiner joiner = new StringJoiner("\n\t"); |
||||
while (!logs.isEmpty()) { |
||||
joiner.add(logs.poll()); |
||||
} |
||||
logger.info(" -> {}", joiner); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* get exit status code |
||||
* |
||||
* @return exit status code |
||||
*/ |
||||
public int getExitStatusCode() { |
||||
return exitStatusCode; |
||||
} |
||||
|
||||
public void setExitStatusCode(int exitStatusCode) { |
||||
this.exitStatusCode = exitStatusCode; |
||||
} |
||||
|
||||
public String getAppIds() { |
||||
return appIds; |
||||
} |
||||
|
||||
public void setAppIds(String appIds) { |
||||
this.appIds = appIds; |
||||
} |
||||
|
||||
public int getProcessId() { |
||||
return processId; |
||||
} |
||||
|
||||
public void setProcessId(int processId) { |
||||
this.processId = processId; |
||||
} |
||||
|
||||
/** |
||||
* get task parameters |
||||
* |
||||
* @return AbstractParameters |
||||
*/ |
||||
public abstract AbstractParameters getParameters(); |
||||
|
||||
private boolean typeIsNormalTask(String taskType) { |
||||
return !(TaskType.SUB_PROCESS.getDesc().equalsIgnoreCase(taskType) || TaskType.DEPENDENT.getDesc().equalsIgnoreCase(taskType)); |
||||
} |
||||
|
||||
/** |
||||
* get exit status according to exitCode |
||||
* |
||||
* @return exit status |
||||
*/ |
||||
public ExecutionStatus getExitStatus() { |
||||
ExecutionStatus status; |
||||
switch (getExitStatusCode()) { |
||||
case Constants.EXIT_CODE_SUCCESS: |
||||
status = ExecutionStatus.SUCCESS; |
||||
break; |
||||
case Constants.EXIT_CODE_KILL: |
||||
status = ExecutionStatus.KILL; |
||||
break; |
||||
default: |
||||
status = ExecutionStatus.FAILURE; |
||||
break; |
||||
} |
||||
return status; |
||||
} |
||||
|
||||
} |
@ -1,95 +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.server.worker.task; |
||||
|
||||
import org.apache.dolphinscheduler.dao.entity.TaskInstance; |
||||
import org.apache.dolphinscheduler.server.entity.TaskExecutionContext; |
||||
import org.apache.dolphinscheduler.server.utils.ProcessUtils; |
||||
import org.apache.dolphinscheduler.service.bean.SpringApplicationContext; |
||||
import org.apache.dolphinscheduler.service.process.ProcessService; |
||||
import org.slf4j.Logger; |
||||
|
||||
/** |
||||
* abstract yarn task |
||||
*/ |
||||
public abstract class AbstractYarnTask extends AbstractTask { |
||||
/** |
||||
* process task |
||||
*/ |
||||
private ShellCommandExecutor shellCommandExecutor; |
||||
|
||||
/** |
||||
* process database access |
||||
*/ |
||||
protected ProcessService processService; |
||||
|
||||
/** |
||||
* Abstract Yarn Task |
||||
* @param taskExecutionContext taskExecutionContext |
||||
* @param logger logger |
||||
*/ |
||||
public AbstractYarnTask(TaskExecutionContext taskExecutionContext, Logger logger) { |
||||
super(taskExecutionContext, logger); |
||||
this.processService = SpringApplicationContext.getBean(ProcessService.class); |
||||
this.shellCommandExecutor = new ShellCommandExecutor(this::logHandle, |
||||
taskExecutionContext, |
||||
logger); |
||||
} |
||||
|
||||
@Override |
||||
public void handle() throws Exception { |
||||
try { |
||||
// SHELL task exit code
|
||||
CommandExecuteResult commandExecuteResult = shellCommandExecutor.run(buildCommand()); |
||||
setExitStatusCode(commandExecuteResult.getExitStatusCode()); |
||||
setAppIds(commandExecuteResult.getAppIds()); |
||||
setProcessId(commandExecuteResult.getProcessId()); |
||||
} catch (Exception e) { |
||||
logger.error("yarn process failure", e); |
||||
exitStatusCode = -1; |
||||
throw e; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* cancel application |
||||
* @param status status |
||||
* @throws Exception exception |
||||
*/ |
||||
@Override |
||||
public void cancelApplication(boolean status) throws Exception { |
||||
cancel = true; |
||||
// cancel process
|
||||
shellCommandExecutor.cancelApplication(); |
||||
TaskInstance taskInstance = processService.findTaskInstanceById(taskExecutionContext.getTaskInstanceId()); |
||||
if (status && taskInstance != null){ |
||||
ProcessUtils.killYarnJob(taskExecutionContext); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* create command |
||||
* @return String |
||||
* @throws Exception exception |
||||
*/ |
||||
protected abstract String buildCommand() throws Exception; |
||||
|
||||
/** |
||||
* set main jar name |
||||
*/ |
||||
protected abstract void setMainJarName(); |
||||
} |
@ -1,69 +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.server.worker.task; |
||||
|
||||
/** |
||||
* command execute result |
||||
*/ |
||||
public class CommandExecuteResult { |
||||
|
||||
/** |
||||
* command exit code |
||||
*/ |
||||
private Integer exitStatusCode; |
||||
|
||||
/** |
||||
* appIds |
||||
*/ |
||||
private String appIds; |
||||
|
||||
/** |
||||
* process id |
||||
*/ |
||||
private Integer processId; |
||||
|
||||
|
||||
public CommandExecuteResult(){ |
||||
this.exitStatusCode = 0; |
||||
} |
||||
|
||||
|
||||
public Integer getExitStatusCode() { |
||||
return exitStatusCode; |
||||
} |
||||
|
||||
public void setExitStatusCode(Integer exitStatusCode) { |
||||
this.exitStatusCode = exitStatusCode; |
||||
} |
||||
|
||||
public String getAppIds() { |
||||
return appIds; |
||||
} |
||||
|
||||
public void setAppIds(String appIds) { |
||||
this.appIds = appIds; |
||||
} |
||||
|
||||
public Integer getProcessId() { |
||||
return processId; |
||||
} |
||||
|
||||
public void setProcessId(Integer processId) { |
||||
this.processId = processId; |
||||
} |
||||
} |
@ -1,188 +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.server.worker.task; |
||||
|
||||
import org.apache.dolphinscheduler.common.Constants; |
||||
import org.apache.dolphinscheduler.common.utils.FileUtils; |
||||
import org.apache.dolphinscheduler.common.utils.StringUtils; |
||||
import org.apache.dolphinscheduler.server.entity.TaskExecutionContext; |
||||
|
||||
import java.io.BufferedReader; |
||||
import java.io.File; |
||||
import java.io.FileInputStream; |
||||
import java.io.IOException; |
||||
import java.io.InputStreamReader; |
||||
import java.nio.charset.StandardCharsets; |
||||
import java.nio.file.Files; |
||||
import java.nio.file.Paths; |
||||
import java.util.Collections; |
||||
import java.util.List; |
||||
import java.util.concurrent.LinkedBlockingQueue; |
||||
import java.util.function.Consumer; |
||||
import java.util.regex.Pattern; |
||||
|
||||
import org.slf4j.Logger; |
||||
import org.slf4j.LoggerFactory; |
||||
|
||||
/** |
||||
* python command executor |
||||
*/ |
||||
public class PythonCommandExecutor extends AbstractCommandExecutor { |
||||
|
||||
/** |
||||
* logger |
||||
*/ |
||||
private static final Logger logger = LoggerFactory.getLogger(PythonCommandExecutor.class); |
||||
|
||||
/** |
||||
* python |
||||
*/ |
||||
public static final String PYTHON = "python"; |
||||
private static final Pattern PYTHON_PATH_PATTERN = Pattern.compile("/bin/python[\\d.]*$"); |
||||
|
||||
/** |
||||
* constructor |
||||
* @param logHandler log handler |
||||
* @param taskExecutionContext taskExecutionContext |
||||
* @param logger logger |
||||
*/ |
||||
public PythonCommandExecutor(Consumer<LinkedBlockingQueue<String>> logHandler, |
||||
TaskExecutionContext taskExecutionContext, |
||||
Logger logger) { |
||||
super(logHandler,taskExecutionContext,logger); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* build command file path |
||||
* |
||||
* @return command file path |
||||
*/ |
||||
@Override |
||||
protected String buildCommandFilePath() { |
||||
return String.format("%s/py_%s.command", taskExecutionContext.getExecutePath(), taskExecutionContext.getTaskAppId()); |
||||
} |
||||
|
||||
/** |
||||
* create command file if not exists |
||||
* @param execCommand exec command |
||||
* @param commandFile command file |
||||
* @throws IOException io exception |
||||
*/ |
||||
@Override |
||||
protected void createCommandFileIfNotExists(String execCommand, String commandFile) throws IOException { |
||||
logger.info("tenantCode :{}, task dir:{}", taskExecutionContext.getTenantCode(), taskExecutionContext.getExecutePath()); |
||||
|
||||
if (!Files.exists(Paths.get(commandFile))) { |
||||
logger.info("generate command file:{}", commandFile); |
||||
|
||||
StringBuilder sb = new StringBuilder(); |
||||
sb.append("#-*- encoding=utf8 -*-\n"); |
||||
|
||||
sb.append("\n\n"); |
||||
sb.append(execCommand); |
||||
logger.info(sb.toString()); |
||||
|
||||
// write data to file
|
||||
FileUtils.writeStringToFile(new File(commandFile), |
||||
sb.toString(), |
||||
StandardCharsets.UTF_8); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* get command options |
||||
* @return command options list |
||||
*/ |
||||
@Override |
||||
protected List<String> commandOptions() { |
||||
// unbuffered binary stdout and stderr
|
||||
return Collections.singletonList("-u"); |
||||
} |
||||
|
||||
/** |
||||
* Gets the command path to which Python can execute |
||||
* @return python command path |
||||
*/ |
||||
@Override |
||||
protected String commandInterpreter() { |
||||
String pythonHome = getPythonHome(taskExecutionContext.getEnvFile()); |
||||
return getPythonCommand(pythonHome); |
||||
} |
||||
|
||||
/** |
||||
* get python command |
||||
* |
||||
* @param pythonHome python home |
||||
* @return python command |
||||
*/ |
||||
public static String getPythonCommand(String pythonHome) { |
||||
if (StringUtils.isEmpty(pythonHome)) { |
||||
return PYTHON; |
||||
} |
||||
File file = new File(pythonHome); |
||||
if (file.exists() && file.isFile()) { |
||||
return pythonHome; |
||||
} |
||||
if (PYTHON_PATH_PATTERN.matcher(pythonHome).find()) { |
||||
return pythonHome; |
||||
} |
||||
return Paths.get(pythonHome, "/bin/python").toString(); |
||||
} |
||||
|
||||
/** |
||||
* get python home |
||||
* |
||||
* @param envPath env path |
||||
* @return python home |
||||
*/ |
||||
public static String getPythonHome(String envPath) { |
||||
BufferedReader br = null; |
||||
StringBuilder sb = new StringBuilder(); |
||||
try { |
||||
br = new BufferedReader(new InputStreamReader(new FileInputStream(envPath))); |
||||
String line; |
||||
while ((line = br.readLine()) != null) { |
||||
if (line.contains(Constants.PYTHON_HOME)) { |
||||
sb.append(line); |
||||
break; |
||||
} |
||||
} |
||||
String result = sb.toString(); |
||||
if (StringUtils.isEmpty(result)) { |
||||
return null; |
||||
} |
||||
String[] arrs = result.split(Constants.EQUAL_SIGN); |
||||
if (arrs.length == 2) { |
||||
return arrs[1]; |
||||
} |
||||
} catch (IOException e) { |
||||
logger.error("read file failure", e); |
||||
} finally { |
||||
try { |
||||
if (br != null) { |
||||
br.close(); |
||||
} |
||||
} catch (IOException e) { |
||||
logger.error(e.getMessage(), e); |
||||
} |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
} |
@ -1,119 +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.server.worker.task; |
||||
|
||||
import org.apache.dolphinscheduler.common.utils.OSUtils; |
||||
import org.apache.dolphinscheduler.server.entity.TaskExecutionContext; |
||||
|
||||
import org.apache.commons.io.FileUtils; |
||||
|
||||
import java.io.File; |
||||
import java.io.IOException; |
||||
import java.nio.charset.StandardCharsets; |
||||
import java.nio.file.Files; |
||||
import java.nio.file.Paths; |
||||
import java.util.List; |
||||
import java.util.concurrent.LinkedBlockingQueue; |
||||
import java.util.function.Consumer; |
||||
|
||||
import org.slf4j.Logger; |
||||
|
||||
/** |
||||
* shell command executor |
||||
*/ |
||||
public class ShellCommandExecutor extends AbstractCommandExecutor { |
||||
|
||||
/** |
||||
* For Unix-like, using sh |
||||
*/ |
||||
public static final String SH = "sh"; |
||||
|
||||
/** |
||||
* For Windows, using cmd.exe |
||||
*/ |
||||
public static final String CMD = "cmd.exe"; |
||||
|
||||
/** |
||||
* constructor |
||||
* @param logHandler logHandler |
||||
* @param taskExecutionContext taskExecutionContext |
||||
* @param logger logger |
||||
*/ |
||||
public ShellCommandExecutor(Consumer<LinkedBlockingQueue<String>> logHandler, |
||||
TaskExecutionContext taskExecutionContext, |
||||
Logger logger) { |
||||
super(logHandler,taskExecutionContext,logger); |
||||
} |
||||
|
||||
@Override |
||||
protected String buildCommandFilePath() { |
||||
// command file
|
||||
return String.format("%s/%s.%s" |
||||
, taskExecutionContext.getExecutePath() |
||||
, taskExecutionContext.getTaskAppId() |
||||
, OSUtils.isWindows() ? "bat" : "command"); |
||||
} |
||||
|
||||
/** |
||||
* get command type |
||||
* @return command type |
||||
*/ |
||||
@Override |
||||
protected String commandInterpreter() { |
||||
return OSUtils.isWindows() ? CMD : SH; |
||||
} |
||||
|
||||
/** |
||||
* create command file if not exists |
||||
* @param execCommand exec command |
||||
* @param commandFile command file |
||||
* @throws IOException io exception |
||||
*/ |
||||
@Override |
||||
protected void createCommandFileIfNotExists(String execCommand, String commandFile) throws IOException { |
||||
logger.info("tenantCode user:{}, task dir:{}", taskExecutionContext.getTenantCode(), |
||||
taskExecutionContext.getTaskAppId()); |
||||
|
||||
// create if non existence
|
||||
if (!Files.exists(Paths.get(commandFile))) { |
||||
logger.info("create command file:{}", commandFile); |
||||
|
||||
StringBuilder sb = new StringBuilder(); |
||||
if (OSUtils.isWindows()) { |
||||
sb.append("@echo off\n"); |
||||
sb.append("cd /d %~dp0\n"); |
||||
if (taskExecutionContext.getEnvFile() != null) { |
||||
sb.append("call ").append(taskExecutionContext.getEnvFile()).append("\n"); |
||||
} |
||||
} else { |
||||
sb.append("#!/bin/sh\n"); |
||||
sb.append("BASEDIR=$(cd `dirname $0`; pwd)\n"); |
||||
sb.append("cd $BASEDIR\n"); |
||||
if (taskExecutionContext.getEnvFile() != null) { |
||||
sb.append("source ").append(taskExecutionContext.getEnvFile()).append("\n"); |
||||
} |
||||
} |
||||
|
||||
sb.append(execCommand); |
||||
logger.info("command : {}", sb.toString()); |
||||
|
||||
// write data to file
|
||||
FileUtils.writeStringToFile(new File(commandFile), sb.toString(), StandardCharsets.UTF_8); |
||||
} |
||||
} |
||||
} |
@ -1,80 +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.server.worker.task; |
||||
|
||||
import org.apache.dolphinscheduler.server.entity.TaskExecutionContext; |
||||
import org.apache.dolphinscheduler.server.worker.task.datax.DataxTask; |
||||
import org.apache.dolphinscheduler.server.worker.task.flink.FlinkTask; |
||||
import org.apache.dolphinscheduler.server.worker.task.http.HttpTask; |
||||
import org.apache.dolphinscheduler.server.worker.task.mr.MapReduceTask; |
||||
import org.apache.dolphinscheduler.server.worker.task.procedure.ProcedureTask; |
||||
import org.apache.dolphinscheduler.server.worker.task.python.PythonTask; |
||||
import org.apache.dolphinscheduler.server.worker.task.shell.ShellTask; |
||||
import org.apache.dolphinscheduler.server.worker.task.spark.SparkTask; |
||||
import org.apache.dolphinscheduler.server.worker.task.sql.SqlTask; |
||||
import org.apache.dolphinscheduler.server.worker.task.sqoop.SqoopTask; |
||||
import org.apache.dolphinscheduler.service.alert.AlertClientService; |
||||
|
||||
import org.slf4j.Logger; |
||||
|
||||
/** |
||||
* task manager |
||||
*/ |
||||
public class TaskManager { |
||||
|
||||
/** |
||||
* create new task |
||||
* @param taskExecutionContext taskExecutionContext |
||||
* @param logger logger |
||||
* @return AbstractTask |
||||
* @throws IllegalArgumentException illegal argument exception |
||||
*/ |
||||
public static AbstractTask newTask(TaskExecutionContext taskExecutionContext, Logger logger, AlertClientService alertClientService) throws IllegalArgumentException { |
||||
String taskType = taskExecutionContext.getTaskType(); |
||||
if (taskType == null) { |
||||
logger.error("task type is null"); |
||||
throw new IllegalArgumentException("task type is null"); |
||||
} |
||||
switch (taskType) { |
||||
case "SHELL": |
||||
case "WATERDROP": |
||||
return new ShellTask(taskExecutionContext, logger); |
||||
case "PROCEDURE": |
||||
return new ProcedureTask(taskExecutionContext, logger); |
||||
case "SQL": |
||||
return new SqlTask(taskExecutionContext, logger, alertClientService); |
||||
case "MR": |
||||
return new MapReduceTask(taskExecutionContext, logger); |
||||
case "SPARK": |
||||
return new SparkTask(taskExecutionContext, logger); |
||||
case "FLINK": |
||||
return new FlinkTask(taskExecutionContext, logger); |
||||
case "PYTHON": |
||||
return new PythonTask(taskExecutionContext, logger); |
||||
case "HTTP": |
||||
return new HttpTask(taskExecutionContext, logger); |
||||
case "DATAX": |
||||
return new DataxTask(taskExecutionContext, logger); |
||||
case "SQOOP": |
||||
return new SqoopTask(taskExecutionContext, logger); |
||||
default: |
||||
logger.error("not support task type: {}", taskType); |
||||
throw new IllegalArgumentException("not support task type"); |
||||
} |
||||
} |
||||
} |
@ -1,346 +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.server.worker.task; |
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat; |
||||
import org.apache.dolphinscheduler.common.enums.CommandType; |
||||
import org.apache.dolphinscheduler.common.enums.DataType; |
||||
import org.apache.dolphinscheduler.common.enums.Direct; |
||||
import org.apache.dolphinscheduler.common.enums.TaskTimeoutStrategy; |
||||
import org.apache.dolphinscheduler.common.process.Property; |
||||
|
||||
import java.util.Date; |
||||
import java.util.HashMap; |
||||
import java.util.Iterator; |
||||
import java.util.Map; |
||||
|
||||
/** |
||||
* task props |
||||
*/ |
||||
public class TaskProps { |
||||
|
||||
/** |
||||
* task node name |
||||
**/ |
||||
private String taskName; |
||||
|
||||
/** |
||||
* task instance id |
||||
**/ |
||||
private int taskInstanceId; |
||||
|
||||
/** |
||||
* tenant code , execute task linux user |
||||
**/ |
||||
private String tenantCode; |
||||
|
||||
/** |
||||
* task type |
||||
*/ |
||||
private String taskType; |
||||
|
||||
/** |
||||
* task parameters |
||||
**/ |
||||
private String taskParams; |
||||
|
||||
/** |
||||
* queue |
||||
**/ |
||||
private String queue; |
||||
|
||||
/** |
||||
* env file |
||||
**/ |
||||
private String envFile; |
||||
|
||||
/** |
||||
* defined params |
||||
**/ |
||||
private Map<String, String> definedParams; |
||||
|
||||
/** |
||||
* task app id |
||||
*/ |
||||
private String taskAppId; |
||||
|
||||
/** |
||||
* task start time |
||||
*/ |
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone="GMT+8") |
||||
private Date taskStartTime; |
||||
|
||||
/** |
||||
* task timeout |
||||
*/ |
||||
private int taskTimeout; |
||||
|
||||
/** |
||||
* task timeout strategy |
||||
*/ |
||||
private TaskTimeoutStrategy taskTimeoutStrategy; |
||||
/** |
||||
* task dependence |
||||
*/ |
||||
private String dependence; |
||||
|
||||
/** |
||||
* schedule time |
||||
*/ |
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone="GMT+8") |
||||
private Date scheduleTime; |
||||
|
||||
/** |
||||
* command type is complement |
||||
*/ |
||||
private CommandType cmdTypeIfComplement; |
||||
|
||||
|
||||
/** |
||||
* host |
||||
*/ |
||||
private String host; |
||||
|
||||
/** |
||||
* log path |
||||
*/ |
||||
private String logPath; |
||||
|
||||
/** |
||||
* execute path |
||||
*/ |
||||
private String executePath; |
||||
|
||||
/** |
||||
* constructor |
||||
*/ |
||||
public TaskProps(){} |
||||
|
||||
/** |
||||
* constructor |
||||
* @param taskParams taskParams |
||||
* @param scheduleTime scheduleTime |
||||
* @param nodeName nodeName |
||||
* @param taskType taskType |
||||
* @param taskInstanceId taskInstanceId |
||||
* @param envFile envFile |
||||
* @param tenantCode tenantCode |
||||
* @param queue queue |
||||
* @param taskStartTime taskStartTime |
||||
* @param definedParams definedParams |
||||
* @param dependence dependence |
||||
* @param cmdTypeIfComplement cmdTypeIfComplement |
||||
* @param host host |
||||
* @param logPath logPath |
||||
* @param executePath executePath |
||||
*/ |
||||
public TaskProps(String taskParams, |
||||
Date scheduleTime, |
||||
String nodeName, |
||||
String taskType, |
||||
int taskInstanceId, |
||||
String envFile, |
||||
String tenantCode, |
||||
String queue, |
||||
Date taskStartTime, |
||||
Map<String, String> definedParams, |
||||
String dependence, |
||||
CommandType cmdTypeIfComplement, |
||||
String host, |
||||
String logPath, |
||||
String executePath){ |
||||
this.taskParams = taskParams; |
||||
this.scheduleTime = scheduleTime; |
||||
this.taskName = nodeName; |
||||
this.taskType = taskType; |
||||
this.taskInstanceId = taskInstanceId; |
||||
this.envFile = envFile; |
||||
this.tenantCode = tenantCode; |
||||
this.queue = queue; |
||||
this.taskStartTime = taskStartTime; |
||||
this.definedParams = definedParams; |
||||
this.dependence = dependence; |
||||
this.cmdTypeIfComplement = cmdTypeIfComplement; |
||||
this.host = host; |
||||
this.logPath = logPath; |
||||
this.executePath = executePath; |
||||
} |
||||
|
||||
public String getTenantCode() { |
||||
return tenantCode; |
||||
} |
||||
|
||||
public void setTenantCode(String tenantCode) { |
||||
this.tenantCode = tenantCode; |
||||
} |
||||
|
||||
public String getTaskParams() { |
||||
return taskParams; |
||||
} |
||||
|
||||
public void setTaskParams(String taskParams) { |
||||
this.taskParams = taskParams; |
||||
} |
||||
|
||||
public String getExecutePath() { |
||||
return executePath; |
||||
} |
||||
|
||||
public void setExecutePath(String executePath) { |
||||
this.executePath = executePath; |
||||
} |
||||
|
||||
public Map<String, String> getDefinedParams() { |
||||
return definedParams; |
||||
} |
||||
|
||||
public void setDefinedParams(Map<String, String> definedParams) { |
||||
this.definedParams = definedParams; |
||||
} |
||||
|
||||
public String getEnvFile() { |
||||
return envFile; |
||||
} |
||||
|
||||
public void setEnvFile(String envFile) { |
||||
this.envFile = envFile; |
||||
} |
||||
|
||||
|
||||
public String getTaskName() { |
||||
return taskName; |
||||
} |
||||
|
||||
public void setTaskName(String taskName) { |
||||
this.taskName = taskName; |
||||
} |
||||
|
||||
public int getTaskInstanceId() { |
||||
return taskInstanceId; |
||||
} |
||||
|
||||
public void setTaskInstanceId(int taskInstanceId) { |
||||
this.taskInstanceId = taskInstanceId; |
||||
} |
||||
|
||||
public String getQueue() { |
||||
return queue; |
||||
} |
||||
|
||||
public void setQueue(String queue) { |
||||
this.queue = queue; |
||||
} |
||||
|
||||
|
||||
public String getTaskAppId() { |
||||
return taskAppId; |
||||
} |
||||
|
||||
public void setTaskAppId(String taskAppId) { |
||||
this.taskAppId = taskAppId; |
||||
} |
||||
|
||||
public Date getTaskStartTime() { |
||||
return taskStartTime; |
||||
} |
||||
|
||||
public void setTaskStartTime(Date taskStartTime) { |
||||
this.taskStartTime = taskStartTime; |
||||
} |
||||
|
||||
public int getTaskTimeout() { |
||||
return taskTimeout; |
||||
} |
||||
|
||||
public void setTaskTimeout(int taskTimeout) { |
||||
this.taskTimeout = taskTimeout; |
||||
} |
||||
|
||||
public TaskTimeoutStrategy getTaskTimeoutStrategy() { |
||||
return taskTimeoutStrategy; |
||||
} |
||||
|
||||
public void setTaskTimeoutStrategy(TaskTimeoutStrategy taskTimeoutStrategy) { |
||||
this.taskTimeoutStrategy = taskTimeoutStrategy; |
||||
} |
||||
|
||||
public String getTaskType() { |
||||
return taskType; |
||||
} |
||||
|
||||
public void setTaskType(String taskType) { |
||||
this.taskType = taskType; |
||||
} |
||||
|
||||
public String getDependence() { |
||||
return dependence; |
||||
} |
||||
|
||||
public void setDependence(String dependence) { |
||||
this.dependence = dependence; |
||||
} |
||||
|
||||
public Date getScheduleTime() { |
||||
return scheduleTime; |
||||
} |
||||
|
||||
public void setScheduleTime(Date scheduleTime) { |
||||
this.scheduleTime = scheduleTime; |
||||
} |
||||
|
||||
public CommandType getCmdTypeIfComplement() { |
||||
return cmdTypeIfComplement; |
||||
} |
||||
|
||||
public void setCmdTypeIfComplement(CommandType cmdTypeIfComplement) { |
||||
this.cmdTypeIfComplement = cmdTypeIfComplement; |
||||
} |
||||
|
||||
public String getHost() { |
||||
return host; |
||||
} |
||||
|
||||
public void setHost(String host) { |
||||
this.host = host; |
||||
} |
||||
|
||||
public String getLogPath() { |
||||
return logPath; |
||||
} |
||||
|
||||
public void setLogPath(String logPath) { |
||||
this.logPath = logPath; |
||||
} |
||||
|
||||
/** |
||||
* get parameters map |
||||
* @return user defined params map |
||||
*/ |
||||
public Map<String,Property> getUserDefParamsMap() { |
||||
if (definedParams != null) { |
||||
Map<String,Property> userDefParamsMaps = new HashMap<>(); |
||||
Iterator<Map.Entry<String, String>> iter = definedParams.entrySet().iterator(); |
||||
while (iter.hasNext()){ |
||||
Map.Entry<String, String> en = iter.next(); |
||||
Property property = new Property(en.getKey(), Direct.IN, DataType.VARCHAR , en.getValue()); |
||||
userDefParamsMaps.put(property.getProp(),property); |
||||
} |
||||
return userDefParamsMaps; |
||||
} |
||||
return null; |
||||
} |
||||
} |
@ -1,580 +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.server.worker.task.datax; |
||||
|
||||
import org.apache.dolphinscheduler.common.Constants; |
||||
import org.apache.dolphinscheduler.common.datasource.BaseConnectionParam; |
||||
import org.apache.dolphinscheduler.common.datasource.DatasourceUtil; |
||||
import org.apache.dolphinscheduler.common.enums.DbType; |
||||
import org.apache.dolphinscheduler.common.enums.Flag; |
||||
import org.apache.dolphinscheduler.common.process.Property; |
||||
import org.apache.dolphinscheduler.common.task.AbstractParameters; |
||||
import org.apache.dolphinscheduler.common.task.datax.DataxParameters; |
||||
import org.apache.dolphinscheduler.common.utils.CollectionUtils; |
||||
import org.apache.dolphinscheduler.common.utils.CommonUtils; |
||||
import org.apache.dolphinscheduler.common.utils.JSONUtils; |
||||
import org.apache.dolphinscheduler.common.utils.OSUtils; |
||||
import org.apache.dolphinscheduler.common.utils.ParameterUtils; |
||||
import org.apache.dolphinscheduler.common.utils.StringUtils; |
||||
import org.apache.dolphinscheduler.server.entity.DataxTaskExecutionContext; |
||||
import org.apache.dolphinscheduler.server.entity.TaskExecutionContext; |
||||
import org.apache.dolphinscheduler.server.utils.DataxUtils; |
||||
import org.apache.dolphinscheduler.server.utils.ParamUtils; |
||||
import org.apache.dolphinscheduler.server.worker.task.AbstractTask; |
||||
import org.apache.dolphinscheduler.server.worker.task.CommandExecuteResult; |
||||
import org.apache.dolphinscheduler.server.worker.task.ShellCommandExecutor; |
||||
|
||||
import org.apache.commons.io.FileUtils; |
||||
|
||||
import java.io.File; |
||||
import java.nio.charset.StandardCharsets; |
||||
import java.nio.file.Files; |
||||
import java.nio.file.Path; |
||||
import java.nio.file.Paths; |
||||
import java.nio.file.StandardOpenOption; |
||||
import java.nio.file.attribute.FileAttribute; |
||||
import java.nio.file.attribute.PosixFilePermission; |
||||
import java.nio.file.attribute.PosixFilePermissions; |
||||
import java.sql.Connection; |
||||
import java.sql.PreparedStatement; |
||||
import java.sql.ResultSet; |
||||
import java.sql.ResultSetMetaData; |
||||
import java.sql.SQLException; |
||||
import java.util.ArrayList; |
||||
import java.util.List; |
||||
import java.util.Map; |
||||
import java.util.Set; |
||||
import java.util.regex.Matcher; |
||||
import java.util.regex.Pattern; |
||||
|
||||
import org.slf4j.Logger; |
||||
|
||||
import com.alibaba.druid.sql.ast.SQLStatement; |
||||
import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr; |
||||
import com.alibaba.druid.sql.ast.expr.SQLPropertyExpr; |
||||
import com.alibaba.druid.sql.ast.statement.SQLSelect; |
||||
import com.alibaba.druid.sql.ast.statement.SQLSelectItem; |
||||
import com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock; |
||||
import com.alibaba.druid.sql.ast.statement.SQLSelectStatement; |
||||
import com.alibaba.druid.sql.ast.statement.SQLUnionQuery; |
||||
import com.alibaba.druid.sql.parser.SQLStatementParser; |
||||
import com.fasterxml.jackson.databind.node.ArrayNode; |
||||
import com.fasterxml.jackson.databind.node.ObjectNode; |
||||
|
||||
/** |
||||
* DataX task |
||||
*/ |
||||
public class DataxTask extends AbstractTask { |
||||
|
||||
/** |
||||
* jvm parameters |
||||
*/ |
||||
public static final String JVM_PARAM = " --jvm=\"-Xms%sG -Xmx%sG\" "; |
||||
/** |
||||
* python process(datax only supports version 2.7 by default) |
||||
*/ |
||||
private static final String DATAX_PYTHON = "python2.7"; |
||||
private static final Pattern PYTHON_PATH_PATTERN = Pattern.compile("/bin/python[\\d.]*$"); |
||||
/** |
||||
* datax path |
||||
*/ |
||||
private static final String DATAX_PATH = "${DATAX_HOME}/bin/datax.py"; |
||||
/** |
||||
* datax channel count |
||||
*/ |
||||
private static final int DATAX_CHANNEL_COUNT = 1; |
||||
|
||||
/** |
||||
* datax parameters |
||||
*/ |
||||
private DataxParameters dataXParameters; |
||||
|
||||
/** |
||||
* shell command executor |
||||
*/ |
||||
private ShellCommandExecutor shellCommandExecutor; |
||||
|
||||
/** |
||||
* taskExecutionContext |
||||
*/ |
||||
private TaskExecutionContext taskExecutionContext; |
||||
|
||||
/** |
||||
* constructor |
||||
* |
||||
* @param taskExecutionContext taskExecutionContext |
||||
* @param logger logger |
||||
*/ |
||||
public DataxTask(TaskExecutionContext taskExecutionContext, Logger logger) { |
||||
super(taskExecutionContext, logger); |
||||
this.taskExecutionContext = taskExecutionContext; |
||||
|
||||
this.shellCommandExecutor = new ShellCommandExecutor(this::logHandle, |
||||
taskExecutionContext, logger); |
||||
} |
||||
|
||||
/** |
||||
* init DataX config |
||||
*/ |
||||
@Override |
||||
public void init() { |
||||
logger.info("datax task params {}", taskExecutionContext.getTaskParams()); |
||||
dataXParameters = JSONUtils.parseObject(taskExecutionContext.getTaskParams(), DataxParameters.class); |
||||
|
||||
if (!dataXParameters.checkParameters()) { |
||||
throw new RuntimeException("datax task params is not valid"); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* run DataX process |
||||
* |
||||
* @throws Exception if error throws Exception |
||||
*/ |
||||
@Override |
||||
public void handle() throws Exception { |
||||
try { |
||||
// set the name of the current thread
|
||||
String threadLoggerInfoName = String.format("TaskLogInfo-%s", taskExecutionContext.getTaskAppId()); |
||||
Thread.currentThread().setName(threadLoggerInfoName); |
||||
|
||||
// replace placeholder,and combine local and global parameters
|
||||
Map<String, Property> paramsMap = ParamUtils.convert(taskExecutionContext,getParameters()); |
||||
|
||||
// run datax procesDataSourceService.s
|
||||
String jsonFilePath = buildDataxJsonFile(paramsMap); |
||||
String shellCommandFilePath = buildShellCommandFile(jsonFilePath, paramsMap); |
||||
CommandExecuteResult commandExecuteResult = shellCommandExecutor.run(shellCommandFilePath); |
||||
|
||||
setExitStatusCode(commandExecuteResult.getExitStatusCode()); |
||||
setAppIds(commandExecuteResult.getAppIds()); |
||||
setProcessId(commandExecuteResult.getProcessId()); |
||||
} catch (Exception e) { |
||||
setExitStatusCode(Constants.EXIT_CODE_FAILURE); |
||||
throw e; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* cancel DataX process |
||||
* |
||||
* @param cancelApplication cancelApplication |
||||
* @throws Exception if error throws Exception |
||||
*/ |
||||
@Override |
||||
public void cancelApplication(boolean cancelApplication) |
||||
throws Exception { |
||||
// cancel process
|
||||
shellCommandExecutor.cancelApplication(); |
||||
} |
||||
|
||||
/** |
||||
* build datax configuration file |
||||
* |
||||
* @return datax json file name |
||||
* @throws Exception if error throws Exception |
||||
*/ |
||||
private String buildDataxJsonFile(Map<String, Property> paramsMap) |
||||
throws Exception { |
||||
// generate json
|
||||
String fileName = String.format("%s/%s_job.json", |
||||
taskExecutionContext.getExecutePath(), |
||||
taskExecutionContext.getTaskAppId()); |
||||
String json; |
||||
|
||||
Path path = new File(fileName).toPath(); |
||||
if (Files.exists(path)) { |
||||
return fileName; |
||||
} |
||||
|
||||
if (dataXParameters.getCustomConfig() == Flag.YES.ordinal()) { |
||||
json = dataXParameters.getJson().replaceAll("\\r\\n", "\n"); |
||||
} else { |
||||
ObjectNode job = JSONUtils.createObjectNode(); |
||||
job.putArray("content").addAll(buildDataxJobContentJson()); |
||||
job.set("setting", buildDataxJobSettingJson()); |
||||
|
||||
ObjectNode root = JSONUtils.createObjectNode(); |
||||
root.set("job", job); |
||||
root.set("core", buildDataxCoreJson()); |
||||
json = root.toString(); |
||||
} |
||||
|
||||
// replace placeholder
|
||||
json = ParameterUtils.convertParameterPlaceholders(json, ParamUtils.convert(paramsMap)); |
||||
|
||||
logger.debug("datax job json : {}", json); |
||||
|
||||
// create datax json file
|
||||
FileUtils.writeStringToFile(new File(fileName), json, StandardCharsets.UTF_8); |
||||
return fileName; |
||||
} |
||||
|
||||
/** |
||||
* build datax job config |
||||
* |
||||
* @return collection of datax job config JSONObject |
||||
* @throws SQLException if error throws SQLException |
||||
*/ |
||||
private List<ObjectNode> buildDataxJobContentJson() { |
||||
|
||||
DataxTaskExecutionContext dataxTaskExecutionContext = taskExecutionContext.getDataxTaskExecutionContext(); |
||||
|
||||
BaseConnectionParam dataSourceCfg = (BaseConnectionParam) DatasourceUtil.buildConnectionParams( |
||||
DbType.of(dataxTaskExecutionContext.getSourcetype()), |
||||
dataxTaskExecutionContext.getSourceConnectionParams()); |
||||
|
||||
BaseConnectionParam dataTargetCfg = (BaseConnectionParam) DatasourceUtil.buildConnectionParams( |
||||
DbType.of(dataxTaskExecutionContext.getTargetType()), |
||||
dataxTaskExecutionContext.getTargetConnectionParams()); |
||||
|
||||
List<ObjectNode> readerConnArr = new ArrayList<>(); |
||||
ObjectNode readerConn = JSONUtils.createObjectNode(); |
||||
|
||||
ArrayNode sqlArr = readerConn.putArray("querySql"); |
||||
for (String sql : new String[]{dataXParameters.getSql()}) { |
||||
sqlArr.add(sql); |
||||
} |
||||
|
||||
ArrayNode urlArr = readerConn.putArray("jdbcUrl"); |
||||
urlArr.add(DatasourceUtil.getJdbcUrl(DbType.valueOf(dataXParameters.getDsType()), dataSourceCfg)); |
||||
|
||||
readerConnArr.add(readerConn); |
||||
|
||||
ObjectNode readerParam = JSONUtils.createObjectNode(); |
||||
readerParam.put("username", dataSourceCfg.getUser()); |
||||
readerParam.put("password", CommonUtils.decodePassword(dataSourceCfg.getPassword())); |
||||
readerParam.putArray("connection").addAll(readerConnArr); |
||||
|
||||
ObjectNode reader = JSONUtils.createObjectNode(); |
||||
reader.put("name", DataxUtils.getReaderPluginName(DbType.of(dataxTaskExecutionContext.getSourcetype()))); |
||||
reader.set("parameter", readerParam); |
||||
|
||||
List<ObjectNode> writerConnArr = new ArrayList<>(); |
||||
ObjectNode writerConn = JSONUtils.createObjectNode(); |
||||
ArrayNode tableArr = writerConn.putArray("table"); |
||||
tableArr.add(dataXParameters.getTargetTable()); |
||||
|
||||
writerConn.put("jdbcUrl", DatasourceUtil.getJdbcUrl(DbType.valueOf(dataXParameters.getDtType()), dataTargetCfg)); |
||||
writerConnArr.add(writerConn); |
||||
|
||||
ObjectNode writerParam = JSONUtils.createObjectNode(); |
||||
writerParam.put("username", dataTargetCfg.getUser()); |
||||
writerParam.put("password", CommonUtils.decodePassword(dataTargetCfg.getPassword())); |
||||
|
||||
String[] columns = parsingSqlColumnNames(DbType.of(dataxTaskExecutionContext.getSourcetype()), |
||||
DbType.of(dataxTaskExecutionContext.getTargetType()), |
||||
dataSourceCfg, dataXParameters.getSql()); |
||||
|
||||
ArrayNode columnArr = writerParam.putArray("column"); |
||||
for (String column : columns) { |
||||
columnArr.add(column); |
||||
} |
||||
writerParam.putArray("connection").addAll(writerConnArr); |
||||
|
||||
if (CollectionUtils.isNotEmpty(dataXParameters.getPreStatements())) { |
||||
ArrayNode preSqlArr = writerParam.putArray("preSql"); |
||||
for (String preSql : dataXParameters.getPreStatements()) { |
||||
preSqlArr.add(preSql); |
||||
} |
||||
|
||||
} |
||||
|
||||
if (CollectionUtils.isNotEmpty(dataXParameters.getPostStatements())) { |
||||
ArrayNode postSqlArr = writerParam.putArray("postSql"); |
||||
for (String postSql : dataXParameters.getPostStatements()) { |
||||
postSqlArr.add(postSql); |
||||
} |
||||
} |
||||
|
||||
ObjectNode writer = JSONUtils.createObjectNode(); |
||||
writer.put("name", DataxUtils.getWriterPluginName(DbType.of(dataxTaskExecutionContext.getTargetType()))); |
||||
writer.set("parameter", writerParam); |
||||
|
||||
List<ObjectNode> contentList = new ArrayList<>(); |
||||
ObjectNode content = JSONUtils.createObjectNode(); |
||||
content.set("reader", reader); |
||||
content.set("writer", writer); |
||||
contentList.add(content); |
||||
|
||||
return contentList; |
||||
} |
||||
|
||||
/** |
||||
* build datax setting config |
||||
* |
||||
* @return datax setting config JSONObject |
||||
*/ |
||||
private ObjectNode buildDataxJobSettingJson() { |
||||
|
||||
ObjectNode speed = JSONUtils.createObjectNode(); |
||||
|
||||
speed.put("channel", DATAX_CHANNEL_COUNT); |
||||
|
||||
if (dataXParameters.getJobSpeedByte() > 0) { |
||||
speed.put("byte", dataXParameters.getJobSpeedByte()); |
||||
} |
||||
|
||||
if (dataXParameters.getJobSpeedRecord() > 0) { |
||||
speed.put("record", dataXParameters.getJobSpeedRecord()); |
||||
} |
||||
|
||||
ObjectNode errorLimit = JSONUtils.createObjectNode(); |
||||
errorLimit.put("record", 0); |
||||
errorLimit.put("percentage", 0); |
||||
|
||||
ObjectNode setting = JSONUtils.createObjectNode(); |
||||
setting.set("speed", speed); |
||||
setting.set("errorLimit", errorLimit); |
||||
|
||||
return setting; |
||||
} |
||||
|
||||
private ObjectNode buildDataxCoreJson() { |
||||
|
||||
ObjectNode speed = JSONUtils.createObjectNode(); |
||||
speed.put("channel", DATAX_CHANNEL_COUNT); |
||||
|
||||
if (dataXParameters.getJobSpeedByte() > 0) { |
||||
speed.put("byte", dataXParameters.getJobSpeedByte()); |
||||
} |
||||
|
||||
if (dataXParameters.getJobSpeedRecord() > 0) { |
||||
speed.put("record", dataXParameters.getJobSpeedRecord()); |
||||
} |
||||
|
||||
ObjectNode channel = JSONUtils.createObjectNode(); |
||||
channel.set("speed", speed); |
||||
|
||||
ObjectNode transport = JSONUtils.createObjectNode(); |
||||
transport.set("channel", channel); |
||||
|
||||
ObjectNode core = JSONUtils.createObjectNode(); |
||||
core.set("transport", transport); |
||||
|
||||
return core; |
||||
} |
||||
|
||||
/** |
||||
* create command |
||||
* |
||||
* @return shell command file name |
||||
* @throws Exception if error throws Exception |
||||
*/ |
||||
private String buildShellCommandFile(String jobConfigFilePath, Map<String, Property> paramsMap) |
||||
throws Exception { |
||||
// generate scripts
|
||||
String fileName = String.format("%s/%s_node.%s", |
||||
taskExecutionContext.getExecutePath(), |
||||
taskExecutionContext.getTaskAppId(), |
||||
OSUtils.isWindows() ? "bat" : "sh"); |
||||
|
||||
Path path = new File(fileName).toPath(); |
||||
|
||||
if (Files.exists(path)) { |
||||
return fileName; |
||||
} |
||||
|
||||
// datax python command
|
||||
StringBuilder sbr = new StringBuilder(); |
||||
sbr.append(getPythonCommand()); |
||||
sbr.append(" "); |
||||
sbr.append(DATAX_PATH); |
||||
sbr.append(" "); |
||||
sbr.append(loadJvmEnv(dataXParameters)); |
||||
sbr.append(jobConfigFilePath); |
||||
|
||||
// replace placeholder
|
||||
String dataxCommand = ParameterUtils.convertParameterPlaceholders(sbr.toString(), ParamUtils.convert(paramsMap)); |
||||
|
||||
logger.debug("raw script : {}", dataxCommand); |
||||
|
||||
// create shell command file
|
||||
Set<PosixFilePermission> perms = PosixFilePermissions.fromString(Constants.RWXR_XR_X); |
||||
FileAttribute<Set<PosixFilePermission>> attr = PosixFilePermissions.asFileAttribute(perms); |
||||
|
||||
if (OSUtils.isWindows()) { |
||||
Files.createFile(path); |
||||
} else { |
||||
Files.createFile(path, attr); |
||||
} |
||||
|
||||
Files.write(path, dataxCommand.getBytes(), StandardOpenOption.APPEND); |
||||
|
||||
return fileName; |
||||
} |
||||
|
||||
public String getPythonCommand() { |
||||
String pythonHome = System.getenv("PYTHON_HOME"); |
||||
return getPythonCommand(pythonHome); |
||||
} |
||||
|
||||
public String getPythonCommand(String pythonHome) { |
||||
if (StringUtils.isEmpty(pythonHome)) { |
||||
return DATAX_PYTHON; |
||||
} |
||||
String pythonBinPath = "/bin/" + DATAX_PYTHON; |
||||
Matcher matcher = PYTHON_PATH_PATTERN.matcher(pythonHome); |
||||
if (matcher.find()) { |
||||
return matcher.replaceAll(pythonBinPath); |
||||
} |
||||
return Paths.get(pythonHome, pythonBinPath).toString(); |
||||
} |
||||
|
||||
public String loadJvmEnv(DataxParameters dataXParameters) { |
||||
int xms = Math.max(dataXParameters.getXms(), 1); |
||||
int xmx = Math.max(dataXParameters.getXmx(), 1); |
||||
return String.format(JVM_PARAM, xms, xmx); |
||||
} |
||||
|
||||
/** |
||||
* parsing synchronized column names in SQL statements |
||||
* |
||||
* @param sourceType the database type of the data source |
||||
* @param targetType the database type of the data target |
||||
* @param dataSourceCfg the database connection parameters of the data source |
||||
* @param sql sql for data synchronization |
||||
* @return Keyword converted column names |
||||
*/ |
||||
private String[] parsingSqlColumnNames(DbType sourceType, DbType targetType, BaseConnectionParam dataSourceCfg, String sql) { |
||||
String[] columnNames = tryGrammaticalAnalysisSqlColumnNames(sourceType, sql); |
||||
|
||||
if (columnNames == null || columnNames.length == 0) { |
||||
logger.info("try to execute sql analysis query column name"); |
||||
columnNames = tryExecuteSqlResolveColumnNames(sourceType, dataSourceCfg, sql); |
||||
} |
||||
|
||||
notNull(columnNames, String.format("parsing sql columns failed : %s", sql)); |
||||
|
||||
return DataxUtils.convertKeywordsColumns(targetType, columnNames); |
||||
} |
||||
|
||||
/** |
||||
* try grammatical parsing column |
||||
* |
||||
* @param dbType database type |
||||
* @param sql sql for data synchronization |
||||
* @return column name array |
||||
* @throws RuntimeException if error throws RuntimeException |
||||
*/ |
||||
private String[] tryGrammaticalAnalysisSqlColumnNames(DbType dbType, String sql) { |
||||
String[] columnNames; |
||||
|
||||
try { |
||||
SQLStatementParser parser = DataxUtils.getSqlStatementParser(dbType, sql); |
||||
if (parser == null) { |
||||
logger.warn("database driver [{}] is not support grammatical analysis sql", dbType); |
||||
return new String[0]; |
||||
} |
||||
|
||||
SQLStatement sqlStatement = parser.parseStatement(); |
||||
SQLSelectStatement sqlSelectStatement = (SQLSelectStatement) sqlStatement; |
||||
SQLSelect sqlSelect = sqlSelectStatement.getSelect(); |
||||
|
||||
List<SQLSelectItem> selectItemList = null; |
||||
if (sqlSelect.getQuery() instanceof SQLSelectQueryBlock) { |
||||
SQLSelectQueryBlock block = (SQLSelectQueryBlock) sqlSelect.getQuery(); |
||||
selectItemList = block.getSelectList(); |
||||
} else if (sqlSelect.getQuery() instanceof SQLUnionQuery) { |
||||
SQLUnionQuery unionQuery = (SQLUnionQuery) sqlSelect.getQuery(); |
||||
SQLSelectQueryBlock block = (SQLSelectQueryBlock) unionQuery.getRight(); |
||||
selectItemList = block.getSelectList(); |
||||
} |
||||
|
||||
notNull(selectItemList, |
||||
String.format("select query type [%s] is not support", sqlSelect.getQuery().toString())); |
||||
|
||||
columnNames = new String[selectItemList.size()]; |
||||
for (int i = 0; i < selectItemList.size(); i++) { |
||||
SQLSelectItem item = selectItemList.get(i); |
||||
|
||||
String columnName = null; |
||||
|
||||
if (item.getAlias() != null) { |
||||
columnName = item.getAlias(); |
||||
} else if (item.getExpr() != null) { |
||||
if (item.getExpr() instanceof SQLPropertyExpr) { |
||||
SQLPropertyExpr expr = (SQLPropertyExpr) item.getExpr(); |
||||
columnName = expr.getName(); |
||||
} else if (item.getExpr() instanceof SQLIdentifierExpr) { |
||||
SQLIdentifierExpr expr = (SQLIdentifierExpr) item.getExpr(); |
||||
columnName = expr.getName(); |
||||
} |
||||
} else { |
||||
throw new RuntimeException( |
||||
String.format("grammatical analysis sql column [ %s ] failed", item.toString())); |
||||
} |
||||
|
||||
if (columnName == null) { |
||||
throw new RuntimeException( |
||||
String.format("grammatical analysis sql column [ %s ] failed", item.toString())); |
||||
} |
||||
|
||||
columnNames[i] = columnName; |
||||
} |
||||
} catch (Exception e) { |
||||
logger.warn(e.getMessage(), e); |
||||
return new String[0]; |
||||
} |
||||
|
||||
return columnNames; |
||||
} |
||||
|
||||
/** |
||||
* try to execute sql to resolve column names |
||||
* |
||||
* @param baseDataSource the database connection parameters |
||||
* @param sql sql for data synchronization |
||||
* @return column name array |
||||
*/ |
||||
public String[] tryExecuteSqlResolveColumnNames(DbType sourceType, BaseConnectionParam baseDataSource, String sql) { |
||||
String[] columnNames; |
||||
sql = String.format("SELECT t.* FROM ( %s ) t WHERE 0 = 1", sql); |
||||
sql = sql.replace(";", ""); |
||||
|
||||
try ( |
||||
Connection connection = DatasourceUtil.getConnection(sourceType, baseDataSource); |
||||
PreparedStatement stmt = connection.prepareStatement(sql); |
||||
ResultSet resultSet = stmt.executeQuery()) { |
||||
|
||||
ResultSetMetaData md = resultSet.getMetaData(); |
||||
int num = md.getColumnCount(); |
||||
columnNames = new String[num]; |
||||
for (int i = 1; i <= num; i++) { |
||||
columnNames[i - 1] = md.getColumnName(i); |
||||
} |
||||
} catch (SQLException e) { |
||||
logger.warn(e.getMessage(), e); |
||||
return null; |
||||
} |
||||
|
||||
return columnNames; |
||||
} |
||||
|
||||
@Override |
||||
public AbstractParameters getParameters() { |
||||
return dataXParameters; |
||||
} |
||||
|
||||
private void notNull(Object obj, String message) { |
||||
if (obj == null) { |
||||
throw new RuntimeException(message); |
||||
} |
||||
} |
||||
|
||||
} |
@ -1,143 +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.server.worker.task.flink; |
||||
|
||||
import org.apache.dolphinscheduler.common.process.Property; |
||||
import org.apache.dolphinscheduler.common.process.ResourceInfo; |
||||
import org.apache.dolphinscheduler.common.task.AbstractParameters; |
||||
import org.apache.dolphinscheduler.common.task.flink.FlinkParameters; |
||||
import org.apache.dolphinscheduler.common.utils.JSONUtils; |
||||
import org.apache.dolphinscheduler.common.utils.ParameterUtils; |
||||
import org.apache.dolphinscheduler.common.utils.StringUtils; |
||||
import org.apache.dolphinscheduler.dao.entity.Resource; |
||||
import org.apache.dolphinscheduler.server.entity.TaskExecutionContext; |
||||
import org.apache.dolphinscheduler.server.utils.FlinkArgsUtils; |
||||
import org.apache.dolphinscheduler.server.utils.ParamUtils; |
||||
import org.apache.dolphinscheduler.server.worker.task.AbstractYarnTask; |
||||
|
||||
import java.util.ArrayList; |
||||
import java.util.List; |
||||
import java.util.Map; |
||||
|
||||
import org.slf4j.Logger; |
||||
|
||||
/** |
||||
* flink task |
||||
*/ |
||||
public class FlinkTask extends AbstractYarnTask { |
||||
|
||||
/** |
||||
* flink command |
||||
* usage: flink run [OPTIONS] <jar-file> <arguments> |
||||
*/ |
||||
private static final String FLINK_COMMAND = "flink"; |
||||
private static final String FLINK_RUN = "run"; |
||||
|
||||
/** |
||||
* flink parameters |
||||
*/ |
||||
private FlinkParameters flinkParameters; |
||||
|
||||
/** |
||||
* taskExecutionContext |
||||
*/ |
||||
private TaskExecutionContext taskExecutionContext; |
||||
|
||||
public FlinkTask(TaskExecutionContext taskExecutionContext, Logger logger) { |
||||
super(taskExecutionContext, logger); |
||||
this.taskExecutionContext = taskExecutionContext; |
||||
} |
||||
|
||||
@Override |
||||
public void init() { |
||||
|
||||
logger.info("flink task params {}", taskExecutionContext.getTaskParams()); |
||||
|
||||
flinkParameters = JSONUtils.parseObject(taskExecutionContext.getTaskParams(), FlinkParameters.class); |
||||
|
||||
if (flinkParameters == null || !flinkParameters.checkParameters()) { |
||||
throw new RuntimeException("flink task params is not valid"); |
||||
} |
||||
flinkParameters.setQueue(taskExecutionContext.getQueue()); |
||||
setMainJarName(); |
||||
|
||||
if (StringUtils.isNotEmpty(flinkParameters.getMainArgs())) { |
||||
String args = flinkParameters.getMainArgs(); |
||||
|
||||
// combining local and global parameters
|
||||
Map<String, Property> paramsMap = ParamUtils.convert(taskExecutionContext,getParameters()); |
||||
|
||||
logger.info("param Map : {}", paramsMap); |
||||
if (paramsMap != null) { |
||||
args = ParameterUtils.convertParameterPlaceholders(args, ParamUtils.convert(paramsMap)); |
||||
logger.info("param args : {}", args); |
||||
} |
||||
flinkParameters.setMainArgs(args); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* create command |
||||
* @return command |
||||
*/ |
||||
@Override |
||||
protected String buildCommand() { |
||||
// flink run [OPTIONS] <jar-file> <arguments>
|
||||
List<String> args = new ArrayList<>(); |
||||
|
||||
args.add(FLINK_COMMAND); |
||||
args.add(FLINK_RUN); |
||||
logger.info("flink task args : {}", args); |
||||
// other parameters
|
||||
args.addAll(FlinkArgsUtils.buildArgs(flinkParameters)); |
||||
|
||||
String command = ParameterUtils |
||||
.convertParameterPlaceholders(String.join(" ", args), taskExecutionContext.getDefinedParams()); |
||||
|
||||
logger.info("flink task command : {}", command); |
||||
|
||||
return command; |
||||
} |
||||
|
||||
@Override |
||||
protected void setMainJarName() { |
||||
// main jar
|
||||
ResourceInfo mainJar = flinkParameters.getMainJar(); |
||||
if (mainJar != null) { |
||||
int resourceId = mainJar.getId(); |
||||
String resourceName; |
||||
if (resourceId == 0) { |
||||
resourceName = mainJar.getRes(); |
||||
} else { |
||||
Resource resource = processService.getResourceById(flinkParameters.getMainJar().getId()); |
||||
if (resource == null) { |
||||
logger.error("resource id: {} not exist", resourceId); |
||||
throw new RuntimeException(String.format("resource id: %d not exist", resourceId)); |
||||
} |
||||
resourceName = resource.getFullName().replaceFirst("/", ""); |
||||
} |
||||
mainJar.setRes(resourceName); |
||||
flinkParameters.setMainJar(mainJar); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public AbstractParameters getParameters() { |
||||
return flinkParameters; |
||||
} |
||||
} |
@ -1,332 +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.server.worker.task.http; |
||||
|
||||
import org.apache.dolphinscheduler.common.Constants; |
||||
import org.apache.dolphinscheduler.common.enums.HttpMethod; |
||||
import org.apache.dolphinscheduler.common.enums.HttpParametersType; |
||||
import org.apache.dolphinscheduler.common.process.HttpProperty; |
||||
import org.apache.dolphinscheduler.common.process.Property; |
||||
import org.apache.dolphinscheduler.common.task.AbstractParameters; |
||||
import org.apache.dolphinscheduler.common.task.http.HttpParameters; |
||||
import org.apache.dolphinscheduler.common.utils.CollectionUtils; |
||||
import org.apache.dolphinscheduler.common.utils.DateUtils; |
||||
import org.apache.dolphinscheduler.common.utils.JSONUtils; |
||||
import org.apache.dolphinscheduler.common.utils.ParameterUtils; |
||||
import org.apache.dolphinscheduler.common.utils.StringUtils; |
||||
import org.apache.dolphinscheduler.server.entity.TaskExecutionContext; |
||||
import org.apache.dolphinscheduler.server.utils.ParamUtils; |
||||
import org.apache.dolphinscheduler.server.worker.task.AbstractTask; |
||||
|
||||
import org.apache.commons.io.Charsets; |
||||
import org.apache.http.HttpEntity; |
||||
import org.apache.http.ParseException; |
||||
import org.apache.http.client.config.RequestConfig; |
||||
import org.apache.http.client.methods.CloseableHttpResponse; |
||||
import org.apache.http.client.methods.HttpUriRequest; |
||||
import org.apache.http.client.methods.RequestBuilder; |
||||
import org.apache.http.entity.StringEntity; |
||||
import org.apache.http.impl.client.CloseableHttpClient; |
||||
import org.apache.http.impl.client.HttpClientBuilder; |
||||
import org.apache.http.impl.client.HttpClients; |
||||
import org.apache.http.util.EntityUtils; |
||||
|
||||
import java.io.IOException; |
||||
import java.nio.charset.StandardCharsets; |
||||
import java.util.ArrayList; |
||||
import java.util.List; |
||||
import java.util.Map; |
||||
|
||||
import org.slf4j.Logger; |
||||
|
||||
import com.fasterxml.jackson.databind.node.ObjectNode; |
||||
|
||||
/** |
||||
* http task |
||||
*/ |
||||
public class HttpTask extends AbstractTask { |
||||
|
||||
/** |
||||
* application json |
||||
*/ |
||||
protected static final String APPLICATION_JSON = "application/json"; |
||||
/** |
||||
* output |
||||
*/ |
||||
protected String output; |
||||
/** |
||||
* http parameters |
||||
*/ |
||||
private HttpParameters httpParameters; |
||||
/** |
||||
* taskExecutionContext |
||||
*/ |
||||
private TaskExecutionContext taskExecutionContext; |
||||
|
||||
/** |
||||
* constructor |
||||
* |
||||
* @param taskExecutionContext taskExecutionContext |
||||
* @param logger logger |
||||
*/ |
||||
public HttpTask(TaskExecutionContext taskExecutionContext, Logger logger) { |
||||
super(taskExecutionContext, logger); |
||||
this.taskExecutionContext = taskExecutionContext; |
||||
} |
||||
|
||||
@Override |
||||
public void init() { |
||||
logger.info("http task params {}", taskExecutionContext.getTaskParams()); |
||||
this.httpParameters = JSONUtils.parseObject(taskExecutionContext.getTaskParams(), HttpParameters.class); |
||||
|
||||
if (!httpParameters.checkParameters()) { |
||||
throw new RuntimeException("http task params is not valid"); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public void handle() throws Exception { |
||||
String threadLoggerInfoName = String.format(Constants.TASK_LOG_INFO_FORMAT, taskExecutionContext.getTaskAppId()); |
||||
Thread.currentThread().setName(threadLoggerInfoName); |
||||
|
||||
long startTime = System.currentTimeMillis(); |
||||
String formatTimeStamp = DateUtils.formatTimeStamp(startTime); |
||||
String statusCode = null; |
||||
String body = null; |
||||
|
||||
try (CloseableHttpClient client = createHttpClient(); |
||||
CloseableHttpResponse response = sendRequest(client)) { |
||||
statusCode = String.valueOf(getStatusCode(response)); |
||||
body = getResponseBody(response); |
||||
exitStatusCode = validResponse(body, statusCode); |
||||
long costTime = System.currentTimeMillis() - startTime; |
||||
logger.info("startTime: {}, httpUrl: {}, httpMethod: {}, costTime : {} milliseconds, statusCode : {}, body : {}, log : {}", |
||||
formatTimeStamp, httpParameters.getUrl(), |
||||
httpParameters.getHttpMethod(), costTime, statusCode, body, output); |
||||
} catch (Exception e) { |
||||
appendMessage(e.toString()); |
||||
exitStatusCode = -1; |
||||
logger.error("httpUrl[" + httpParameters.getUrl() + "] connection failed:" + output, e); |
||||
throw e; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* send request |
||||
* |
||||
* @param client client |
||||
* @return CloseableHttpResponse |
||||
* @throws IOException io exception |
||||
*/ |
||||
protected CloseableHttpResponse sendRequest(CloseableHttpClient client) throws IOException { |
||||
RequestBuilder builder = createRequestBuilder(); |
||||
|
||||
// replace placeholder,and combine local and global parameters
|
||||
Map<String, Property> paramsMap = ParamUtils.convert(taskExecutionContext,getParameters()); |
||||
|
||||
List<HttpProperty> httpPropertyList = new ArrayList<>(); |
||||
if (CollectionUtils.isNotEmpty(httpParameters.getHttpParams())) { |
||||
for (HttpProperty httpProperty : httpParameters.getHttpParams()) { |
||||
String jsonObject = JSONUtils.toJsonString(httpProperty); |
||||
String params = ParameterUtils.convertParameterPlaceholders(jsonObject, ParamUtils.convert(paramsMap)); |
||||
logger.info("http request params:{}", params); |
||||
httpPropertyList.add(JSONUtils.parseObject(params, HttpProperty.class)); |
||||
} |
||||
} |
||||
addRequestParams(builder, httpPropertyList); |
||||
String requestUrl = ParameterUtils.convertParameterPlaceholders(httpParameters.getUrl(), ParamUtils.convert(paramsMap)); |
||||
HttpUriRequest request = builder.setUri(requestUrl).build(); |
||||
setHeaders(request, httpPropertyList); |
||||
return client.execute(request); |
||||
} |
||||
|
||||
/** |
||||
* get response body |
||||
* |
||||
* @param httpResponse http response |
||||
* @return response body |
||||
* @throws ParseException parse exception |
||||
* @throws IOException io exception |
||||
*/ |
||||
protected String getResponseBody(CloseableHttpResponse httpResponse) throws ParseException, IOException { |
||||
if (httpResponse == null) { |
||||
return null; |
||||
} |
||||
HttpEntity entity = httpResponse.getEntity(); |
||||
if (entity == null) { |
||||
return null; |
||||
} |
||||
return EntityUtils.toString(entity, StandardCharsets.UTF_8.name()); |
||||
} |
||||
|
||||
/** |
||||
* get status code |
||||
* |
||||
* @param httpResponse http response |
||||
* @return status code |
||||
*/ |
||||
protected int getStatusCode(CloseableHttpResponse httpResponse) { |
||||
return httpResponse.getStatusLine().getStatusCode(); |
||||
} |
||||
|
||||
/** |
||||
* valid response |
||||
* |
||||
* @param body body |
||||
* @param statusCode status code |
||||
* @return exit status code |
||||
*/ |
||||
protected int validResponse(String body, String statusCode) { |
||||
int exitStatusCode = 0; |
||||
switch (httpParameters.getHttpCheckCondition()) { |
||||
case BODY_CONTAINS: |
||||
if (StringUtils.isEmpty(body) || !body.contains(httpParameters.getCondition())) { |
||||
appendMessage(httpParameters.getUrl() + " doesn contain " |
||||
+ httpParameters.getCondition()); |
||||
exitStatusCode = -1; |
||||
} |
||||
break; |
||||
case BODY_NOT_CONTAINS: |
||||
if (StringUtils.isEmpty(body) || body.contains(httpParameters.getCondition())) { |
||||
appendMessage(httpParameters.getUrl() + " contains " |
||||
+ httpParameters.getCondition()); |
||||
exitStatusCode = -1; |
||||
} |
||||
break; |
||||
case STATUS_CODE_CUSTOM: |
||||
if (!statusCode.equals(httpParameters.getCondition())) { |
||||
appendMessage(httpParameters.getUrl() + " statuscode: " + statusCode + ", Must be: " + httpParameters.getCondition()); |
||||
exitStatusCode = -1; |
||||
} |
||||
break; |
||||
default: |
||||
if (!"200".equals(statusCode)) { |
||||
appendMessage(httpParameters.getUrl() + " statuscode: " + statusCode + ", Must be: 200"); |
||||
exitStatusCode = -1; |
||||
} |
||||
break; |
||||
} |
||||
return exitStatusCode; |
||||
} |
||||
|
||||
public String getOutput() { |
||||
return output; |
||||
} |
||||
|
||||
/** |
||||
* append message |
||||
* |
||||
* @param message message |
||||
*/ |
||||
protected void appendMessage(String message) { |
||||
if (output == null) { |
||||
output = ""; |
||||
} |
||||
if (message != null && !message.trim().isEmpty()) { |
||||
output += message; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* add request params |
||||
* |
||||
* @param builder buidler |
||||
* @param httpPropertyList http property list |
||||
*/ |
||||
protected void addRequestParams(RequestBuilder builder, List<HttpProperty> httpPropertyList) { |
||||
if (CollectionUtils.isNotEmpty(httpPropertyList)) { |
||||
ObjectNode jsonParam = JSONUtils.createObjectNode(); |
||||
for (HttpProperty property : httpPropertyList) { |
||||
if (property.getHttpParametersType() != null) { |
||||
if (property.getHttpParametersType().equals(HttpParametersType.PARAMETER)) { |
||||
builder.addParameter(property.getProp(), property.getValue()); |
||||
} else if (property.getHttpParametersType().equals(HttpParametersType.BODY)) { |
||||
jsonParam.put(property.getProp(), property.getValue()); |
||||
} |
||||
} |
||||
} |
||||
StringEntity postingString = new StringEntity(jsonParam.toString(), Charsets.UTF_8); |
||||
postingString.setContentEncoding(StandardCharsets.UTF_8.name()); |
||||
postingString.setContentType(APPLICATION_JSON); |
||||
builder.setEntity(postingString); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* set headers |
||||
* |
||||
* @param request request |
||||
* @param httpPropertyList http property list |
||||
*/ |
||||
protected void setHeaders(HttpUriRequest request, List<HttpProperty> httpPropertyList) { |
||||
if (CollectionUtils.isNotEmpty(httpPropertyList)) { |
||||
for (HttpProperty property : httpPropertyList) { |
||||
if (HttpParametersType.HEADERS.equals(property.getHttpParametersType())) { |
||||
request.addHeader(property.getProp(), property.getValue()); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* create http client |
||||
* |
||||
* @return CloseableHttpClient |
||||
*/ |
||||
protected CloseableHttpClient createHttpClient() { |
||||
final RequestConfig requestConfig = requestConfig(); |
||||
HttpClientBuilder httpClientBuilder; |
||||
httpClientBuilder = HttpClients.custom().setDefaultRequestConfig(requestConfig); |
||||
return httpClientBuilder.build(); |
||||
} |
||||
|
||||
/** |
||||
* request config |
||||
* |
||||
* @return RequestConfig |
||||
*/ |
||||
private RequestConfig requestConfig() { |
||||
return RequestConfig.custom().setSocketTimeout(httpParameters.getSocketTimeout()).setConnectTimeout(httpParameters.getConnectTimeout()).build(); |
||||
} |
||||
|
||||
/** |
||||
* create request builder |
||||
* |
||||
* @return RequestBuilder |
||||
*/ |
||||
protected RequestBuilder createRequestBuilder() { |
||||
if (httpParameters.getHttpMethod().equals(HttpMethod.GET)) { |
||||
return RequestBuilder.get(); |
||||
} else if (httpParameters.getHttpMethod().equals(HttpMethod.POST)) { |
||||
return RequestBuilder.post(); |
||||
} else if (httpParameters.getHttpMethod().equals(HttpMethod.HEAD)) { |
||||
return RequestBuilder.head(); |
||||
} else if (httpParameters.getHttpMethod().equals(HttpMethod.PUT)) { |
||||
return RequestBuilder.put(); |
||||
} else if (httpParameters.getHttpMethod().equals(HttpMethod.DELETE)) { |
||||
return RequestBuilder.delete(); |
||||
} else { |
||||
return null; |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public AbstractParameters getParameters() { |
||||
return this.httpParameters; |
||||
} |
||||
} |
@ -1,145 +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.server.worker.task.mr; |
||||
|
||||
import org.apache.dolphinscheduler.common.Constants; |
||||
import org.apache.dolphinscheduler.common.enums.ProgramType; |
||||
import org.apache.dolphinscheduler.common.process.Property; |
||||
import org.apache.dolphinscheduler.common.process.ResourceInfo; |
||||
import org.apache.dolphinscheduler.common.task.AbstractParameters; |
||||
import org.apache.dolphinscheduler.common.task.mr.MapReduceParameters; |
||||
import org.apache.dolphinscheduler.common.utils.JSONUtils; |
||||
import org.apache.dolphinscheduler.common.utils.ParameterUtils; |
||||
import org.apache.dolphinscheduler.dao.entity.Resource; |
||||
import org.apache.dolphinscheduler.server.entity.TaskExecutionContext; |
||||
import org.apache.dolphinscheduler.server.utils.MapReduceArgsUtils; |
||||
import org.apache.dolphinscheduler.server.utils.ParamUtils; |
||||
import org.apache.dolphinscheduler.server.worker.task.AbstractYarnTask; |
||||
|
||||
import java.util.ArrayList; |
||||
import java.util.List; |
||||
import java.util.Map; |
||||
|
||||
import org.slf4j.Logger; |
||||
|
||||
/** |
||||
* mapreduce task |
||||
*/ |
||||
public class MapReduceTask extends AbstractYarnTask { |
||||
|
||||
/** |
||||
* mapreduce command |
||||
* usage: hadoop jar <jar> [mainClass] [GENERIC_OPTIONS] args... |
||||
*/ |
||||
private static final String MAPREDUCE_COMMAND = Constants.HADOOP; |
||||
|
||||
/** |
||||
* mapreduce parameters |
||||
*/ |
||||
private MapReduceParameters mapreduceParameters; |
||||
|
||||
/** |
||||
* taskExecutionContext |
||||
*/ |
||||
private TaskExecutionContext taskExecutionContext; |
||||
|
||||
/** |
||||
* constructor |
||||
* @param taskExecutionContext taskExecutionContext |
||||
* @param logger logger |
||||
*/ |
||||
public MapReduceTask(TaskExecutionContext taskExecutionContext, Logger logger) { |
||||
super(taskExecutionContext, logger); |
||||
this.taskExecutionContext = taskExecutionContext; |
||||
} |
||||
|
||||
@Override |
||||
public void init() { |
||||
|
||||
logger.info("mapreduce task params {}", taskExecutionContext.getTaskParams()); |
||||
|
||||
this.mapreduceParameters = JSONUtils.parseObject(taskExecutionContext.getTaskParams(), MapReduceParameters.class); |
||||
|
||||
// check parameters
|
||||
if (mapreduceParameters == null || !mapreduceParameters.checkParameters()) { |
||||
throw new RuntimeException("mapreduce task params is not valid"); |
||||
} |
||||
|
||||
mapreduceParameters.setQueue(taskExecutionContext.getQueue()); |
||||
setMainJarName(); |
||||
|
||||
// replace placeholder,and combine local and global parameters
|
||||
Map<String, Property> paramsMap = ParamUtils.convert(taskExecutionContext,getParameters()); |
||||
|
||||
if (paramsMap != null) { |
||||
String args = ParameterUtils.convertParameterPlaceholders(mapreduceParameters.getMainArgs(), ParamUtils.convert(paramsMap)); |
||||
mapreduceParameters.setMainArgs(args); |
||||
if (mapreduceParameters.getProgramType() != null && mapreduceParameters.getProgramType() == ProgramType.PYTHON) { |
||||
String others = ParameterUtils.convertParameterPlaceholders(mapreduceParameters.getOthers(), ParamUtils.convert(paramsMap)); |
||||
mapreduceParameters.setOthers(others); |
||||
} |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* build command |
||||
* @return command |
||||
*/ |
||||
@Override |
||||
protected String buildCommand() { |
||||
// hadoop jar <jar> [mainClass] [GENERIC_OPTIONS] args...
|
||||
List<String> args = new ArrayList<>(); |
||||
args.add(MAPREDUCE_COMMAND); |
||||
|
||||
// other parameters
|
||||
args.addAll(MapReduceArgsUtils.buildArgs(mapreduceParameters)); |
||||
|
||||
String command = ParameterUtils.convertParameterPlaceholders(String.join(" ", args), |
||||
taskExecutionContext.getDefinedParams()); |
||||
logger.info("mapreduce task command: {}", command); |
||||
|
||||
return command; |
||||
} |
||||
|
||||
@Override |
||||
protected void setMainJarName() { |
||||
// main jar
|
||||
ResourceInfo mainJar = mapreduceParameters.getMainJar(); |
||||
if (mainJar != null) { |
||||
int resourceId = mainJar.getId(); |
||||
String resourceName; |
||||
if (resourceId == 0) { |
||||
resourceName = mainJar.getRes(); |
||||
} else { |
||||
Resource resource = processService.getResourceById(mapreduceParameters.getMainJar().getId()); |
||||
if (resource == null) { |
||||
logger.error("resource id: {} not exist", resourceId); |
||||
throw new RuntimeException(String.format("resource id: %d not exist", resourceId)); |
||||
} |
||||
resourceName = resource.getFullName().replaceFirst("/", ""); |
||||
} |
||||
mainJar.setRes(resourceName); |
||||
mapreduceParameters.setMainJar(mainJar); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public AbstractParameters getParameters() { |
||||
return mapreduceParameters; |
||||
} |
||||
} |
@ -1,341 +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.server.worker.task.procedure; |
||||
|
||||
import static org.apache.dolphinscheduler.common.enums.DataType.BOOLEAN; |
||||
import static org.apache.dolphinscheduler.common.enums.DataType.DATE; |
||||
import static org.apache.dolphinscheduler.common.enums.DataType.DOUBLE; |
||||
import static org.apache.dolphinscheduler.common.enums.DataType.FLOAT; |
||||
import static org.apache.dolphinscheduler.common.enums.DataType.INTEGER; |
||||
import static org.apache.dolphinscheduler.common.enums.DataType.LONG; |
||||
import static org.apache.dolphinscheduler.common.enums.DataType.TIME; |
||||
import static org.apache.dolphinscheduler.common.enums.DataType.TIMESTAMP; |
||||
import static org.apache.dolphinscheduler.common.enums.DataType.VARCHAR; |
||||
|
||||
import org.apache.dolphinscheduler.common.Constants; |
||||
import org.apache.dolphinscheduler.common.datasource.ConnectionParam; |
||||
import org.apache.dolphinscheduler.common.datasource.DatasourceUtil; |
||||
import org.apache.dolphinscheduler.common.enums.DataType; |
||||
import org.apache.dolphinscheduler.common.enums.DbType; |
||||
import org.apache.dolphinscheduler.common.enums.Direct; |
||||
import org.apache.dolphinscheduler.common.enums.TaskTimeoutStrategy; |
||||
import org.apache.dolphinscheduler.common.process.Property; |
||||
import org.apache.dolphinscheduler.common.task.AbstractParameters; |
||||
import org.apache.dolphinscheduler.common.task.procedure.ProcedureParameters; |
||||
import org.apache.dolphinscheduler.common.utils.CollectionUtils; |
||||
import org.apache.dolphinscheduler.common.utils.JSONUtils; |
||||
import org.apache.dolphinscheduler.common.utils.ParameterUtils; |
||||
import org.apache.dolphinscheduler.common.utils.StringUtils; |
||||
import org.apache.dolphinscheduler.server.entity.TaskExecutionContext; |
||||
import org.apache.dolphinscheduler.server.utils.ParamUtils; |
||||
import org.apache.dolphinscheduler.server.worker.task.AbstractTask; |
||||
|
||||
import java.sql.CallableStatement; |
||||
import java.sql.Connection; |
||||
import java.sql.PreparedStatement; |
||||
import java.sql.SQLException; |
||||
import java.sql.Types; |
||||
import java.util.Collection; |
||||
import java.util.HashMap; |
||||
import java.util.Iterator; |
||||
import java.util.Map; |
||||
|
||||
import org.slf4j.Logger; |
||||
|
||||
/** |
||||
* procedure task |
||||
*/ |
||||
public class ProcedureTask extends AbstractTask { |
||||
|
||||
/** |
||||
* procedure parameters |
||||
*/ |
||||
private ProcedureParameters procedureParameters; |
||||
|
||||
/** |
||||
* taskExecutionContext |
||||
*/ |
||||
private TaskExecutionContext taskExecutionContext; |
||||
|
||||
/** |
||||
* constructor |
||||
* |
||||
* @param taskExecutionContext taskExecutionContext |
||||
* @param logger logger |
||||
*/ |
||||
public ProcedureTask(TaskExecutionContext taskExecutionContext, Logger logger) { |
||||
super(taskExecutionContext, logger); |
||||
|
||||
this.taskExecutionContext = taskExecutionContext; |
||||
|
||||
logger.info("procedure task params {}", taskExecutionContext.getTaskParams()); |
||||
|
||||
this.procedureParameters = JSONUtils.parseObject(taskExecutionContext.getTaskParams(), ProcedureParameters.class); |
||||
|
||||
// check parameters
|
||||
if (!procedureParameters.checkParameters()) { |
||||
throw new RuntimeException("procedure task params is not valid"); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public void handle() throws Exception { |
||||
// set the name of the current thread
|
||||
String threadLoggerInfoName = String.format(Constants.TASK_LOG_INFO_FORMAT, taskExecutionContext.getTaskAppId()); |
||||
Thread.currentThread().setName(threadLoggerInfoName); |
||||
|
||||
logger.info("procedure type : {}, datasource : {}, method : {} , localParams : {}", |
||||
procedureParameters.getType(), |
||||
procedureParameters.getDatasource(), |
||||
procedureParameters.getMethod(), |
||||
procedureParameters.getLocalParams()); |
||||
|
||||
Connection connection = null; |
||||
CallableStatement stmt = null; |
||||
try { |
||||
// load class
|
||||
DbType dbType = DbType.valueOf(procedureParameters.getType()); |
||||
// get datasource
|
||||
ConnectionParam connectionParam = DatasourceUtil.buildConnectionParams(DbType.valueOf(procedureParameters.getType()), |
||||
taskExecutionContext.getProcedureTaskExecutionContext().getConnectionParams()); |
||||
|
||||
// get jdbc connection
|
||||
connection = DatasourceUtil.getConnection(dbType, connectionParam); |
||||
|
||||
// combining local and global parameters
|
||||
Map<String, Property> paramsMap = ParamUtils.convert(taskExecutionContext,getParameters()); |
||||
|
||||
// call method
|
||||
stmt = connection.prepareCall(procedureParameters.getMethod()); |
||||
|
||||
// set timeout
|
||||
setTimeout(stmt); |
||||
|
||||
// outParameterMap
|
||||
Map<Integer, Property> outParameterMap = getOutParameterMap(stmt, paramsMap); |
||||
|
||||
stmt.executeUpdate(); |
||||
|
||||
// print the output parameters to the log
|
||||
printOutParameter(stmt, outParameterMap); |
||||
|
||||
setExitStatusCode(Constants.EXIT_CODE_SUCCESS); |
||||
} catch (Exception e) { |
||||
setExitStatusCode(Constants.EXIT_CODE_FAILURE); |
||||
logger.error("procedure task error", e); |
||||
throw e; |
||||
} finally { |
||||
close(stmt, connection); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* print outParameter |
||||
* |
||||
* @param stmt CallableStatement |
||||
* @param outParameterMap outParameterMap |
||||
* @throws SQLException SQLException |
||||
*/ |
||||
private void printOutParameter(CallableStatement stmt, |
||||
Map<Integer, Property> outParameterMap) throws SQLException { |
||||
Iterator<Map.Entry<Integer, Property>> iter = outParameterMap.entrySet().iterator(); |
||||
while (iter.hasNext()) { |
||||
Map.Entry<Integer, Property> en = iter.next(); |
||||
|
||||
int index = en.getKey(); |
||||
Property property = en.getValue(); |
||||
String prop = property.getProp(); |
||||
DataType dataType = property.getType(); |
||||
// get output parameter
|
||||
getOutputParameter(stmt, index, prop, dataType); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* get output parameter |
||||
* |
||||
* @param stmt CallableStatement |
||||
* @param paramsMap paramsMap |
||||
* @return outParameterMap |
||||
* @throws Exception Exception |
||||
*/ |
||||
private Map<Integer, Property> getOutParameterMap(CallableStatement stmt, Map<String, Property> paramsMap) throws Exception { |
||||
Map<Integer, Property> outParameterMap = new HashMap<>(); |
||||
if (procedureParameters.getLocalParametersMap() == null) { |
||||
return outParameterMap; |
||||
} |
||||
|
||||
Collection<Property> userDefParamsList = procedureParameters.getLocalParametersMap().values(); |
||||
|
||||
if (CollectionUtils.isEmpty(userDefParamsList)) { |
||||
return outParameterMap; |
||||
} |
||||
|
||||
int index = 1; |
||||
for (Property property : userDefParamsList) { |
||||
logger.info("localParams : prop : {} , dirct : {} , type : {} , value : {}" |
||||
, property.getProp(), |
||||
property.getDirect(), |
||||
property.getType(), |
||||
property.getValue()); |
||||
// set parameters
|
||||
if (property.getDirect().equals(Direct.IN)) { |
||||
ParameterUtils.setInParameter(index, stmt, property.getType(), paramsMap.get(property.getProp()).getValue()); |
||||
} else if (property.getDirect().equals(Direct.OUT)) { |
||||
setOutParameter(index, stmt, property.getType(), paramsMap.get(property.getProp()).getValue()); |
||||
property.setValue(paramsMap.get(property.getProp()).getValue()); |
||||
outParameterMap.put(index, property); |
||||
} |
||||
index++; |
||||
} |
||||
|
||||
return outParameterMap; |
||||
} |
||||
|
||||
/** |
||||
* set timeout |
||||
* |
||||
* @param stmt CallableStatement |
||||
*/ |
||||
private void setTimeout(CallableStatement stmt) throws SQLException { |
||||
Boolean failed = taskExecutionContext.getTaskTimeoutStrategy() == TaskTimeoutStrategy.FAILED; |
||||
Boolean warnFailed = taskExecutionContext.getTaskTimeoutStrategy() == TaskTimeoutStrategy.WARNFAILED; |
||||
if (failed || warnFailed) { |
||||
stmt.setQueryTimeout(taskExecutionContext.getTaskTimeout()); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* close jdbc resource |
||||
* |
||||
* @param stmt stmt |
||||
* @param connection connection |
||||
*/ |
||||
private void close(PreparedStatement stmt, Connection connection) { |
||||
if (stmt != null) { |
||||
try { |
||||
stmt.close(); |
||||
} catch (SQLException e) { |
||||
logger.error("close prepared statement error : {}", e.getMessage(), e); |
||||
} |
||||
} |
||||
if (connection != null) { |
||||
try { |
||||
connection.close(); |
||||
} catch (SQLException e) { |
||||
logger.error("close connection error : {}", e.getMessage(), e); |
||||
} |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* get output parameter |
||||
* |
||||
* @param stmt stmt |
||||
* @param index index |
||||
* @param prop prop |
||||
* @param dataType dataType |
||||
* @throws SQLException SQLException |
||||
*/ |
||||
private void getOutputParameter(CallableStatement stmt, int index, String prop, DataType dataType) throws SQLException { |
||||
switch (dataType) { |
||||
case VARCHAR: |
||||
logger.info("out prameter varchar key : {} , value : {}", prop, stmt.getString(index)); |
||||
break; |
||||
case INTEGER: |
||||
logger.info("out prameter integer key : {} , value : {}", prop, stmt.getInt(index)); |
||||
break; |
||||
case LONG: |
||||
logger.info("out prameter long key : {} , value : {}", prop, stmt.getLong(index)); |
||||
break; |
||||
case FLOAT: |
||||
logger.info("out prameter float key : {} , value : {}", prop, stmt.getFloat(index)); |
||||
break; |
||||
case DOUBLE: |
||||
logger.info("out prameter double key : {} , value : {}", prop, stmt.getDouble(index)); |
||||
break; |
||||
case DATE: |
||||
logger.info("out prameter date key : {} , value : {}", prop, stmt.getDate(index)); |
||||
break; |
||||
case TIME: |
||||
logger.info("out prameter time key : {} , value : {}", prop, stmt.getTime(index)); |
||||
break; |
||||
case TIMESTAMP: |
||||
logger.info("out prameter timestamp key : {} , value : {}", prop, stmt.getTimestamp(index)); |
||||
break; |
||||
case BOOLEAN: |
||||
logger.info("out prameter boolean key : {} , value : {}", prop, stmt.getBoolean(index)); |
||||
break; |
||||
default: |
||||
break; |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public AbstractParameters getParameters() { |
||||
return procedureParameters; |
||||
} |
||||
|
||||
/** |
||||
* set out parameter |
||||
* |
||||
* @param index index |
||||
* @param stmt stmt |
||||
* @param dataType dataType |
||||
* @param value value |
||||
* @throws Exception exception |
||||
*/ |
||||
private void setOutParameter(int index, CallableStatement stmt, DataType dataType, String value) throws Exception { |
||||
int sqlType; |
||||
switch (dataType) { |
||||
case VARCHAR: |
||||
sqlType = Types.VARCHAR; |
||||
break; |
||||
case INTEGER: |
||||
case LONG: |
||||
sqlType = Types.INTEGER; |
||||
break; |
||||
case FLOAT: |
||||
sqlType = Types.FLOAT; |
||||
break; |
||||
case DOUBLE: |
||||
sqlType = Types.DOUBLE; |
||||
break; |
||||
case DATE: |
||||
sqlType = Types.DATE; |
||||
break; |
||||
case TIME: |
||||
sqlType = Types.TIME; |
||||
break; |
||||
case TIMESTAMP: |
||||
sqlType = Types.TIMESTAMP; |
||||
break; |
||||
case BOOLEAN: |
||||
sqlType = Types.BOOLEAN; |
||||
break; |
||||
default: |
||||
throw new IllegalStateException("Unexpected value: " + dataType); |
||||
} |
||||
|
||||
if (StringUtils.isEmpty(value)) { |
||||
stmt.registerOutParameter(index, sqlType); |
||||
} else { |
||||
stmt.registerOutParameter(index, sqlType, value); |
||||
} |
||||
} |
||||
} |
@ -1,144 +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.server.worker.task.python; |
||||
|
||||
import org.apache.dolphinscheduler.common.Constants; |
||||
import org.apache.dolphinscheduler.common.process.Property; |
||||
import org.apache.dolphinscheduler.common.task.AbstractParameters; |
||||
import org.apache.dolphinscheduler.common.task.python.PythonParameters; |
||||
import org.apache.dolphinscheduler.common.utils.JSONUtils; |
||||
import org.apache.dolphinscheduler.common.utils.ParameterUtils; |
||||
import org.apache.dolphinscheduler.common.utils.VarPoolUtils; |
||||
import org.apache.dolphinscheduler.server.entity.TaskExecutionContext; |
||||
import org.apache.dolphinscheduler.server.utils.ParamUtils; |
||||
import org.apache.dolphinscheduler.server.worker.task.AbstractTask; |
||||
import org.apache.dolphinscheduler.server.worker.task.CommandExecuteResult; |
||||
import org.apache.dolphinscheduler.server.worker.task.PythonCommandExecutor; |
||||
|
||||
import java.util.Map; |
||||
|
||||
import org.slf4j.Logger; |
||||
|
||||
/** |
||||
* python task |
||||
*/ |
||||
public class PythonTask extends AbstractTask { |
||||
|
||||
/** |
||||
* python parameters |
||||
*/ |
||||
private PythonParameters pythonParameters; |
||||
|
||||
/** |
||||
* task dir |
||||
*/ |
||||
private String taskDir; |
||||
|
||||
/** |
||||
* python command executor |
||||
*/ |
||||
private PythonCommandExecutor pythonCommandExecutor; |
||||
|
||||
/** |
||||
* taskExecutionContext |
||||
*/ |
||||
private TaskExecutionContext taskExecutionContext; |
||||
|
||||
/** |
||||
* constructor |
||||
* @param taskExecutionContext taskExecutionContext |
||||
* @param logger logger |
||||
*/ |
||||
public PythonTask(TaskExecutionContext taskExecutionContext, Logger logger) { |
||||
super(taskExecutionContext, logger); |
||||
this.taskExecutionContext = taskExecutionContext; |
||||
|
||||
this.pythonCommandExecutor = new PythonCommandExecutor(this::logHandle, |
||||
taskExecutionContext, |
||||
logger); |
||||
} |
||||
|
||||
@Override |
||||
public void init() { |
||||
logger.info("python task params {}", taskExecutionContext.getTaskParams()); |
||||
|
||||
pythonParameters = JSONUtils.parseObject(taskExecutionContext.getTaskParams(), PythonParameters.class); |
||||
|
||||
if (!pythonParameters.checkParameters()) { |
||||
throw new RuntimeException("python task params is not valid"); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public void handle() throws Exception { |
||||
try { |
||||
// construct process
|
||||
CommandExecuteResult commandExecuteResult = pythonCommandExecutor.run(buildCommand()); |
||||
|
||||
setExitStatusCode(commandExecuteResult.getExitStatusCode()); |
||||
setAppIds(commandExecuteResult.getAppIds()); |
||||
setProcessId(commandExecuteResult.getProcessId()); |
||||
pythonParameters.dealOutParam(pythonCommandExecutor.getVarPool()); |
||||
} |
||||
catch (Exception e) { |
||||
logger.error("python task failure", e); |
||||
setExitStatusCode(Constants.EXIT_CODE_FAILURE); |
||||
throw e; |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public void cancelApplication(boolean cancelApplication) throws Exception { |
||||
// cancel process
|
||||
pythonCommandExecutor.cancelApplication(); |
||||
} |
||||
|
||||
/** |
||||
* build command |
||||
* @return raw python script |
||||
* @throws Exception exception |
||||
*/ |
||||
private String buildCommand() throws Exception { |
||||
String rawPythonScript = pythonParameters.getRawScript().replaceAll("\\r\\n", "\n"); |
||||
|
||||
// combining local and global parameters
|
||||
Map<String, Property> paramsMap = ParamUtils.convert(taskExecutionContext,getParameters()); |
||||
|
||||
try { |
||||
rawPythonScript = VarPoolUtils.convertPythonScriptPlaceholders(rawPythonScript); |
||||
} |
||||
catch (StringIndexOutOfBoundsException e) { |
||||
logger.error("setShareVar field format error, raw python script : {}", rawPythonScript); |
||||
} |
||||
|
||||
if (paramsMap != null) { |
||||
rawPythonScript = ParameterUtils.convertParameterPlaceholders(rawPythonScript, ParamUtils.convert(paramsMap)); |
||||
} |
||||
|
||||
logger.info("raw python script : {}", pythonParameters.getRawScript()); |
||||
logger.info("task dir : {}", taskDir); |
||||
|
||||
return rawPythonScript; |
||||
} |
||||
|
||||
@Override |
||||
public AbstractParameters getParameters() { |
||||
return pythonParameters; |
||||
} |
||||
|
||||
} |
@ -1,185 +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.server.worker.task.shell; |
||||
|
||||
import static java.util.Calendar.DAY_OF_MONTH; |
||||
|
||||
import org.apache.dolphinscheduler.common.Constants; |
||||
import org.apache.dolphinscheduler.common.enums.CommandType; |
||||
import org.apache.dolphinscheduler.common.process.Property; |
||||
import org.apache.dolphinscheduler.common.task.AbstractParameters; |
||||
import org.apache.dolphinscheduler.common.task.shell.ShellParameters; |
||||
import org.apache.dolphinscheduler.common.utils.DateUtils; |
||||
import org.apache.dolphinscheduler.common.utils.JSONUtils; |
||||
import org.apache.dolphinscheduler.common.utils.OSUtils; |
||||
import org.apache.dolphinscheduler.common.utils.ParameterUtils; |
||||
import org.apache.dolphinscheduler.server.entity.TaskExecutionContext; |
||||
import org.apache.dolphinscheduler.server.utils.ParamUtils; |
||||
import org.apache.dolphinscheduler.server.worker.task.AbstractTask; |
||||
import org.apache.dolphinscheduler.server.worker.task.CommandExecuteResult; |
||||
import org.apache.dolphinscheduler.server.worker.task.ShellCommandExecutor; |
||||
|
||||
import java.io.File; |
||||
import java.nio.file.Files; |
||||
import java.nio.file.Path; |
||||
import java.nio.file.StandardOpenOption; |
||||
import java.nio.file.attribute.FileAttribute; |
||||
import java.nio.file.attribute.PosixFilePermission; |
||||
import java.nio.file.attribute.PosixFilePermissions; |
||||
import java.util.Date; |
||||
import java.util.HashMap; |
||||
import java.util.Map; |
||||
import java.util.Set; |
||||
|
||||
import org.slf4j.Logger; |
||||
|
||||
/** |
||||
* shell task |
||||
*/ |
||||
public class ShellTask extends AbstractTask { |
||||
|
||||
/** |
||||
* shell parameters |
||||
*/ |
||||
private ShellParameters shellParameters; |
||||
|
||||
/** |
||||
* shell command executor |
||||
*/ |
||||
private ShellCommandExecutor shellCommandExecutor; |
||||
|
||||
/** |
||||
* taskExecutionContext |
||||
*/ |
||||
private TaskExecutionContext taskExecutionContext; |
||||
|
||||
/** |
||||
* constructor |
||||
* |
||||
* @param taskExecutionContext taskExecutionContext |
||||
* @param logger logger |
||||
*/ |
||||
public ShellTask(TaskExecutionContext taskExecutionContext, Logger logger) { |
||||
super(taskExecutionContext, logger); |
||||
|
||||
this.taskExecutionContext = taskExecutionContext; |
||||
this.shellCommandExecutor = new ShellCommandExecutor(this::logHandle, |
||||
taskExecutionContext, |
||||
logger); |
||||
} |
||||
|
||||
@Override |
||||
public void init() { |
||||
logger.info("shell task params {}", taskExecutionContext.getTaskParams()); |
||||
|
||||
shellParameters = JSONUtils.parseObject(taskExecutionContext.getTaskParams(), ShellParameters.class); |
||||
|
||||
if (!shellParameters.checkParameters()) { |
||||
throw new RuntimeException("shell task params is not valid"); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public void handle() throws Exception { |
||||
try { |
||||
// construct process
|
||||
String command = buildCommand(); |
||||
CommandExecuteResult commandExecuteResult = shellCommandExecutor.run(command); |
||||
setExitStatusCode(commandExecuteResult.getExitStatusCode()); |
||||
setAppIds(commandExecuteResult.getAppIds()); |
||||
setProcessId(commandExecuteResult.getProcessId()); |
||||
shellParameters.dealOutParam(shellCommandExecutor.getVarPool()); |
||||
} catch (Exception e) { |
||||
logger.error("shell task error", e); |
||||
setExitStatusCode(Constants.EXIT_CODE_FAILURE); |
||||
throw e; |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public void cancelApplication(boolean cancelApplication) throws Exception { |
||||
// cancel process
|
||||
shellCommandExecutor.cancelApplication(); |
||||
} |
||||
|
||||
/** |
||||
* create command |
||||
* |
||||
* @return file name |
||||
* @throws Exception exception |
||||
*/ |
||||
private String buildCommand() throws Exception { |
||||
// generate scripts
|
||||
String fileName = String.format("%s/%s_node.%s", |
||||
taskExecutionContext.getExecutePath(), |
||||
taskExecutionContext.getTaskAppId(), OSUtils.isWindows() ? "bat" : "sh"); |
||||
|
||||
Path path = new File(fileName).toPath(); |
||||
|
||||
if (Files.exists(path)) { |
||||
return fileName; |
||||
} |
||||
|
||||
String script = shellParameters.getRawScript().replaceAll("\\r\\n", "\n"); |
||||
script = parseScript(script); |
||||
shellParameters.setRawScript(script); |
||||
|
||||
logger.info("raw script : {}", shellParameters.getRawScript()); |
||||
logger.info("task execute path : {}", taskExecutionContext.getExecutePath()); |
||||
|
||||
Set<PosixFilePermission> perms = PosixFilePermissions.fromString(Constants.RWXR_XR_X); |
||||
FileAttribute<Set<PosixFilePermission>> attr = PosixFilePermissions.asFileAttribute(perms); |
||||
|
||||
if (OSUtils.isWindows()) { |
||||
Files.createFile(path); |
||||
} else { |
||||
Files.createFile(path, attr); |
||||
} |
||||
|
||||
Files.write(path, shellParameters.getRawScript().getBytes(), StandardOpenOption.APPEND); |
||||
|
||||
return fileName; |
||||
} |
||||
|
||||
@Override |
||||
public AbstractParameters getParameters() { |
||||
return shellParameters; |
||||
} |
||||
|
||||
private String parseScript(String script) { |
||||
// combining local and global parameters
|
||||
Map<String, Property> paramsMap = ParamUtils.convert(taskExecutionContext,getParameters()); |
||||
|
||||
// replace variable TIME with $[YYYYmmddd...] in shell file when history run job and batch complement job
|
||||
if (taskExecutionContext.getScheduleTime() != null) { |
||||
if (paramsMap == null) { |
||||
paramsMap = new HashMap<>(); |
||||
} |
||||
Date date = taskExecutionContext.getScheduleTime(); |
||||
if (CommandType.COMPLEMENT_DATA.getCode() == taskExecutionContext.getCmdTypeIfComplement()) { |
||||
date = DateUtils.add(taskExecutionContext.getScheduleTime(), DAY_OF_MONTH, 1); |
||||
} |
||||
String dateTime = DateUtils.format(date, Constants.PARAMETER_FORMAT_TIME); |
||||
Property p = new Property(); |
||||
p.setValue(dateTime); |
||||
p.setProp(Constants.PARAMETER_DATETIME); |
||||
paramsMap.put(Constants.PARAMETER_DATETIME, p); |
||||
} |
||||
return ParameterUtils.convertParameterPlaceholders(script, ParamUtils.convert(paramsMap)); |
||||
} |
||||
} |
@ -1,155 +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.server.worker.task.spark; |
||||
|
||||
import org.apache.dolphinscheduler.common.enums.SparkVersion; |
||||
import org.apache.dolphinscheduler.common.process.Property; |
||||
import org.apache.dolphinscheduler.common.process.ResourceInfo; |
||||
import org.apache.dolphinscheduler.common.task.AbstractParameters; |
||||
import org.apache.dolphinscheduler.common.task.spark.SparkParameters; |
||||
import org.apache.dolphinscheduler.common.utils.JSONUtils; |
||||
import org.apache.dolphinscheduler.common.utils.ParameterUtils; |
||||
import org.apache.dolphinscheduler.dao.entity.Resource; |
||||
import org.apache.dolphinscheduler.server.entity.TaskExecutionContext; |
||||
import org.apache.dolphinscheduler.server.utils.ParamUtils; |
||||
import org.apache.dolphinscheduler.server.utils.SparkArgsUtils; |
||||
import org.apache.dolphinscheduler.server.worker.task.AbstractYarnTask; |
||||
|
||||
import java.util.ArrayList; |
||||
import java.util.List; |
||||
import java.util.Map; |
||||
|
||||
import org.slf4j.Logger; |
||||
|
||||
/** |
||||
* spark task |
||||
*/ |
||||
public class SparkTask extends AbstractYarnTask { |
||||
|
||||
/** |
||||
* spark1 command |
||||
* usage: spark-submit [options] <app jar | python file> [app arguments] |
||||
*/ |
||||
private static final String SPARK1_COMMAND = "${SPARK_HOME1}/bin/spark-submit"; |
||||
|
||||
/** |
||||
* spark2 command |
||||
* usage: spark-submit [options] <app jar | python file> [app arguments] |
||||
*/ |
||||
private static final String SPARK2_COMMAND = "${SPARK_HOME2}/bin/spark-submit"; |
||||
|
||||
/** |
||||
* spark parameters |
||||
*/ |
||||
private SparkParameters sparkParameters; |
||||
|
||||
/** |
||||
* taskExecutionContext |
||||
*/ |
||||
private TaskExecutionContext taskExecutionContext; |
||||
|
||||
public SparkTask(TaskExecutionContext taskExecutionContext, Logger logger) { |
||||
super(taskExecutionContext, logger); |
||||
this.taskExecutionContext = taskExecutionContext; |
||||
} |
||||
|
||||
@Override |
||||
public void init() { |
||||
|
||||
logger.info("spark task params {}", taskExecutionContext.getTaskParams()); |
||||
|
||||
sparkParameters = JSONUtils.parseObject(taskExecutionContext.getTaskParams(), SparkParameters.class); |
||||
|
||||
if (null == sparkParameters) { |
||||
logger.error("Spark params is null"); |
||||
return; |
||||
} |
||||
|
||||
if (!sparkParameters.checkParameters()) { |
||||
throw new RuntimeException("spark task params is not valid"); |
||||
} |
||||
sparkParameters.setQueue(taskExecutionContext.getQueue()); |
||||
setMainJarName(); |
||||
} |
||||
|
||||
/** |
||||
* create command |
||||
* @return command |
||||
*/ |
||||
@Override |
||||
protected String buildCommand() { |
||||
// spark-submit [options] <app jar | python file> [app arguments]
|
||||
List<String> args = new ArrayList<>(); |
||||
|
||||
// spark version
|
||||
String sparkCommand = SPARK2_COMMAND; |
||||
|
||||
if (SparkVersion.SPARK1.name().equals(sparkParameters.getSparkVersion())) { |
||||
sparkCommand = SPARK1_COMMAND; |
||||
} |
||||
|
||||
args.add(sparkCommand); |
||||
|
||||
// other parameters
|
||||
args.addAll(SparkArgsUtils.buildArgs(sparkParameters)); |
||||
|
||||
// replace placeholder, and combining local and global parameters
|
||||
Map<String, Property> paramsMap = ParamUtils.convert(taskExecutionContext,getParameters()); |
||||
|
||||
String command = null; |
||||
|
||||
if (null != paramsMap) { |
||||
command = ParameterUtils.convertParameterPlaceholders(String.join(" ", args), ParamUtils.convert(paramsMap)); |
||||
} |
||||
|
||||
logger.info("spark task command: {}", command); |
||||
|
||||
return command; |
||||
} |
||||
|
||||
@Override |
||||
protected void setMainJarName() { |
||||
// main jar
|
||||
ResourceInfo mainJar = sparkParameters.getMainJar(); |
||||
|
||||
if (null == mainJar) { |
||||
throw new RuntimeException("Spark task jar params is null"); |
||||
} |
||||
|
||||
int resourceId = mainJar.getId(); |
||||
String resourceName; |
||||
if (resourceId == 0) { |
||||
resourceName = mainJar.getRes(); |
||||
} else { |
||||
Resource resource = processService.getResourceById(sparkParameters.getMainJar().getId()); |
||||
if (resource == null) { |
||||
logger.error("resource id: {} not exist", resourceId); |
||||
throw new RuntimeException(String.format("resource id: %d not exist", resourceId)); |
||||
} |
||||
resourceName = resource.getFullName().replaceFirst("/", ""); |
||||
} |
||||
mainJar.setRes(resourceName); |
||||
sparkParameters.setMainJar(mainJar); |
||||
|
||||
} |
||||
|
||||
@Override |
||||
public AbstractParameters getParameters() { |
||||
return sparkParameters; |
||||
} |
||||
} |
@ -1,510 +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.server.worker.task.sql; |
||||
|
||||
import org.apache.dolphinscheduler.common.Constants; |
||||
import org.apache.dolphinscheduler.common.datasource.BaseConnectionParam; |
||||
import org.apache.dolphinscheduler.common.datasource.DatasourceUtil; |
||||
import org.apache.dolphinscheduler.common.enums.DbType; |
||||
import org.apache.dolphinscheduler.common.enums.Direct; |
||||
import org.apache.dolphinscheduler.common.enums.TaskTimeoutStrategy; |
||||
import org.apache.dolphinscheduler.common.process.Property; |
||||
import org.apache.dolphinscheduler.common.task.AbstractParameters; |
||||
import org.apache.dolphinscheduler.common.task.sql.SqlBinds; |
||||
import org.apache.dolphinscheduler.common.task.sql.SqlParameters; |
||||
import org.apache.dolphinscheduler.common.task.sql.SqlType; |
||||
import org.apache.dolphinscheduler.common.utils.CollectionUtils; |
||||
import org.apache.dolphinscheduler.common.utils.JSONUtils; |
||||
import org.apache.dolphinscheduler.common.utils.ParameterUtils; |
||||
import org.apache.dolphinscheduler.common.utils.StringUtils; |
||||
import org.apache.dolphinscheduler.dao.AlertDao; |
||||
import org.apache.dolphinscheduler.remote.command.alert.AlertSendResponseCommand; |
||||
import org.apache.dolphinscheduler.server.entity.SQLTaskExecutionContext; |
||||
import org.apache.dolphinscheduler.server.entity.TaskExecutionContext; |
||||
import org.apache.dolphinscheduler.server.utils.ParamUtils; |
||||
import org.apache.dolphinscheduler.server.utils.UDFUtils; |
||||
import org.apache.dolphinscheduler.server.worker.task.AbstractTask; |
||||
import org.apache.dolphinscheduler.service.alert.AlertClientService; |
||||
import org.apache.dolphinscheduler.service.bean.SpringApplicationContext; |
||||
|
||||
import org.apache.commons.collections.MapUtils; |
||||
|
||||
import java.sql.Connection; |
||||
import java.sql.PreparedStatement; |
||||
import java.sql.ResultSet; |
||||
import java.sql.ResultSetMetaData; |
||||
import java.sql.SQLException; |
||||
import java.sql.Statement; |
||||
import java.util.ArrayList; |
||||
import java.util.HashMap; |
||||
import java.util.List; |
||||
import java.util.Map; |
||||
import java.util.Optional; |
||||
import java.util.regex.Matcher; |
||||
import java.util.regex.Pattern; |
||||
import java.util.stream.Collectors; |
||||
|
||||
import org.slf4j.Logger; |
||||
|
||||
import com.fasterxml.jackson.databind.node.ArrayNode; |
||||
import com.fasterxml.jackson.databind.node.ObjectNode; |
||||
|
||||
/** |
||||
* sql task |
||||
*/ |
||||
public class SqlTask extends AbstractTask { |
||||
|
||||
/** |
||||
* sql parameters |
||||
*/ |
||||
private SqlParameters sqlParameters; |
||||
/** |
||||
* alert dao |
||||
*/ |
||||
private AlertDao alertDao; |
||||
/** |
||||
* base datasource |
||||
*/ |
||||
private BaseConnectionParam baseConnectionParam; |
||||
|
||||
/** |
||||
* taskExecutionContext |
||||
*/ |
||||
private TaskExecutionContext taskExecutionContext; |
||||
|
||||
private AlertClientService alertClientService; |
||||
|
||||
public SqlTask(TaskExecutionContext taskExecutionContext, Logger logger, AlertClientService alertClientService) { |
||||
super(taskExecutionContext, logger); |
||||
|
||||
this.taskExecutionContext = taskExecutionContext; |
||||
|
||||
logger.info("sql task params {}", taskExecutionContext.getTaskParams()); |
||||
this.sqlParameters = JSONUtils.parseObject(taskExecutionContext.getTaskParams(), SqlParameters.class); |
||||
|
||||
if (!sqlParameters.checkParameters()) { |
||||
throw new RuntimeException("sql task params is not valid"); |
||||
} |
||||
|
||||
this.alertClientService = alertClientService; |
||||
this.alertDao = SpringApplicationContext.getBean(AlertDao.class); |
||||
} |
||||
|
||||
@Override |
||||
public void handle() throws Exception { |
||||
// set the name of the current thread
|
||||
String threadLoggerInfoName = String.format(Constants.TASK_LOG_INFO_FORMAT, taskExecutionContext.getTaskAppId()); |
||||
Thread.currentThread().setName(threadLoggerInfoName); |
||||
|
||||
logger.info("Full sql parameters: {}", sqlParameters); |
||||
logger.info("sql type : {}, datasource : {}, sql : {} , localParams : {},udfs : {},showType : {},connParams : {},varPool : {} ,query max result limit {}", |
||||
sqlParameters.getType(), |
||||
sqlParameters.getDatasource(), |
||||
sqlParameters.getSql(), |
||||
sqlParameters.getLocalParams(), |
||||
sqlParameters.getUdfs(), |
||||
sqlParameters.getShowType(), |
||||
sqlParameters.getConnParams(), |
||||
sqlParameters.getVarPool(), |
||||
sqlParameters.getLimit()); |
||||
try { |
||||
SQLTaskExecutionContext sqlTaskExecutionContext = taskExecutionContext.getSqlTaskExecutionContext(); |
||||
|
||||
// get datasource
|
||||
baseConnectionParam = (BaseConnectionParam) DatasourceUtil.buildConnectionParams( |
||||
DbType.valueOf(sqlParameters.getType()), |
||||
sqlTaskExecutionContext.getConnectionParams()); |
||||
|
||||
// ready to execute SQL and parameter entity Map
|
||||
SqlBinds mainSqlBinds = getSqlAndSqlParamsMap(sqlParameters.getSql()); |
||||
List<SqlBinds> preStatementSqlBinds = Optional.ofNullable(sqlParameters.getPreStatements()) |
||||
.orElse(new ArrayList<>()) |
||||
.stream() |
||||
.map(this::getSqlAndSqlParamsMap) |
||||
.collect(Collectors.toList()); |
||||
List<SqlBinds> postStatementSqlBinds = Optional.ofNullable(sqlParameters.getPostStatements()) |
||||
.orElse(new ArrayList<>()) |
||||
.stream() |
||||
.map(this::getSqlAndSqlParamsMap) |
||||
.collect(Collectors.toList()); |
||||
|
||||
List<String> createFuncs = UDFUtils.createFuncs(sqlTaskExecutionContext.getUdfFuncTenantCodeMap(), |
||||
logger); |
||||
|
||||
// execute sql task
|
||||
executeFuncAndSql(mainSqlBinds, preStatementSqlBinds, postStatementSqlBinds, createFuncs); |
||||
|
||||
setExitStatusCode(Constants.EXIT_CODE_SUCCESS); |
||||
|
||||
} catch (Exception e) { |
||||
setExitStatusCode(Constants.EXIT_CODE_FAILURE); |
||||
logger.error("sql task error: {}", e.toString()); |
||||
throw e; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* ready to execute SQL and parameter entity Map |
||||
* |
||||
* @return SqlBinds |
||||
*/ |
||||
private SqlBinds getSqlAndSqlParamsMap(String sql) { |
||||
Map<Integer, Property> sqlParamsMap = new HashMap<>(); |
||||
StringBuilder sqlBuilder = new StringBuilder(); |
||||
|
||||
// combining local and global parameters
|
||||
Map<String, Property> paramsMap = ParamUtils.convert(taskExecutionContext,getParameters()); |
||||
|
||||
// spell SQL according to the final user-defined variable
|
||||
if (paramsMap == null) { |
||||
sqlBuilder.append(sql); |
||||
return new SqlBinds(sqlBuilder.toString(), sqlParamsMap); |
||||
} |
||||
|
||||
if (StringUtils.isNotEmpty(sqlParameters.getTitle())) { |
||||
String title = ParameterUtils.convertParameterPlaceholders(sqlParameters.getTitle(), |
||||
ParamUtils.convert(paramsMap)); |
||||
logger.info("SQL title : {}", title); |
||||
sqlParameters.setTitle(title); |
||||
} |
||||
|
||||
//new
|
||||
//replace variable TIME with $[YYYYmmddd...] in sql when history run job and batch complement job
|
||||
sql = ParameterUtils.replaceScheduleTime(sql, taskExecutionContext.getScheduleTime()); |
||||
// special characters need to be escaped, ${} needs to be escaped
|
||||
String rgex = "['\"]*\\$\\{(.*?)\\}['\"]*"; |
||||
setSqlParamsMap(sql, rgex, sqlParamsMap, paramsMap); |
||||
//Replace the original value in sql !{...} ,Does not participate in precompilation
|
||||
String rgexo = "['\"]*\\!\\{(.*?)\\}['\"]*"; |
||||
sql = replaceOriginalValue(sql, rgexo, paramsMap); |
||||
// replace the ${} of the SQL statement with the Placeholder
|
||||
String formatSql = sql.replaceAll(rgex, "?"); |
||||
sqlBuilder.append(formatSql); |
||||
|
||||
// print repalce sql
|
||||
printReplacedSql(sql, formatSql, rgex, sqlParamsMap); |
||||
return new SqlBinds(sqlBuilder.toString(), sqlParamsMap); |
||||
} |
||||
|
||||
public String replaceOriginalValue(String content, String rgex, Map<String, Property> sqlParamsMap) { |
||||
Pattern pattern = Pattern.compile(rgex); |
||||
while (true) { |
||||
Matcher m = pattern.matcher(content); |
||||
if (!m.find()) { |
||||
break; |
||||
} |
||||
String paramName = m.group(1); |
||||
String paramValue = sqlParamsMap.get(paramName).getValue(); |
||||
content = m.replaceFirst(paramValue); |
||||
} |
||||
return content; |
||||
} |
||||
|
||||
@Override |
||||
public AbstractParameters getParameters() { |
||||
return this.sqlParameters; |
||||
} |
||||
|
||||
/** |
||||
* execute function and sql |
||||
* |
||||
* @param mainSqlBinds main sql binds |
||||
* @param preStatementsBinds pre statements binds |
||||
* @param postStatementsBinds post statements binds |
||||
* @param createFuncs create functions |
||||
*/ |
||||
public void executeFuncAndSql(SqlBinds mainSqlBinds, |
||||
List<SqlBinds> preStatementsBinds, |
||||
List<SqlBinds> postStatementsBinds, |
||||
List<String> createFuncs) throws Exception { |
||||
Connection connection = null; |
||||
PreparedStatement stmt = null; |
||||
ResultSet resultSet = null; |
||||
try { |
||||
|
||||
// create connection
|
||||
connection = DatasourceUtil.getConnection(DbType.valueOf(sqlParameters.getType()), baseConnectionParam); |
||||
// create temp function
|
||||
if (CollectionUtils.isNotEmpty(createFuncs)) { |
||||
createTempFunction(connection, createFuncs); |
||||
} |
||||
|
||||
// pre sql
|
||||
preSql(connection, preStatementsBinds); |
||||
stmt = prepareStatementAndBind(connection, mainSqlBinds); |
||||
|
||||
String result = null; |
||||
// decide whether to executeQuery or executeUpdate based on sqlType
|
||||
if (sqlParameters.getSqlType() == SqlType.QUERY.ordinal()) { |
||||
// query statements need to be convert to JsonArray and inserted into Alert to send
|
||||
resultSet = stmt.executeQuery(); |
||||
result = resultProcess(resultSet); |
||||
|
||||
} else if (sqlParameters.getSqlType() == SqlType.NON_QUERY.ordinal()) { |
||||
// non query statement
|
||||
String updateResult = String.valueOf(stmt.executeUpdate()); |
||||
result = setNonQuerySqlReturn(updateResult, sqlParameters.getLocalParams()); |
||||
} |
||||
//deal out params
|
||||
sqlParameters.dealOutParam(result); |
||||
postSql(connection, postStatementsBinds); |
||||
} catch (Exception e) { |
||||
logger.error("execute sql error: {}", e.getMessage()); |
||||
throw e; |
||||
} finally { |
||||
close(resultSet, stmt, connection); |
||||
} |
||||
} |
||||
|
||||
public String setNonQuerySqlReturn(String updateResult, List<Property> properties) { |
||||
String result = null; |
||||
for (Property info : properties) { |
||||
if (Direct.OUT == info.getDirect()) { |
||||
List<Map<String, String>> updateRL = new ArrayList<>(); |
||||
Map<String, String> updateRM = new HashMap<>(); |
||||
updateRM.put(info.getProp(), updateResult); |
||||
updateRL.add(updateRM); |
||||
result = JSONUtils.toJsonString(updateRL); |
||||
break; |
||||
} |
||||
} |
||||
return result; |
||||
} |
||||
|
||||
/** |
||||
* result process |
||||
* |
||||
* @param resultSet resultSet |
||||
* @throws Exception Exception |
||||
*/ |
||||
private String resultProcess(ResultSet resultSet) throws Exception { |
||||
ArrayNode resultJSONArray = JSONUtils.createArrayNode(); |
||||
if (resultSet != null) { |
||||
ResultSetMetaData md = resultSet.getMetaData(); |
||||
int num = md.getColumnCount(); |
||||
|
||||
int rowCount = 0; |
||||
|
||||
while (rowCount < sqlParameters.getLimit() && resultSet.next()) { |
||||
ObjectNode mapOfColValues = JSONUtils.createObjectNode(); |
||||
for (int i = 1; i <= num; i++) { |
||||
mapOfColValues.set(md.getColumnLabel(i), JSONUtils.toJsonNode(resultSet.getObject(i))); |
||||
} |
||||
resultJSONArray.add(mapOfColValues); |
||||
rowCount++; |
||||
} |
||||
|
||||
int displayRows = sqlParameters.getDisplayRows() > 0 ? sqlParameters.getDisplayRows() : Constants.DEFAULT_DISPLAY_ROWS; |
||||
displayRows = Math.min(displayRows, resultJSONArray.size()); |
||||
logger.info("display sql result {} rows as follows:", displayRows); |
||||
for (int i = 0; i < displayRows; i++) { |
||||
String row = JSONUtils.toJsonString(resultJSONArray.get(i)); |
||||
logger.info("row {} : {}", i + 1, row); |
||||
} |
||||
} |
||||
String result = JSONUtils.toJsonString(resultJSONArray); |
||||
if (sqlParameters.getSendEmail() == null || sqlParameters.getSendEmail()) { |
||||
sendAttachment(sqlParameters.getGroupId(), StringUtils.isNotEmpty(sqlParameters.getTitle()) |
||||
? sqlParameters.getTitle() |
||||
: taskExecutionContext.getTaskName() + " query result sets", result); |
||||
} |
||||
logger.debug("execute sql result : {}", result); |
||||
return result; |
||||
} |
||||
|
||||
/** |
||||
* pre sql |
||||
* |
||||
* @param connection connection |
||||
* @param preStatementsBinds preStatementsBinds |
||||
*/ |
||||
private void preSql(Connection connection, |
||||
List<SqlBinds> preStatementsBinds) throws Exception { |
||||
for (SqlBinds sqlBind : preStatementsBinds) { |
||||
try (PreparedStatement pstmt = prepareStatementAndBind(connection, sqlBind)) { |
||||
int result = pstmt.executeUpdate(); |
||||
logger.info("pre statement execute result: {}, for sql: {}", result, sqlBind.getSql()); |
||||
|
||||
} |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* post sql |
||||
* |
||||
* @param connection connection |
||||
* @param postStatementsBinds postStatementsBinds |
||||
*/ |
||||
private void postSql(Connection connection, |
||||
List<SqlBinds> postStatementsBinds) throws Exception { |
||||
for (SqlBinds sqlBind : postStatementsBinds) { |
||||
try (PreparedStatement pstmt = prepareStatementAndBind(connection, sqlBind)) { |
||||
int result = pstmt.executeUpdate(); |
||||
logger.info("post statement execute result: {},for sql: {}", result, sqlBind.getSql()); |
||||
} |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* create temp function |
||||
* |
||||
* @param connection connection |
||||
* @param createFuncs createFuncs |
||||
*/ |
||||
private void createTempFunction(Connection connection, |
||||
List<String> createFuncs) throws Exception { |
||||
try (Statement funcStmt = connection.createStatement()) { |
||||
for (String createFunc : createFuncs) { |
||||
logger.info("hive create function sql: {}", createFunc); |
||||
funcStmt.execute(createFunc); |
||||
} |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* close jdbc resource |
||||
* |
||||
* @param resultSet resultSet |
||||
* @param pstmt pstmt |
||||
* @param connection connection |
||||
*/ |
||||
private void close(ResultSet resultSet, |
||||
PreparedStatement pstmt, |
||||
Connection connection) { |
||||
if (resultSet != null) { |
||||
try { |
||||
resultSet.close(); |
||||
} catch (SQLException e) { |
||||
logger.error("close result set error : {}", e.getMessage(), e); |
||||
} |
||||
} |
||||
|
||||
if (pstmt != null) { |
||||
try { |
||||
pstmt.close(); |
||||
} catch (SQLException e) { |
||||
logger.error("close prepared statement error : {}", e.getMessage(), e); |
||||
} |
||||
} |
||||
|
||||
if (connection != null) { |
||||
try { |
||||
connection.close(); |
||||
} catch (SQLException e) { |
||||
logger.error("close connection error : {}", e.getMessage(), e); |
||||
} |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* preparedStatement bind |
||||
* |
||||
* @param connection connection |
||||
* @param sqlBinds sqlBinds |
||||
* @return PreparedStatement |
||||
* @throws Exception Exception |
||||
*/ |
||||
private PreparedStatement prepareStatementAndBind(Connection connection, SqlBinds sqlBinds) throws Exception { |
||||
// is the timeout set
|
||||
boolean timeoutFlag = taskExecutionContext.getTaskTimeoutStrategy() == TaskTimeoutStrategy.FAILED |
||||
|| taskExecutionContext.getTaskTimeoutStrategy() == TaskTimeoutStrategy.WARNFAILED; |
||||
PreparedStatement stmt = connection.prepareStatement(sqlBinds.getSql()); |
||||
if (timeoutFlag) { |
||||
stmt.setQueryTimeout(taskExecutionContext.getTaskTimeout()); |
||||
} |
||||
Map<Integer, Property> params = sqlBinds.getParamsMap(); |
||||
if (params != null) { |
||||
for (Map.Entry<Integer, Property> entry : params.entrySet()) { |
||||
Property prop = entry.getValue(); |
||||
ParameterUtils.setInParameter(entry.getKey(), stmt, prop.getType(), prop.getValue()); |
||||
} |
||||
} |
||||
logger.info("prepare statement replace sql : {} ", stmt); |
||||
return stmt; |
||||
} |
||||
|
||||
/** |
||||
* send mail as an attachment |
||||
* |
||||
* @param title title |
||||
* @param content content |
||||
*/ |
||||
public void sendAttachment(int groupId, String title, String content) { |
||||
AlertSendResponseCommand alertSendResponseCommand = alertClientService.sendAlert(groupId, title, content); |
||||
if (!alertSendResponseCommand.getResStatus()) { |
||||
throw new RuntimeException("send mail failed!"); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* regular expressions match the contents between two specified strings |
||||
* |
||||
* @param content content |
||||
* @param rgex rgex |
||||
* @param sqlParamsMap sql params map |
||||
* @param paramsPropsMap params props map |
||||
*/ |
||||
public void setSqlParamsMap(String content, String rgex, Map<Integer, Property> sqlParamsMap, Map<String, Property> paramsPropsMap) { |
||||
Pattern pattern = Pattern.compile(rgex); |
||||
Matcher m = pattern.matcher(content); |
||||
int index = 1; |
||||
while (m.find()) { |
||||
|
||||
String paramName = m.group(1); |
||||
Property prop = paramsPropsMap.get(paramName); |
||||
|
||||
if (prop == null) { |
||||
logger.error("setSqlParamsMap: No Property with paramName: {} is found in paramsPropsMap of task instance" |
||||
+ " with id: {}. So couldn't put Property in sqlParamsMap.", paramName, taskExecutionContext.getTaskInstanceId()); |
||||
} |
||||
else { |
||||
sqlParamsMap.put(index, prop); |
||||
index++; |
||||
logger.info("setSqlParamsMap: Property with paramName: {} put in sqlParamsMap of content {} successfully.", paramName, content); |
||||
} |
||||
|
||||
} |
||||
} |
||||
|
||||
/** |
||||
* print replace sql |
||||
* |
||||
* @param content content |
||||
* @param formatSql format sql |
||||
* @param rgex rgex |
||||
* @param sqlParamsMap sql params map |
||||
*/ |
||||
public void printReplacedSql(String content, String formatSql, String rgex, Map<Integer, Property> sqlParamsMap) { |
||||
//parameter print style
|
||||
logger.info("after replace sql , preparing : {}", formatSql); |
||||
if (MapUtils.isEmpty(sqlParamsMap)) { |
||||
logger.info("sqlParamsMap should not be Empty"); |
||||
return; |
||||
} |
||||
StringBuilder logPrint = new StringBuilder("replaced sql , parameters:"); |
||||
if (sqlParamsMap == null) { |
||||
logger.info("printReplacedSql: sqlParamsMap is null."); |
||||
} |
||||
else { |
||||
for (int i = 1; i <= sqlParamsMap.size(); i++) { |
||||
logPrint.append(sqlParamsMap.get(i).getValue() + "(" + sqlParamsMap.get(i).getType() + ")"); |
||||
} |
||||
} |
||||
logger.info("Sql Params are {}", logPrint); |
||||
} |
||||
} |
@ -1,75 +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.server.worker.task.sqoop; |
||||
|
||||
public final class SqoopConstants { |
||||
|
||||
private SqoopConstants() { |
||||
} |
||||
|
||||
//sqoop general param
|
||||
public static final String SQOOP = "sqoop"; |
||||
public static final String SQOOP_MR_JOB_NAME = "mapred.job.name"; |
||||
public static final String SQOOP_PARALLELISM = "-m"; |
||||
public static final String FIELDS_TERMINATED_BY = "--fields-terminated-by"; |
||||
public static final String LINES_TERMINATED_BY = "--lines-terminated-by"; |
||||
public static final String FIELD_NULL_PLACEHOLDER = "--null-non-string 'NULL' --null-string 'NULL'"; |
||||
|
||||
//sqoop db
|
||||
public static final String DB_CONNECT = "--connect"; |
||||
public static final String DB_USERNAME = "--username"; |
||||
public static final String DB_PWD = "--password"; |
||||
public static final String TABLE = "--table"; |
||||
public static final String COLUMNS = "--columns"; |
||||
public static final String QUERY_WHERE = "where"; |
||||
public static final String QUERY = "--query"; |
||||
public static final String QUERY_CONDITION = "AND \\$CONDITIONS"; |
||||
public static final String QUERY_WITHOUT_CONDITION = "WHERE \\$CONDITIONS"; |
||||
public static final String MAP_COLUMN_HIVE = "--map-column-hive"; |
||||
public static final String MAP_COLUMN_JAVA = "--map-column-java"; |
||||
|
||||
|
||||
//sqoop hive source
|
||||
public static final String HCATALOG_DATABASE = "--hcatalog-database"; |
||||
public static final String HCATALOG_TABLE = "--hcatalog-table"; |
||||
public static final String HCATALOG_PARTITION_KEYS = "--hcatalog-partition-keys"; |
||||
public static final String HCATALOG_PARTITION_VALUES = "--hcatalog-partition-values"; |
||||
|
||||
//sqoop hdfs
|
||||
public static final String HDFS_EXPORT_DIR = "--export-dir"; |
||||
public static final String TARGET_DIR = "--target-dir"; |
||||
public static final String COMPRESSION_CODEC = "--compression-codec"; |
||||
|
||||
//sqoop hive
|
||||
public static final String HIVE_IMPORT = "--hive-import"; |
||||
public static final String HIVE_DATABASE = "--hive-database"; |
||||
public static final String HIVE_TABLE = "--hive-table"; |
||||
public static final String CREATE_HIVE_TABLE = "--create-hive-table"; |
||||
public static final String HIVE_DROP_IMPORT_DELIMS = "--hive-drop-import-delims"; |
||||
public static final String HIVE_OVERWRITE = "--hive-overwrite"; |
||||
public static final String DELETE_TARGET_DIR = "--delete-target-dir"; |
||||
public static final String HIVE_DELIMS_REPLACEMENT = "--hive-delims-replacement"; |
||||
public static final String HIVE_PARTITION_KEY = "--hive-partition-key"; |
||||
public static final String HIVE_PARTITION_VALUE = "--hive-partition-value"; |
||||
|
||||
//sqoop update model
|
||||
public static final String UPDATE_KEY = "--update-key"; |
||||
public static final String UPDATE_MODE = "--update-mode"; |
||||
|
||||
|
||||
} |
@ -1,95 +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.server.worker.task.sqoop; |
||||
|
||||
import org.apache.dolphinscheduler.common.process.Property; |
||||
import org.apache.dolphinscheduler.common.task.AbstractParameters; |
||||
import org.apache.dolphinscheduler.common.task.sqoop.SqoopParameters; |
||||
import org.apache.dolphinscheduler.common.utils.JSONUtils; |
||||
import org.apache.dolphinscheduler.common.utils.ParameterUtils; |
||||
import org.apache.dolphinscheduler.server.entity.TaskExecutionContext; |
||||
import org.apache.dolphinscheduler.server.utils.ParamUtils; |
||||
import org.apache.dolphinscheduler.server.worker.task.AbstractYarnTask; |
||||
import org.apache.dolphinscheduler.server.worker.task.sqoop.generator.SqoopJobGenerator; |
||||
|
||||
import java.util.Map; |
||||
|
||||
import org.slf4j.Logger; |
||||
|
||||
/** |
||||
* sqoop task extends the shell task |
||||
*/ |
||||
public class SqoopTask extends AbstractYarnTask { |
||||
|
||||
/** |
||||
* sqoop task params |
||||
*/ |
||||
private SqoopParameters sqoopParameters; |
||||
|
||||
/** |
||||
* taskExecutionContext |
||||
*/ |
||||
private final TaskExecutionContext sqoopTaskExecutionContext; |
||||
|
||||
public SqoopTask(TaskExecutionContext taskExecutionContext, Logger logger) { |
||||
super(taskExecutionContext, logger); |
||||
this.sqoopTaskExecutionContext = taskExecutionContext; |
||||
} |
||||
|
||||
@Override |
||||
public void init() { |
||||
logger.info("sqoop task params {}", sqoopTaskExecutionContext.getTaskParams()); |
||||
sqoopParameters = |
||||
JSONUtils.parseObject(sqoopTaskExecutionContext.getTaskParams(), SqoopParameters.class); |
||||
//check sqoop task params
|
||||
if (null == sqoopParameters) { |
||||
throw new IllegalArgumentException("Sqoop Task params is null"); |
||||
} |
||||
|
||||
if (!sqoopParameters.checkParameters()) { |
||||
throw new IllegalArgumentException("Sqoop Task params check fail"); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
protected String buildCommand() { |
||||
//get sqoop scripts
|
||||
SqoopJobGenerator generator = new SqoopJobGenerator(); |
||||
String script = generator.generateSqoopJob(sqoopParameters, sqoopTaskExecutionContext); |
||||
|
||||
// combining local and global parameters
|
||||
Map<String, Property> paramsMap = ParamUtils.convert(sqoopTaskExecutionContext,getParameters()); |
||||
|
||||
if (paramsMap != null) { |
||||
String resultScripts = ParameterUtils.convertParameterPlaceholders(script, ParamUtils.convert(paramsMap)); |
||||
logger.info("sqoop script: {}", resultScripts); |
||||
return resultScripts; |
||||
} |
||||
|
||||
return null; |
||||
} |
||||
|
||||
@Override |
||||
protected void setMainJarName() { |
||||
} |
||||
|
||||
@Override |
||||
public AbstractParameters getParameters() { |
||||
return sqoopParameters; |
||||
} |
||||
} |
@ -1,85 +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.server.worker.task.sqoop.generator; |
||||
|
||||
import org.apache.dolphinscheduler.common.Constants; |
||||
import org.apache.dolphinscheduler.common.process.Property; |
||||
import org.apache.dolphinscheduler.common.task.sqoop.SqoopParameters; |
||||
import org.apache.dolphinscheduler.common.utils.CollectionUtils; |
||||
import org.apache.dolphinscheduler.server.worker.task.sqoop.SqoopConstants; |
||||
|
||||
import java.util.List; |
||||
|
||||
import org.slf4j.Logger; |
||||
import org.slf4j.LoggerFactory; |
||||
|
||||
/** |
||||
* common script generator |
||||
*/ |
||||
public class CommonGenerator { |
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(CommonGenerator.class); |
||||
|
||||
public String generate(SqoopParameters sqoopParameters) { |
||||
|
||||
StringBuilder commonSb = new StringBuilder(); |
||||
|
||||
try { |
||||
//sqoop task model
|
||||
commonSb.append(SqoopConstants.SQOOP) |
||||
.append(Constants.SPACE) |
||||
.append(sqoopParameters.getModelType()); |
||||
|
||||
//sqoop map-reduce job name
|
||||
commonSb.append(Constants.SPACE).append(Constants.D).append(Constants.SPACE) |
||||
.append(String.format("%s%s%s", SqoopConstants.SQOOP_MR_JOB_NAME, |
||||
Constants.EQUAL_SIGN, sqoopParameters.getJobName())); |
||||
|
||||
//hadoop custom param
|
||||
List<Property> hadoopCustomParams = sqoopParameters.getHadoopCustomParams(); |
||||
if (CollectionUtils.isNotEmpty(hadoopCustomParams)) { |
||||
for (Property hadoopCustomParam : hadoopCustomParams) { |
||||
String hadoopCustomParamStr = String.format("%s%s%s", hadoopCustomParam.getProp(), |
||||
Constants.EQUAL_SIGN, hadoopCustomParam.getValue()); |
||||
|
||||
commonSb.append(Constants.SPACE).append(Constants.D) |
||||
.append(Constants.SPACE).append(hadoopCustomParamStr); |
||||
} |
||||
} |
||||
|
||||
//sqoop custom params
|
||||
List<Property> sqoopAdvancedParams = sqoopParameters.getSqoopAdvancedParams(); |
||||
if (CollectionUtils.isNotEmpty(sqoopAdvancedParams)) { |
||||
for (Property sqoopAdvancedParam : sqoopAdvancedParams) { |
||||
commonSb.append(Constants.SPACE).append(sqoopAdvancedParam.getProp()) |
||||
.append(Constants.SPACE).append(sqoopAdvancedParam.getValue()); |
||||
} |
||||
} |
||||
|
||||
//sqoop parallelism
|
||||
if (sqoopParameters.getConcurrency() > 0) { |
||||
commonSb.append(Constants.SPACE).append(SqoopConstants.SQOOP_PARALLELISM) |
||||
.append(Constants.SPACE).append(sqoopParameters.getConcurrency()); |
||||
} |
||||
} catch (Exception e) { |
||||
logger.error(String.format("Sqoop task general param build failed: [%s]", e.getMessage())); |
||||
} |
||||
|
||||
return commonSb.toString(); |
||||
} |
||||
} |
@ -1,124 +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.server.worker.task.sqoop.generator; |
||||
|
||||
import org.apache.dolphinscheduler.common.enums.SqoopJobType; |
||||
import org.apache.dolphinscheduler.common.task.sqoop.SqoopParameters; |
||||
import org.apache.dolphinscheduler.server.entity.TaskExecutionContext; |
||||
import org.apache.dolphinscheduler.server.worker.task.sqoop.generator.sources.HdfsSourceGenerator; |
||||
import org.apache.dolphinscheduler.server.worker.task.sqoop.generator.sources.HiveSourceGenerator; |
||||
import org.apache.dolphinscheduler.server.worker.task.sqoop.generator.sources.MysqlSourceGenerator; |
||||
import org.apache.dolphinscheduler.server.worker.task.sqoop.generator.targets.HdfsTargetGenerator; |
||||
import org.apache.dolphinscheduler.server.worker.task.sqoop.generator.targets.HiveTargetGenerator; |
||||
import org.apache.dolphinscheduler.server.worker.task.sqoop.generator.targets.MysqlTargetGenerator; |
||||
|
||||
/** |
||||
* Sqoop Job Scripts Generator |
||||
*/ |
||||
public class SqoopJobGenerator { |
||||
|
||||
private static final String MYSQL = "MYSQL"; |
||||
private static final String HIVE = "HIVE"; |
||||
private static final String HDFS = "HDFS"; |
||||
|
||||
/** |
||||
* target script generator |
||||
*/ |
||||
private ITargetGenerator targetGenerator; |
||||
/** |
||||
* source script generator |
||||
*/ |
||||
private ISourceGenerator sourceGenerator; |
||||
/** |
||||
* common script generator |
||||
*/ |
||||
private final CommonGenerator commonGenerator; |
||||
|
||||
public SqoopJobGenerator() { |
||||
commonGenerator = new CommonGenerator(); |
||||
} |
||||
|
||||
private void createSqoopJobGenerator(String sourceType, String targetType) { |
||||
sourceGenerator = createSourceGenerator(sourceType); |
||||
targetGenerator = createTargetGenerator(targetType); |
||||
} |
||||
|
||||
/** |
||||
* get the final sqoop scripts |
||||
* |
||||
* @param sqoopParameters sqoop params |
||||
* @return sqoop scripts |
||||
*/ |
||||
public String generateSqoopJob(SqoopParameters sqoopParameters, TaskExecutionContext taskExecutionContext) { |
||||
|
||||
String sqoopScripts = ""; |
||||
|
||||
if (SqoopJobType.TEMPLATE.getDescp().equals(sqoopParameters.getJobType())) { |
||||
createSqoopJobGenerator(sqoopParameters.getSourceType(), sqoopParameters.getTargetType()); |
||||
if (sourceGenerator == null || targetGenerator == null) { |
||||
throw new RuntimeException("sqoop task source type or target type is null"); |
||||
} |
||||
|
||||
sqoopScripts = String.format("%s%s%s", commonGenerator.generate(sqoopParameters), |
||||
sourceGenerator.generate(sqoopParameters, taskExecutionContext), |
||||
targetGenerator.generate(sqoopParameters, taskExecutionContext)); |
||||
} else if (SqoopJobType.CUSTOM.getDescp().equals(sqoopParameters.getJobType())) { |
||||
sqoopScripts = sqoopParameters.getCustomShell().replaceAll("\\r\\n", "\n"); |
||||
} |
||||
|
||||
return sqoopScripts; |
||||
} |
||||
|
||||
/** |
||||
* get the source generator |
||||
* |
||||
* @param sourceType sqoop source type |
||||
* @return sqoop source generator |
||||
*/ |
||||
private ISourceGenerator createSourceGenerator(String sourceType) { |
||||
switch (sourceType) { |
||||
case MYSQL: |
||||
return new MysqlSourceGenerator(); |
||||
case HIVE: |
||||
return new HiveSourceGenerator(); |
||||
case HDFS: |
||||
return new HdfsSourceGenerator(); |
||||
default: |
||||
return null; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* get the target generator |
||||
* |
||||
* @param targetType sqoop target type |
||||
* @return sqoop target generator |
||||
*/ |
||||
private ITargetGenerator createTargetGenerator(String targetType) { |
||||
switch (targetType) { |
||||
case MYSQL: |
||||
return new MysqlTargetGenerator(); |
||||
case HIVE: |
||||
return new HiveTargetGenerator(); |
||||
case HDFS: |
||||
return new HdfsTargetGenerator(); |
||||
default: |
||||
return null; |
||||
} |
||||
} |
||||
} |
@ -1,63 +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.server.worker.task.sqoop.generator.sources; |
||||
|
||||
import org.apache.dolphinscheduler.common.Constants; |
||||
import org.apache.dolphinscheduler.common.task.sqoop.SqoopParameters; |
||||
import org.apache.dolphinscheduler.common.task.sqoop.sources.SourceHdfsParameter; |
||||
import org.apache.dolphinscheduler.common.utils.JSONUtils; |
||||
import org.apache.dolphinscheduler.common.utils.StringUtils; |
||||
import org.apache.dolphinscheduler.server.entity.TaskExecutionContext; |
||||
import org.apache.dolphinscheduler.server.worker.task.sqoop.SqoopConstants; |
||||
import org.apache.dolphinscheduler.server.worker.task.sqoop.generator.ISourceGenerator; |
||||
|
||||
import org.slf4j.Logger; |
||||
import org.slf4j.LoggerFactory; |
||||
|
||||
/** |
||||
* hdfs source generator |
||||
*/ |
||||
public class HdfsSourceGenerator implements ISourceGenerator { |
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(HdfsSourceGenerator.class); |
||||
|
||||
@Override |
||||
public String generate(SqoopParameters sqoopParameters, TaskExecutionContext taskExecutionContext) { |
||||
|
||||
StringBuilder hdfsSourceSb = new StringBuilder(); |
||||
|
||||
try { |
||||
SourceHdfsParameter sourceHdfsParameter |
||||
= JSONUtils.parseObject(sqoopParameters.getSourceParams(), SourceHdfsParameter.class); |
||||
|
||||
if (null != sourceHdfsParameter) { |
||||
if (StringUtils.isNotEmpty(sourceHdfsParameter.getExportDir())) { |
||||
hdfsSourceSb.append(Constants.SPACE).append(SqoopConstants.HDFS_EXPORT_DIR) |
||||
.append(Constants.SPACE).append(sourceHdfsParameter.getExportDir()); |
||||
} else { |
||||
throw new IllegalArgumentException("Sqoop hdfs export dir is null"); |
||||
} |
||||
|
||||
} |
||||
} catch (Exception e) { |
||||
logger.error(String.format("Sqoop hdfs source parmas build failed: [%s]", e.getMessage())); |
||||
} |
||||
|
||||
return hdfsSourceSb.toString(); |
||||
} |
||||
} |
@ -1,73 +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.server.worker.task.sqoop.generator.sources; |
||||
|
||||
import org.apache.dolphinscheduler.common.Constants; |
||||
import org.apache.dolphinscheduler.common.task.sqoop.SqoopParameters; |
||||
import org.apache.dolphinscheduler.common.task.sqoop.sources.SourceHiveParameter; |
||||
import org.apache.dolphinscheduler.common.utils.JSONUtils; |
||||
import org.apache.dolphinscheduler.common.utils.StringUtils; |
||||
import org.apache.dolphinscheduler.server.entity.TaskExecutionContext; |
||||
import org.apache.dolphinscheduler.server.worker.task.sqoop.SqoopConstants; |
||||
import org.apache.dolphinscheduler.server.worker.task.sqoop.generator.ISourceGenerator; |
||||
|
||||
import org.slf4j.Logger; |
||||
import org.slf4j.LoggerFactory; |
||||
|
||||
/** |
||||
* hive source generator |
||||
*/ |
||||
public class HiveSourceGenerator implements ISourceGenerator { |
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(HiveSourceGenerator.class); |
||||
|
||||
@Override |
||||
public String generate(SqoopParameters sqoopParameters, TaskExecutionContext taskExecutionContext) { |
||||
|
||||
StringBuilder hiveSourceSb = new StringBuilder(); |
||||
|
||||
try { |
||||
SourceHiveParameter sourceHiveParameter |
||||
= JSONUtils.parseObject(sqoopParameters.getSourceParams(), SourceHiveParameter.class); |
||||
|
||||
if (null != sourceHiveParameter) { |
||||
if (StringUtils.isNotEmpty(sourceHiveParameter.getHiveDatabase())) { |
||||
hiveSourceSb.append(Constants.SPACE).append(SqoopConstants.HCATALOG_DATABASE) |
||||
.append(Constants.SPACE).append(sourceHiveParameter.getHiveDatabase()); |
||||
} |
||||
|
||||
if (StringUtils.isNotEmpty(sourceHiveParameter.getHiveTable())) { |
||||
hiveSourceSb.append(Constants.SPACE).append(SqoopConstants.HCATALOG_TABLE) |
||||
.append(Constants.SPACE).append(sourceHiveParameter.getHiveTable()); |
||||
} |
||||
|
||||
if (StringUtils.isNotEmpty(sourceHiveParameter.getHivePartitionKey()) |
||||
&& StringUtils.isNotEmpty(sourceHiveParameter.getHivePartitionValue())) { |
||||
hiveSourceSb.append(Constants.SPACE).append(SqoopConstants.HCATALOG_PARTITION_KEYS) |
||||
.append(Constants.SPACE).append(sourceHiveParameter.getHivePartitionKey()) |
||||
.append(Constants.SPACE).append(SqoopConstants.HCATALOG_PARTITION_VALUES) |
||||
.append(Constants.SPACE).append(sourceHiveParameter.getHivePartitionValue()); |
||||
} |
||||
} |
||||
} catch (Exception e) { |
||||
logger.error(String.format("Sqoop hive source params build failed: [%s]", e.getMessage())); |
||||
} |
||||
|
||||
return hiveSourceSb.toString(); |
||||
} |
||||
} |
@ -1,135 +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.server.worker.task.sqoop.generator.sources; |
||||
|
||||
import org.apache.dolphinscheduler.common.Constants; |
||||
import org.apache.dolphinscheduler.common.datasource.BaseConnectionParam; |
||||
import org.apache.dolphinscheduler.common.datasource.DatasourceUtil; |
||||
import org.apache.dolphinscheduler.common.enums.DbType; |
||||
import org.apache.dolphinscheduler.common.enums.SqoopQueryType; |
||||
import org.apache.dolphinscheduler.common.process.Property; |
||||
import org.apache.dolphinscheduler.common.task.sqoop.SqoopParameters; |
||||
import org.apache.dolphinscheduler.common.task.sqoop.sources.SourceMysqlParameter; |
||||
import org.apache.dolphinscheduler.common.utils.CommonUtils; |
||||
import org.apache.dolphinscheduler.common.utils.JSONUtils; |
||||
import org.apache.dolphinscheduler.common.utils.StringUtils; |
||||
import org.apache.dolphinscheduler.server.entity.SqoopTaskExecutionContext; |
||||
import org.apache.dolphinscheduler.server.entity.TaskExecutionContext; |
||||
import org.apache.dolphinscheduler.server.worker.task.sqoop.SqoopConstants; |
||||
import org.apache.dolphinscheduler.server.worker.task.sqoop.generator.ISourceGenerator; |
||||
|
||||
import java.util.List; |
||||
|
||||
import org.slf4j.Logger; |
||||
import org.slf4j.LoggerFactory; |
||||
|
||||
/** |
||||
* mysql source generator |
||||
*/ |
||||
public class MysqlSourceGenerator implements ISourceGenerator { |
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(MysqlSourceGenerator.class); |
||||
|
||||
@Override |
||||
public String generate(SqoopParameters sqoopParameters, TaskExecutionContext taskExecutionContext) { |
||||
|
||||
StringBuilder mysqlSourceSb = new StringBuilder(); |
||||
|
||||
try { |
||||
SourceMysqlParameter sourceMysqlParameter = JSONUtils.parseObject(sqoopParameters.getSourceParams(), SourceMysqlParameter.class); |
||||
SqoopTaskExecutionContext sqoopTaskExecutionContext = taskExecutionContext.getSqoopTaskExecutionContext(); |
||||
|
||||
if (null != sourceMysqlParameter) { |
||||
BaseConnectionParam baseDataSource = (BaseConnectionParam) DatasourceUtil.buildConnectionParams( |
||||
DbType.of(sqoopTaskExecutionContext.getSourcetype()), |
||||
sqoopTaskExecutionContext.getSourceConnectionParams()); |
||||
|
||||
if (null != baseDataSource) { |
||||
|
||||
mysqlSourceSb.append(Constants.SPACE).append(SqoopConstants.DB_CONNECT) |
||||
.append(Constants.SPACE).append(Constants.DOUBLE_QUOTES) |
||||
.append(DatasourceUtil.getJdbcUrl(DbType.MYSQL, baseDataSource)).append(Constants.DOUBLE_QUOTES) |
||||
.append(Constants.SPACE).append(SqoopConstants.DB_USERNAME) |
||||
.append(Constants.SPACE).append(baseDataSource.getUser()) |
||||
.append(Constants.SPACE).append(SqoopConstants.DB_PWD) |
||||
.append(Constants.SPACE).append(Constants.DOUBLE_QUOTES) |
||||
.append(CommonUtils.decodePassword(baseDataSource.getPassword())).append(Constants.DOUBLE_QUOTES); |
||||
|
||||
//sqoop table & sql query
|
||||
if (sourceMysqlParameter.getSrcQueryType() == SqoopQueryType.FORM.getCode()) { |
||||
if (StringUtils.isNotEmpty(sourceMysqlParameter.getSrcTable())) { |
||||
mysqlSourceSb.append(Constants.SPACE).append(SqoopConstants.TABLE) |
||||
.append(Constants.SPACE).append(sourceMysqlParameter.getSrcTable()); |
||||
} |
||||
|
||||
if (StringUtils.isNotEmpty(sourceMysqlParameter.getSrcColumns())) { |
||||
mysqlSourceSb.append(Constants.SPACE).append(SqoopConstants.COLUMNS) |
||||
.append(Constants.SPACE).append(sourceMysqlParameter.getSrcColumns()); |
||||
} |
||||
} else if (sourceMysqlParameter.getSrcQueryType() == SqoopQueryType.SQL.getCode() |
||||
&& StringUtils.isNotEmpty(sourceMysqlParameter.getSrcQuerySql())) { |
||||
|
||||
String srcQuery = sourceMysqlParameter.getSrcQuerySql(); |
||||
mysqlSourceSb.append(Constants.SPACE).append(SqoopConstants.QUERY) |
||||
.append(Constants.SPACE).append(Constants.DOUBLE_QUOTES).append(srcQuery); |
||||
|
||||
if (srcQuery.toLowerCase().contains(SqoopConstants.QUERY_WHERE)) { |
||||
mysqlSourceSb.append(Constants.SPACE).append(SqoopConstants.QUERY_CONDITION).append(Constants.DOUBLE_QUOTES); |
||||
} else { |
||||
mysqlSourceSb.append(Constants.SPACE).append(SqoopConstants.QUERY_WITHOUT_CONDITION).append(Constants.DOUBLE_QUOTES); |
||||
} |
||||
} |
||||
|
||||
//sqoop hive map column
|
||||
List<Property> mapColumnHive = sourceMysqlParameter.getMapColumnHive(); |
||||
|
||||
if (null != mapColumnHive && !mapColumnHive.isEmpty()) { |
||||
StringBuilder columnMap = new StringBuilder(); |
||||
for (Property item : mapColumnHive) { |
||||
columnMap.append(item.getProp()).append(Constants.EQUAL_SIGN).append(item.getValue()).append(Constants.COMMA); |
||||
} |
||||
|
||||
if (StringUtils.isNotEmpty(columnMap.toString())) { |
||||
mysqlSourceSb.append(Constants.SPACE).append(SqoopConstants.MAP_COLUMN_HIVE) |
||||
.append(Constants.SPACE).append(columnMap.substring(0, columnMap.length() - 1)); |
||||
} |
||||
} |
||||
|
||||
//sqoop map column java
|
||||
List<Property> mapColumnJava = sourceMysqlParameter.getMapColumnJava(); |
||||
|
||||
if (null != mapColumnJava && !mapColumnJava.isEmpty()) { |
||||
StringBuilder columnMap = new StringBuilder(); |
||||
for (Property item : mapColumnJava) { |
||||
columnMap.append(item.getProp()).append(Constants.EQUAL_SIGN).append(item.getValue()).append(Constants.COMMA); |
||||
} |
||||
|
||||
if (StringUtils.isNotEmpty(columnMap.toString())) { |
||||
mysqlSourceSb.append(Constants.SPACE).append(SqoopConstants.MAP_COLUMN_JAVA) |
||||
.append(Constants.SPACE).append(columnMap.substring(0, columnMap.length() - 1)); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} catch (Exception e) { |
||||
logger.error(String.format("Sqoop task mysql source params build failed: [%s]", e.getMessage())); |
||||
} |
||||
|
||||
return mysqlSourceSb.toString(); |
||||
} |
||||
} |
@ -1,86 +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.server.worker.task.sqoop.generator.targets; |
||||
|
||||
import org.apache.dolphinscheduler.common.Constants; |
||||
import org.apache.dolphinscheduler.common.task.sqoop.SqoopParameters; |
||||
import org.apache.dolphinscheduler.common.task.sqoop.targets.TargetHdfsParameter; |
||||
import org.apache.dolphinscheduler.common.utils.JSONUtils; |
||||
import org.apache.dolphinscheduler.common.utils.StringUtils; |
||||
import org.apache.dolphinscheduler.server.entity.TaskExecutionContext; |
||||
import org.apache.dolphinscheduler.server.worker.task.sqoop.SqoopConstants; |
||||
import org.apache.dolphinscheduler.server.worker.task.sqoop.generator.ITargetGenerator; |
||||
|
||||
import org.slf4j.Logger; |
||||
import org.slf4j.LoggerFactory; |
||||
|
||||
/** |
||||
* hdfs target generator |
||||
*/ |
||||
public class HdfsTargetGenerator implements ITargetGenerator { |
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(HdfsTargetGenerator.class); |
||||
|
||||
@Override |
||||
public String generate(SqoopParameters sqoopParameters, TaskExecutionContext taskExecutionContext) { |
||||
|
||||
StringBuilder hdfsTargetSb = new StringBuilder(); |
||||
|
||||
try { |
||||
TargetHdfsParameter targetHdfsParameter = |
||||
JSONUtils.parseObject(sqoopParameters.getTargetParams(), TargetHdfsParameter.class); |
||||
|
||||
if (null != targetHdfsParameter) { |
||||
|
||||
if (StringUtils.isNotEmpty(targetHdfsParameter.getTargetPath())) { |
||||
hdfsTargetSb.append(Constants.SPACE).append(SqoopConstants.TARGET_DIR) |
||||
.append(Constants.SPACE).append(targetHdfsParameter.getTargetPath()); |
||||
} |
||||
|
||||
if (StringUtils.isNotEmpty(targetHdfsParameter.getCompressionCodec())) { |
||||
hdfsTargetSb.append(Constants.SPACE).append(SqoopConstants.COMPRESSION_CODEC) |
||||
.append(Constants.SPACE).append(targetHdfsParameter.getCompressionCodec()); |
||||
} |
||||
|
||||
if (StringUtils.isNotEmpty(targetHdfsParameter.getFileType())) { |
||||
hdfsTargetSb.append(Constants.SPACE).append(targetHdfsParameter.getFileType()); |
||||
} |
||||
|
||||
if (targetHdfsParameter.isDeleteTargetDir()) { |
||||
hdfsTargetSb.append(Constants.SPACE).append(SqoopConstants.DELETE_TARGET_DIR); |
||||
} |
||||
|
||||
if (StringUtils.isNotEmpty(targetHdfsParameter.getFieldsTerminated())) { |
||||
hdfsTargetSb.append(Constants.SPACE).append(SqoopConstants.FIELDS_TERMINATED_BY) |
||||
.append(Constants.SPACE).append(Constants.SINGLE_QUOTES).append(targetHdfsParameter.getFieldsTerminated()).append(Constants.SINGLE_QUOTES); |
||||
} |
||||
|
||||
if (StringUtils.isNotEmpty(targetHdfsParameter.getLinesTerminated())) { |
||||
hdfsTargetSb.append(Constants.SPACE).append(SqoopConstants.LINES_TERMINATED_BY) |
||||
.append(Constants.SPACE).append(Constants.SINGLE_QUOTES).append(targetHdfsParameter.getLinesTerminated()).append(Constants.SINGLE_QUOTES); |
||||
} |
||||
|
||||
hdfsTargetSb.append(Constants.SPACE).append(SqoopConstants.FIELD_NULL_PLACEHOLDER); |
||||
} |
||||
} catch (Exception e) { |
||||
logger.error(String.format("Sqoop hdfs target params build failed: [%s]", e.getMessage())); |
||||
} |
||||
|
||||
return hdfsTargetSb.toString(); |
||||
} |
||||
} |
@ -1,91 +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.server.worker.task.sqoop.generator.targets; |
||||
|
||||
import org.apache.dolphinscheduler.common.Constants; |
||||
import org.apache.dolphinscheduler.common.task.sqoop.SqoopParameters; |
||||
import org.apache.dolphinscheduler.common.task.sqoop.targets.TargetHiveParameter; |
||||
import org.apache.dolphinscheduler.common.utils.JSONUtils; |
||||
import org.apache.dolphinscheduler.common.utils.StringUtils; |
||||
import org.apache.dolphinscheduler.server.entity.TaskExecutionContext; |
||||
import org.apache.dolphinscheduler.server.worker.task.sqoop.SqoopConstants; |
||||
import org.apache.dolphinscheduler.server.worker.task.sqoop.generator.ITargetGenerator; |
||||
|
||||
import org.slf4j.Logger; |
||||
import org.slf4j.LoggerFactory; |
||||
|
||||
/** |
||||
* hive target generator |
||||
*/ |
||||
public class HiveTargetGenerator implements ITargetGenerator { |
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(HiveTargetGenerator.class); |
||||
|
||||
@Override |
||||
public String generate(SqoopParameters sqoopParameters, TaskExecutionContext taskExecutionContext) { |
||||
|
||||
StringBuilder hiveTargetSb = new StringBuilder(); |
||||
|
||||
try { |
||||
TargetHiveParameter targetHiveParameter = |
||||
JSONUtils.parseObject(sqoopParameters.getTargetParams(), TargetHiveParameter.class); |
||||
if (null != targetHiveParameter) { |
||||
hiveTargetSb.append(Constants.SPACE).append(SqoopConstants.HIVE_IMPORT); |
||||
|
||||
if (StringUtils.isNotEmpty(targetHiveParameter.getHiveDatabase()) |
||||
&& StringUtils.isNotEmpty(targetHiveParameter.getHiveTable())) { |
||||
hiveTargetSb.append(Constants.SPACE).append(SqoopConstants.HIVE_DATABASE) |
||||
.append(Constants.SPACE).append(targetHiveParameter.getHiveDatabase()) |
||||
.append(Constants.SPACE).append(SqoopConstants.HIVE_TABLE) |
||||
.append(Constants.SPACE).append(targetHiveParameter.getHiveTable()); |
||||
} |
||||
|
||||
if (targetHiveParameter.isCreateHiveTable()) { |
||||
hiveTargetSb.append(Constants.SPACE).append(SqoopConstants.CREATE_HIVE_TABLE); |
||||
} |
||||
|
||||
if (targetHiveParameter.isDropDelimiter()) { |
||||
hiveTargetSb.append(Constants.SPACE).append(SqoopConstants.HIVE_DROP_IMPORT_DELIMS); |
||||
} |
||||
|
||||
if (targetHiveParameter.isHiveOverWrite()) { |
||||
hiveTargetSb.append(Constants.SPACE).append(SqoopConstants.HIVE_OVERWRITE) |
||||
.append(Constants.SPACE).append(SqoopConstants.DELETE_TARGET_DIR); |
||||
} |
||||
|
||||
if (StringUtils.isNotEmpty(targetHiveParameter.getReplaceDelimiter())) { |
||||
hiveTargetSb.append(Constants.SPACE).append(SqoopConstants.HIVE_DELIMS_REPLACEMENT) |
||||
.append(Constants.SPACE).append(targetHiveParameter.getReplaceDelimiter()); |
||||
} |
||||
|
||||
if (StringUtils.isNotEmpty(targetHiveParameter.getHivePartitionKey()) |
||||
&& StringUtils.isNotEmpty(targetHiveParameter.getHivePartitionValue())) { |
||||
hiveTargetSb.append(Constants.SPACE).append(SqoopConstants.HIVE_PARTITION_KEY) |
||||
.append(Constants.SPACE).append(targetHiveParameter.getHivePartitionKey()) |
||||
.append(Constants.SPACE).append(SqoopConstants.HIVE_PARTITION_VALUE) |
||||
.append(Constants.SPACE).append(targetHiveParameter.getHivePartitionValue()); |
||||
} |
||||
|
||||
} |
||||
} catch (Exception e) { |
||||
logger.error(String.format("Sqoop hive target params build failed: [%s]", e.getMessage())); |
||||
} |
||||
|
||||
return hiveTargetSb.toString(); |
||||
} |
||||
} |
@ -1,115 +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.server.worker.task.sqoop.generator.targets; |
||||
|
||||
import org.apache.dolphinscheduler.common.Constants; |
||||
import org.apache.dolphinscheduler.common.datasource.BaseConnectionParam; |
||||
import org.apache.dolphinscheduler.common.datasource.DatasourceUtil; |
||||
import org.apache.dolphinscheduler.common.enums.DbType; |
||||
import org.apache.dolphinscheduler.common.task.sqoop.SqoopParameters; |
||||
import org.apache.dolphinscheduler.common.task.sqoop.targets.TargetMysqlParameter; |
||||
import org.apache.dolphinscheduler.common.utils.CommonUtils; |
||||
import org.apache.dolphinscheduler.common.utils.JSONUtils; |
||||
import org.apache.dolphinscheduler.common.utils.StringUtils; |
||||
import org.apache.dolphinscheduler.server.entity.SqoopTaskExecutionContext; |
||||
import org.apache.dolphinscheduler.server.entity.TaskExecutionContext; |
||||
import org.apache.dolphinscheduler.server.worker.task.sqoop.SqoopConstants; |
||||
import org.apache.dolphinscheduler.server.worker.task.sqoop.generator.ITargetGenerator; |
||||
|
||||
import org.slf4j.Logger; |
||||
import org.slf4j.LoggerFactory; |
||||
|
||||
/** |
||||
* mysql target generator |
||||
*/ |
||||
public class MysqlTargetGenerator implements ITargetGenerator { |
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(MysqlTargetGenerator.class); |
||||
|
||||
@Override |
||||
public String generate(SqoopParameters sqoopParameters, TaskExecutionContext taskExecutionContext) { |
||||
|
||||
StringBuilder mysqlTargetSb = new StringBuilder(); |
||||
|
||||
try { |
||||
TargetMysqlParameter targetMysqlParameter = |
||||
JSONUtils.parseObject(sqoopParameters.getTargetParams(), TargetMysqlParameter.class); |
||||
|
||||
SqoopTaskExecutionContext sqoopTaskExecutionContext = taskExecutionContext.getSqoopTaskExecutionContext(); |
||||
|
||||
if (null != targetMysqlParameter && targetMysqlParameter.getTargetDatasource() != 0) { |
||||
|
||||
// get datasource
|
||||
BaseConnectionParam baseDataSource = (BaseConnectionParam) DatasourceUtil.buildConnectionParams( |
||||
DbType.of(sqoopTaskExecutionContext.getTargetType()), |
||||
sqoopTaskExecutionContext.getTargetConnectionParams()); |
||||
|
||||
if (null != baseDataSource) { |
||||
|
||||
mysqlTargetSb.append(Constants.SPACE).append(SqoopConstants.DB_CONNECT) |
||||
.append(Constants.SPACE).append(Constants.DOUBLE_QUOTES) |
||||
.append(DatasourceUtil.getJdbcUrl(DbType.MYSQL, baseDataSource)).append(Constants.DOUBLE_QUOTES) |
||||
.append(Constants.SPACE).append(SqoopConstants.DB_USERNAME) |
||||
.append(Constants.SPACE).append(baseDataSource.getUser()) |
||||
.append(Constants.SPACE).append(SqoopConstants.DB_PWD) |
||||
.append(Constants.SPACE).append(Constants.DOUBLE_QUOTES) |
||||
.append(CommonUtils.decodePassword(baseDataSource.getPassword())).append(Constants.DOUBLE_QUOTES) |
||||
.append(Constants.SPACE).append(SqoopConstants.TABLE) |
||||
.append(Constants.SPACE).append(targetMysqlParameter.getTargetTable()); |
||||
|
||||
if (StringUtils.isNotEmpty(targetMysqlParameter.getTargetColumns())) { |
||||
mysqlTargetSb.append(Constants.SPACE).append(SqoopConstants.COLUMNS) |
||||
.append(Constants.SPACE).append(targetMysqlParameter.getTargetColumns()); |
||||
} |
||||
|
||||
if (StringUtils.isNotEmpty(targetMysqlParameter.getFieldsTerminated())) { |
||||
mysqlTargetSb.append(Constants.SPACE).append(SqoopConstants.FIELDS_TERMINATED_BY); |
||||
if (targetMysqlParameter.getFieldsTerminated().contains("'")) { |
||||
mysqlTargetSb.append(Constants.SPACE).append(targetMysqlParameter.getFieldsTerminated()); |
||||
|
||||
} else { |
||||
mysqlTargetSb.append(Constants.SPACE).append(Constants.SINGLE_QUOTES).append(targetMysqlParameter.getFieldsTerminated()).append(Constants.SINGLE_QUOTES); |
||||
} |
||||
} |
||||
|
||||
if (StringUtils.isNotEmpty(targetMysqlParameter.getLinesTerminated())) { |
||||
mysqlTargetSb.append(Constants.SPACE).append(SqoopConstants.LINES_TERMINATED_BY); |
||||
if (targetMysqlParameter.getLinesTerminated().contains(Constants.SINGLE_QUOTES)) { |
||||
mysqlTargetSb.append(Constants.SPACE).append(targetMysqlParameter.getLinesTerminated()); |
||||
} else { |
||||
mysqlTargetSb.append(Constants.SPACE).append(Constants.SINGLE_QUOTES).append(targetMysqlParameter.getLinesTerminated()).append(Constants.SINGLE_QUOTES); |
||||
} |
||||
} |
||||
|
||||
if (targetMysqlParameter.getIsUpdate() |
||||
&& StringUtils.isNotEmpty(targetMysqlParameter.getTargetUpdateKey()) |
||||
&& StringUtils.isNotEmpty(targetMysqlParameter.getTargetUpdateMode())) { |
||||
mysqlTargetSb.append(Constants.SPACE).append(SqoopConstants.UPDATE_KEY) |
||||
.append(Constants.SPACE).append(targetMysqlParameter.getTargetUpdateKey()) |
||||
.append(Constants.SPACE).append(SqoopConstants.UPDATE_MODE) |
||||
.append(Constants.SPACE).append(targetMysqlParameter.getTargetUpdateMode()); |
||||
} |
||||
} |
||||
} |
||||
} catch (Exception e) { |
||||
logger.error(String.format("Sqoop mysql target params build failed: [%s]", e.getMessage())); |
||||
} |
||||
|
||||
return mysqlTargetSb.toString(); |
||||
} |
||||
} |
@ -0,0 +1,167 @@
|
||||
/* |
||||
* 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.server.master; |
||||
|
||||
import org.apache.dolphinscheduler.common.Constants; |
||||
import org.apache.dolphinscheduler.common.enums.ExecutionStatus; |
||||
import org.apache.dolphinscheduler.common.enums.TaskTimeoutStrategy; |
||||
import org.apache.dolphinscheduler.common.enums.TimeoutFlag; |
||||
import org.apache.dolphinscheduler.common.task.switchtask.SwitchParameters; |
||||
import org.apache.dolphinscheduler.common.task.switchtask.SwitchResultVo; |
||||
import org.apache.dolphinscheduler.common.utils.JSONUtils; |
||||
import org.apache.dolphinscheduler.dao.entity.ProcessInstance; |
||||
import org.apache.dolphinscheduler.dao.entity.TaskDefinition; |
||||
import org.apache.dolphinscheduler.dao.entity.TaskInstance; |
||||
import org.apache.dolphinscheduler.server.master.config.MasterConfig; |
||||
import org.apache.dolphinscheduler.server.master.runner.SwitchTaskExecThread; |
||||
import org.apache.dolphinscheduler.service.bean.SpringApplicationContext; |
||||
import org.apache.dolphinscheduler.service.process.ProcessService; |
||||
|
||||
import java.util.ArrayList; |
||||
import java.util.HashMap; |
||||
import java.util.List; |
||||
import java.util.Map; |
||||
|
||||
import org.junit.Assert; |
||||
import org.junit.Before; |
||||
import org.junit.Test; |
||||
import org.junit.runner.RunWith; |
||||
import org.mockito.Mockito; |
||||
import org.mockito.junit.MockitoJUnitRunner; |
||||
import org.slf4j.Logger; |
||||
import org.slf4j.LoggerFactory; |
||||
import org.springframework.context.ApplicationContext; |
||||
|
||||
@RunWith(MockitoJUnitRunner.Silent.class) |
||||
public class SwitchTaskTest { |
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(SwitchTaskTest.class); |
||||
|
||||
/** |
||||
* TaskNode.runFlag : task can be run normally |
||||
*/ |
||||
public static final String FLOWNODE_RUN_FLAG_NORMAL = "NORMAL"; |
||||
|
||||
private ProcessService processService; |
||||
|
||||
private ProcessInstance processInstance; |
||||
|
||||
@Before |
||||
public void before() { |
||||
ApplicationContext applicationContext = Mockito.mock(ApplicationContext.class); |
||||
SpringApplicationContext springApplicationContext = new SpringApplicationContext(); |
||||
springApplicationContext.setApplicationContext(applicationContext); |
||||
|
||||
MasterConfig config = new MasterConfig(); |
||||
Mockito.when(applicationContext.getBean(MasterConfig.class)).thenReturn(config); |
||||
config.setMasterTaskCommitRetryTimes(3); |
||||
config.setMasterTaskCommitInterval(1000); |
||||
|
||||
processService = Mockito.mock(ProcessService.class); |
||||
Mockito.when(applicationContext.getBean(ProcessService.class)).thenReturn(processService); |
||||
|
||||
processInstance = getProcessInstance(); |
||||
Mockito.when(processService |
||||
.findProcessInstanceById(processInstance.getId())) |
||||
.thenReturn(processInstance); |
||||
} |
||||
|
||||
private TaskInstance testBasicInit(ExecutionStatus expectResult) { |
||||
TaskDefinition taskDefinition = new TaskDefinition(); |
||||
taskDefinition.setTimeoutFlag(TimeoutFlag.OPEN); |
||||
taskDefinition.setTimeoutNotifyStrategy(TaskTimeoutStrategy.WARN); |
||||
taskDefinition.setTimeout(0); |
||||
Mockito.when(processService.findTaskDefinition(1L, 1)) |
||||
.thenReturn(taskDefinition); |
||||
TaskInstance taskInstance = getTaskInstance(getTaskNode(), processInstance); |
||||
|
||||
// for MasterBaseTaskExecThread.submit
|
||||
Mockito.when(processService |
||||
.submitTask(taskInstance)) |
||||
.thenReturn(taskInstance); |
||||
// for MasterBaseTaskExecThread.call
|
||||
Mockito.when(processService |
||||
.findTaskInstanceById(taskInstance.getId())) |
||||
.thenReturn(taskInstance); |
||||
// for SwitchTaskExecThread.initTaskParameters
|
||||
Mockito.when(processService |
||||
.saveTaskInstance(taskInstance)) |
||||
.thenReturn(true); |
||||
// for SwitchTaskExecThread.updateTaskState
|
||||
Mockito.when(processService |
||||
.updateTaskInstance(taskInstance)) |
||||
.thenReturn(true); |
||||
|
||||
return taskInstance; |
||||
} |
||||
|
||||
@Test |
||||
public void testExe() throws Exception { |
||||
TaskInstance taskInstance = testBasicInit(ExecutionStatus.SUCCESS); |
||||
taskInstance.setState(ExecutionStatus.SUBMITTED_SUCCESS); |
||||
SwitchTaskExecThread taskExecThread = new SwitchTaskExecThread(taskInstance); |
||||
taskExecThread.call(); |
||||
Assert.assertEquals(ExecutionStatus.SUCCESS, taskExecThread.getTaskInstance().getState()); |
||||
} |
||||
|
||||
private SwitchParameters getTaskNode() { |
||||
SwitchParameters conditionsParameters = new SwitchParameters(); |
||||
|
||||
SwitchResultVo switchResultVo1 = new SwitchResultVo(); |
||||
switchResultVo1.setCondition(" 2 == 1"); |
||||
switchResultVo1.setNextNode("t1"); |
||||
SwitchResultVo switchResultVo2 = new SwitchResultVo(); |
||||
switchResultVo2.setCondition(" 2 == 2"); |
||||
switchResultVo2.setNextNode("t2"); |
||||
SwitchResultVo switchResultVo3 = new SwitchResultVo(); |
||||
switchResultVo3.setCondition(" 3 == 2"); |
||||
switchResultVo3.setNextNode("t3"); |
||||
List<SwitchResultVo> list = new ArrayList<>(); |
||||
list.add(switchResultVo1); |
||||
list.add(switchResultVo2); |
||||
list.add(switchResultVo3); |
||||
conditionsParameters.setDependTaskList(list); |
||||
conditionsParameters.setNextNode("t"); |
||||
conditionsParameters.setRelation("AND"); |
||||
|
||||
return conditionsParameters; |
||||
} |
||||
|
||||
private ProcessInstance getProcessInstance() { |
||||
ProcessInstance processInstance = new ProcessInstance(); |
||||
processInstance.setId(1000); |
||||
processInstance.setState(ExecutionStatus.RUNNING_EXECUTION); |
||||
processInstance.setProcessDefinitionCode(1L); |
||||
return processInstance; |
||||
} |
||||
|
||||
private TaskInstance getTaskInstance(SwitchParameters conditionsParameters, ProcessInstance processInstance) { |
||||
TaskInstance taskInstance = new TaskInstance(); |
||||
taskInstance.setId(1000); |
||||
Map<String, Object> taskParamsMap = new HashMap<>(); |
||||
taskParamsMap.put(Constants.SWITCH_RESULT, ""); |
||||
taskInstance.setTaskParams(JSONUtils.toJsonString(taskParamsMap)); |
||||
taskInstance.setSwitchDependency(conditionsParameters); |
||||
taskInstance.setName("C"); |
||||
taskInstance.setTaskType("SWITCH"); |
||||
taskInstance.setProcessInstanceId(processInstance.getId()); |
||||
taskInstance.setTaskCode(1L); |
||||
taskInstance.setTaskDefinitionVersion(1); |
||||
return taskInstance; |
||||
} |
||||
} |
@ -1,192 +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.server.worker.runner; |
||||
|
||||
import org.apache.dolphinscheduler.common.enums.ExecutionStatus; |
||||
import org.apache.dolphinscheduler.common.enums.TaskType; |
||||
import org.apache.dolphinscheduler.common.model.TaskNode; |
||||
import org.apache.dolphinscheduler.common.task.AbstractParameters; |
||||
import org.apache.dolphinscheduler.common.task.sql.SqlParameters; |
||||
import org.apache.dolphinscheduler.common.utils.CommonUtils; |
||||
import org.apache.dolphinscheduler.common.utils.JSONUtils; |
||||
import org.apache.dolphinscheduler.common.utils.LoggerUtils; |
||||
import org.apache.dolphinscheduler.common.utils.OSUtils; |
||||
import org.apache.dolphinscheduler.remote.command.Command; |
||||
import org.apache.dolphinscheduler.remote.command.TaskExecuteAckCommand; |
||||
import org.apache.dolphinscheduler.remote.command.TaskExecuteResponseCommand; |
||||
import org.apache.dolphinscheduler.server.entity.TaskExecutionContext; |
||||
import org.apache.dolphinscheduler.server.worker.cache.impl.TaskExecutionContextCacheManagerImpl; |
||||
import org.apache.dolphinscheduler.server.worker.processor.TaskCallbackService; |
||||
import org.apache.dolphinscheduler.server.worker.task.AbstractTask; |
||||
import org.apache.dolphinscheduler.server.worker.task.TaskManager; |
||||
import org.apache.dolphinscheduler.service.alert.AlertClientService; |
||||
import org.apache.dolphinscheduler.service.bean.SpringApplicationContext; |
||||
|
||||
import java.util.Collections; |
||||
import java.util.Date; |
||||
import java.util.List; |
||||
|
||||
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; |
||||
import org.slf4j.Logger; |
||||
import org.slf4j.LoggerFactory; |
||||
|
||||
/** |
||||
* test task execute thread. |
||||
*/ |
||||
@RunWith(PowerMockRunner.class) |
||||
@PrepareForTest({TaskManager.class, JSONUtils.class, CommonUtils.class, SpringApplicationContext.class, OSUtils.class}) |
||||
public class TaskExecuteThreadTest { |
||||
|
||||
private TaskExecutionContext taskExecutionContext; |
||||
|
||||
private TaskCallbackService taskCallbackService; |
||||
|
||||
private Command ackCommand; |
||||
|
||||
private Command responseCommand; |
||||
|
||||
private Logger taskLogger; |
||||
|
||||
private TaskExecutionContextCacheManagerImpl taskExecutionContextCacheManager; |
||||
|
||||
private AlertClientService alertClientService; |
||||
|
||||
@Before |
||||
public void before() { |
||||
// init task execution context, logger
|
||||
taskExecutionContext = new TaskExecutionContext(); |
||||
taskExecutionContext.setProcessId(12345); |
||||
taskExecutionContext.setProcessInstanceId(1); |
||||
taskExecutionContext.setTaskInstanceId(1); |
||||
taskExecutionContext.setProcessDefineCode(1L); |
||||
taskExecutionContext.setProcessDefineVersion(1); |
||||
taskExecutionContext.setTaskType(TaskType.SHELL.getDesc()); |
||||
taskExecutionContext.setFirstSubmitTime(new Date()); |
||||
taskExecutionContext.setDelayTime(0); |
||||
taskExecutionContext.setLogPath("/tmp/test.log"); |
||||
taskExecutionContext.setHost("localhost"); |
||||
taskExecutionContext.setExecutePath("/tmp/dolphinscheduler/exec/process/1/2/3/4"); |
||||
|
||||
ackCommand = new TaskExecuteAckCommand().convert2Command(); |
||||
responseCommand = new TaskExecuteResponseCommand(taskExecutionContext.getTaskInstanceId()).convert2Command(); |
||||
|
||||
taskLogger = LoggerFactory.getLogger(LoggerUtils.buildTaskId( |
||||
LoggerUtils.TASK_LOGGER_INFO_PREFIX, |
||||
taskExecutionContext.getProcessDefineCode(), |
||||
taskExecutionContext.getProcessDefineVersion(), |
||||
taskExecutionContext.getProcessInstanceId(), |
||||
taskExecutionContext.getTaskInstanceId() |
||||
)); |
||||
|
||||
taskExecutionContextCacheManager = new TaskExecutionContextCacheManagerImpl(); |
||||
taskExecutionContextCacheManager.cacheTaskExecutionContext(taskExecutionContext); |
||||
|
||||
taskCallbackService = PowerMockito.mock(TaskCallbackService.class); |
||||
PowerMockito.doNothing().when(taskCallbackService).sendAck(taskExecutionContext.getTaskInstanceId(), ackCommand); |
||||
PowerMockito.doNothing().when(taskCallbackService).sendResult(taskExecutionContext.getTaskInstanceId(), responseCommand); |
||||
|
||||
PowerMockito.mockStatic(SpringApplicationContext.class); |
||||
PowerMockito.when(SpringApplicationContext.getBean(TaskExecutionContextCacheManagerImpl.class)) |
||||
.thenReturn(taskExecutionContextCacheManager); |
||||
|
||||
alertClientService = PowerMockito.mock(AlertClientService.class); |
||||
|
||||
PowerMockito.mockStatic(TaskManager.class); |
||||
PowerMockito.when(TaskManager.newTask(taskExecutionContext, taskLogger, alertClientService)) |
||||
.thenReturn(new SimpleTask(taskExecutionContext, taskLogger)); |
||||
|
||||
PowerMockito.mockStatic(JSONUtils.class); |
||||
PowerMockito.when(JSONUtils.parseObject(taskExecutionContext.getTaskJson(), TaskNode.class)) |
||||
.thenReturn(new TaskNode()); |
||||
|
||||
PowerMockito.mockStatic(CommonUtils.class); |
||||
PowerMockito.when(CommonUtils.getSystemEnvPath()).thenReturn("/user_home/.bash_profile"); |
||||
|
||||
List<String> osUserList = Collections.singletonList("test"); |
||||
PowerMockito.mockStatic(OSUtils.class); |
||||
PowerMockito.when(OSUtils.getUserList()).thenReturn(osUserList); |
||||
} |
||||
|
||||
@Test |
||||
public void testNormalExecution() { |
||||
taskExecutionContext.setTaskType(TaskType.SQL.getDesc()); |
||||
taskExecutionContext.setStartTime(new Date()); |
||||
taskExecutionContext.setCurrentExecutionStatus(ExecutionStatus.RUNNING_EXECUTION); |
||||
taskExecutionContext.setTenantCode("test"); |
||||
TaskExecuteThread taskExecuteThread = new TaskExecuteThread(taskExecutionContext, taskCallbackService, taskLogger, alertClientService); |
||||
taskExecuteThread.run(); |
||||
taskExecutionContext.getCurrentExecutionStatus(); |
||||
|
||||
taskExecuteThread.run(); |
||||
|
||||
Assert.assertEquals(ExecutionStatus.RUNNING_EXECUTION, taskExecutionContext.getCurrentExecutionStatus()); |
||||
} |
||||
|
||||
@Test |
||||
public void testDelayExecution() { |
||||
taskExecutionContext.setTaskType(TaskType.PYTHON.getDesc()); |
||||
taskExecutionContext.setStartTime(null); |
||||
taskExecutionContext.setDelayTime(1); |
||||
taskExecutionContext.setCurrentExecutionStatus(ExecutionStatus.DELAY_EXECUTION); |
||||
taskExecutionContext.setTenantCode("test"); |
||||
TaskExecuteThread taskExecuteThread = new TaskExecuteThread(taskExecutionContext, taskCallbackService, taskLogger, alertClientService); |
||||
taskExecuteThread.run(); |
||||
|
||||
Assert.assertEquals(ExecutionStatus.RUNNING_EXECUTION, taskExecutionContext.getCurrentExecutionStatus()); |
||||
} |
||||
|
||||
private class SimpleTask extends AbstractTask { |
||||
|
||||
protected SimpleTask(TaskExecutionContext taskExecutionContext, Logger logger) { |
||||
super(taskExecutionContext, logger); |
||||
// pid
|
||||
this.processId = taskExecutionContext.getProcessId(); |
||||
} |
||||
|
||||
@Override |
||||
public AbstractParameters getParameters() { |
||||
return new SqlParameters(); |
||||
} |
||||
|
||||
@Override |
||||
public void init() { |
||||
|
||||
} |
||||
|
||||
@Override |
||||
public void handle() throws Exception { |
||||
|
||||
} |
||||
|
||||
@Override |
||||
public void after() { |
||||
|
||||
} |
||||
|
||||
@Override |
||||
public ExecutionStatus getExitStatus() { |
||||
return ExecutionStatus.SUCCESS; |
||||
} |
||||
} |
||||
} |
@ -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.server.worker.runner; |
||||
|
||||
import org.apache.dolphinscheduler.common.enums.ExecutionStatus; |
||||
import org.apache.dolphinscheduler.common.enums.TaskType; |
||||
import org.apache.dolphinscheduler.common.model.TaskNode; |
||||
import org.apache.dolphinscheduler.common.task.AbstractParameters; |
||||
import org.apache.dolphinscheduler.common.thread.Stopper; |
||||
import org.apache.dolphinscheduler.common.utils.CommonUtils; |
||||
import org.apache.dolphinscheduler.common.utils.JSONUtils; |
||||
import org.apache.dolphinscheduler.common.utils.LoggerUtils; |
||||
import org.apache.dolphinscheduler.common.utils.OSUtils; |
||||
import org.apache.dolphinscheduler.remote.command.Command; |
||||
import org.apache.dolphinscheduler.remote.command.TaskExecuteAckCommand; |
||||
import org.apache.dolphinscheduler.remote.command.TaskExecuteResponseCommand; |
||||
import org.apache.dolphinscheduler.server.entity.TaskExecutionContext; |
||||
import org.apache.dolphinscheduler.server.worker.cache.impl.TaskExecutionContextCacheManagerImpl; |
||||
import org.apache.dolphinscheduler.server.worker.config.WorkerConfig; |
||||
import org.apache.dolphinscheduler.server.worker.processor.TaskCallbackService; |
||||
import org.apache.dolphinscheduler.server.worker.task.AbstractTask; |
||||
import org.apache.dolphinscheduler.server.worker.task.TaskManager; |
||||
import org.apache.dolphinscheduler.service.alert.AlertClientService; |
||||
import org.apache.dolphinscheduler.service.bean.SpringApplicationContext; |
||||
|
||||
import java.util.Collections; |
||||
import java.util.Date; |
||||
import java.util.List; |
||||
|
||||
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; |
||||
import org.slf4j.Logger; |
||||
import org.slf4j.LoggerFactory; |
||||
|
||||
/** |
||||
* test worker manager thread. |
||||
*/ |
||||
@RunWith(PowerMockRunner.class) |
||||
@PrepareForTest({ |
||||
Stopper.class, |
||||
TaskManager.class, |
||||
JSONUtils.class, |
||||
CommonUtils.class, |
||||
SpringApplicationContext.class, |
||||
OSUtils.class}) |
||||
public class WorkerManagerThreadTest { |
||||
|
||||
private TaskCallbackService taskCallbackService; |
||||
|
||||
private WorkerManagerThread workerManager; |
||||
|
||||
private TaskExecutionContext taskExecutionContext; |
||||
|
||||
private AlertClientService alertClientService; |
||||
|
||||
private Logger taskLogger; |
||||
|
||||
@Before |
||||
public void before() { |
||||
// init task execution context, logger
|
||||
taskExecutionContext = new TaskExecutionContext(); |
||||
taskExecutionContext.setProcessId(12345); |
||||
taskExecutionContext.setProcessInstanceId(1); |
||||
taskExecutionContext.setTaskInstanceId(1); |
||||
taskExecutionContext.setProcessDefineCode(1L); |
||||
taskExecutionContext.setProcessDefineVersion(1); |
||||
taskExecutionContext.setTenantCode("test"); |
||||
taskExecutionContext.setTaskType(TaskType.SHELL.getDesc()); |
||||
taskExecutionContext.setFirstSubmitTime(new Date()); |
||||
taskExecutionContext.setDelayTime(0); |
||||
taskExecutionContext.setLogPath("/tmp/test.log"); |
||||
taskExecutionContext.setHost("localhost"); |
||||
taskExecutionContext.setExecutePath("/tmp/dolphinscheduler/exec/process/1/2/3/4"); |
||||
|
||||
Command ackCommand = new TaskExecuteAckCommand().convert2Command(); |
||||
Command responseCommand = new TaskExecuteResponseCommand(taskExecutionContext.getTaskInstanceId()).convert2Command(); |
||||
|
||||
taskLogger = LoggerFactory.getLogger(LoggerUtils.buildTaskId( |
||||
LoggerUtils.TASK_LOGGER_INFO_PREFIX, |
||||
taskExecutionContext.getProcessDefineCode(), |
||||
taskExecutionContext.getProcessDefineVersion(), |
||||
taskExecutionContext.getProcessInstanceId(), |
||||
taskExecutionContext.getTaskInstanceId() |
||||
)); |
||||
|
||||
TaskExecutionContextCacheManagerImpl taskExecutionContextCacheManager = new TaskExecutionContextCacheManagerImpl(); |
||||
taskExecutionContextCacheManager.cacheTaskExecutionContext(taskExecutionContext); |
||||
|
||||
alertClientService = PowerMockito.mock(AlertClientService.class); |
||||
WorkerConfig workerConfig = PowerMockito.mock(WorkerConfig.class); |
||||
taskCallbackService = PowerMockito.mock(TaskCallbackService.class); |
||||
PowerMockito.doNothing().when(taskCallbackService).sendAck(taskExecutionContext.getTaskInstanceId(), ackCommand); |
||||
PowerMockito.doNothing().when(taskCallbackService).sendResult(taskExecutionContext.getTaskInstanceId(), responseCommand); |
||||
PowerMockito.mockStatic(SpringApplicationContext.class); |
||||
PowerMockito.when(SpringApplicationContext.getBean(TaskExecutionContextCacheManagerImpl.class)) |
||||
.thenReturn(taskExecutionContextCacheManager); |
||||
PowerMockito.when(SpringApplicationContext.getBean(WorkerConfig.class)) |
||||
.thenReturn(workerConfig); |
||||
PowerMockito.when(SpringApplicationContext.getBean(TaskCallbackService.class)) |
||||
.thenReturn(taskCallbackService); |
||||
PowerMockito.when(workerConfig.getWorkerExecThreads()).thenReturn(5); |
||||
workerManager = new WorkerManagerThread(); |
||||
|
||||
PowerMockito.mockStatic(TaskManager.class); |
||||
PowerMockito.when(TaskManager.newTask(taskExecutionContext, taskLogger, alertClientService)) |
||||
.thenReturn(new SimpleTask(taskExecutionContext, taskLogger)); |
||||
PowerMockito.mockStatic(JSONUtils.class); |
||||
PowerMockito.when(JSONUtils.parseObject(taskExecutionContext.getTaskJson(), TaskNode.class)) |
||||
.thenReturn(new TaskNode()); |
||||
PowerMockito.mockStatic(CommonUtils.class); |
||||
PowerMockito.when(CommonUtils.getSystemEnvPath()).thenReturn("/user_home/.bash_profile"); |
||||
List<String> osUserList = Collections.singletonList("test"); |
||||
PowerMockito.mockStatic(OSUtils.class); |
||||
PowerMockito.when(OSUtils.getUserList()).thenReturn(osUserList); |
||||
PowerMockito.mockStatic(Stopper.class); |
||||
PowerMockito.when(Stopper.isRunning()).thenReturn(true, false); |
||||
} |
||||
|
||||
@Test |
||||
public void testSendTaskKillResponse() { |
||||
TaskExecuteThread taskExecuteThread = new TaskExecuteThread(taskExecutionContext, taskCallbackService, taskLogger, alertClientService); |
||||
workerManager.offer(taskExecuteThread); |
||||
Assert.assertEquals(1, workerManager.getQueueSize()); |
||||
workerManager.killTaskBeforeExecuteByInstanceId(1); |
||||
Assert.assertEquals(0, workerManager.getQueueSize()); |
||||
} |
||||
|
||||
@Test |
||||
public void testRun() { |
||||
TaskExecuteThread taskExecuteThread = new TaskExecuteThread(taskExecutionContext, taskCallbackService, taskLogger, alertClientService); |
||||
workerManager.offer(taskExecuteThread); |
||||
Assert.assertEquals(1, workerManager.getQueueSize()); |
||||
workerManager.run(); |
||||
Assert.assertEquals(0, workerManager.getQueueSize()); |
||||
} |
||||
|
||||
private static class SimpleTask extends AbstractTask { |
||||
|
||||
protected SimpleTask(TaskExecutionContext taskExecutionContext, Logger logger) { |
||||
super(taskExecutionContext, logger); |
||||
// pid
|
||||
this.processId = taskExecutionContext.getProcessId(); |
||||
} |
||||
|
||||
@Override |
||||
public AbstractParameters getParameters() { |
||||
return null; |
||||
} |
||||
|
||||
@Override |
||||
public void init() { |
||||
|
||||
} |
||||
|
||||
@Override |
||||
public void handle() { |
||||
|
||||
} |
||||
|
||||
@Override |
||||
public void after() { |
||||
|
||||
} |
||||
|
||||
@Override |
||||
public ExecutionStatus getExitStatus() { |
||||
return ExecutionStatus.SUCCESS; |
||||
} |
||||
} |
||||
} |
@ -1,250 +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.server.worker.shell; |
||||
|
||||
import org.apache.dolphinscheduler.common.Constants; |
||||
import org.apache.dolphinscheduler.common.enums.ExecutionStatus; |
||||
import org.apache.dolphinscheduler.common.utils.OSUtils; |
||||
import org.apache.dolphinscheduler.server.entity.TaskExecutionContext; |
||||
import org.apache.dolphinscheduler.server.worker.task.AbstractCommandExecutor; |
||||
import org.apache.dolphinscheduler.server.worker.task.AbstractTask; |
||||
import org.apache.dolphinscheduler.server.worker.task.TaskProps; |
||||
import org.apache.dolphinscheduler.service.bean.SpringApplicationContext; |
||||
import org.apache.dolphinscheduler.service.process.ProcessService; |
||||
|
||||
import java.io.IOException; |
||||
import java.io.InputStream; |
||||
import java.io.OutputStream; |
||||
import java.lang.reflect.Method; |
||||
import java.util.Date; |
||||
import java.util.List; |
||||
|
||||
import org.junit.Assert; |
||||
import org.junit.Before; |
||||
import org.junit.Ignore; |
||||
import org.junit.Test; |
||||
import org.junit.runner.RunWith; |
||||
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 org.springframework.context.ApplicationContext; |
||||
|
||||
/** |
||||
* python shell command executor test |
||||
*/ |
||||
@RunWith(PowerMockRunner.class) |
||||
@PrepareForTest(OSUtils.class) |
||||
@PowerMockIgnore({"javax.management.*"}) |
||||
public class ShellCommandExecutorTest { |
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(ShellCommandExecutorTest.class); |
||||
|
||||
private ProcessService processService = null; |
||||
private ApplicationContext applicationContext; |
||||
|
||||
@Before |
||||
public void before() { |
||||
applicationContext = PowerMockito.mock(ApplicationContext.class); |
||||
processService = PowerMockito.mock(ProcessService.class); |
||||
SpringApplicationContext springApplicationContext = new SpringApplicationContext(); |
||||
springApplicationContext.setApplicationContext(applicationContext); |
||||
PowerMockito.when(applicationContext.getBean(ProcessService.class)).thenReturn(processService); |
||||
} |
||||
|
||||
@Ignore |
||||
@Test |
||||
public void test() throws Exception { |
||||
|
||||
TaskProps taskProps = new TaskProps(); |
||||
// processDefineId_processInstanceId_taskInstanceId
|
||||
taskProps.setExecutePath("/opt/soft/program/tmp/dolphinscheduler/exec/flow/5/36/2864/7657"); |
||||
taskProps.setTaskAppId("36_2864_7657"); |
||||
// set tenant -> task execute linux user
|
||||
taskProps.setTenantCode("hdfs"); |
||||
taskProps.setTaskStartTime(new Date()); |
||||
taskProps.setTaskTimeout(360000); |
||||
taskProps.setTaskInstanceId(7657); |
||||
|
||||
// TaskInstance taskInstance = processService.findTaskInstanceById(7657);
|
||||
//
|
||||
// TaskNode taskNode = JSON.parseObject(taskJson, TaskNode.class);
|
||||
// taskProps.setTaskParams(taskNode.getParams());
|
||||
//
|
||||
//
|
||||
// // custom logger
|
||||
// Logger taskLogger = LoggerFactory.getLogger(LoggerUtils.buildTaskId(LoggerUtils.TASK_LOGGER_INFO_PREFIX,
|
||||
// taskInstance.getProcessDefine().getCode(),
|
||||
// taskInstance.getProcessDefine().getVersion(),
|
||||
// taskInstance.getProcessInstanceId(),
|
||||
// taskInstance.getId()));
|
||||
//
|
||||
//
|
||||
// AbstractTask task = TaskManager.newTask(taskInstance.getTaskType(), taskProps, taskLogger);
|
||||
|
||||
AbstractTask task = null; |
||||
|
||||
logger.info("task info : {}", task); |
||||
|
||||
// job init
|
||||
task.init(); |
||||
|
||||
// job handle
|
||||
task.handle(); |
||||
ExecutionStatus status = ExecutionStatus.SUCCESS; |
||||
|
||||
if (task.getExitStatusCode() == Constants.EXIT_CODE_SUCCESS) { |
||||
status = ExecutionStatus.SUCCESS; |
||||
} else if (task.getExitStatusCode() == Constants.EXIT_CODE_KILL) { |
||||
status = ExecutionStatus.KILL; |
||||
} else { |
||||
status = ExecutionStatus.FAILURE; |
||||
} |
||||
|
||||
logger.info(status.toString()); |
||||
} |
||||
|
||||
@Test |
||||
public void testParseProcessOutput() { |
||||
Class<AbstractCommandExecutor> shellCommandExecutorClass = AbstractCommandExecutor.class; |
||||
try { |
||||
|
||||
Method method = shellCommandExecutorClass.getDeclaredMethod("parseProcessOutput", Process.class); |
||||
method.setAccessible(true); |
||||
Object[] arg1s = {new Process() { |
||||
@Override |
||||
public OutputStream getOutputStream() { |
||||
return new OutputStream() { |
||||
@Override |
||||
public void write(int b) throws IOException { |
||||
logger.info("unit test"); |
||||
} |
||||
}; |
||||
} |
||||
|
||||
@Override |
||||
public InputStream getInputStream() { |
||||
return new InputStream() { |
||||
@Override |
||||
public int read() throws IOException { |
||||
return 0; |
||||
} |
||||
}; |
||||
} |
||||
|
||||
@Override |
||||
public InputStream getErrorStream() { |
||||
return null; |
||||
} |
||||
|
||||
@Override |
||||
public int waitFor() throws InterruptedException { |
||||
return 0; |
||||
} |
||||
|
||||
@Override |
||||
public int exitValue() { |
||||
return 0; |
||||
} |
||||
|
||||
@Override |
||||
public void destroy() { |
||||
logger.info("unit test"); |
||||
} |
||||
} }; |
||||
method.invoke(new AbstractCommandExecutor(null, new TaskExecutionContext(), logger) { |
||||
@Override |
||||
protected String buildCommandFilePath() { |
||||
return null; |
||||
} |
||||
|
||||
@Override |
||||
protected String commandInterpreter() { |
||||
return null; |
||||
} |
||||
|
||||
@Override |
||||
protected void createCommandFileIfNotExists(String execCommand, String commandFile) throws IOException { |
||||
logger.info("unit test"); |
||||
} |
||||
}, arg1s); |
||||
} catch (Exception e) { |
||||
logger.error(e.getMessage()); |
||||
} |
||||
} |
||||
|
||||
@Test |
||||
public void testFindAppId() { |
||||
Class<AbstractCommandExecutor> shellCommandExecutorClass = AbstractCommandExecutor.class; |
||||
try { |
||||
|
||||
Method method = shellCommandExecutorClass.getDeclaredMethod("findAppId", new Class[]{String.class}); |
||||
method.setAccessible(true); |
||||
Object[] arg1s = {"11111"}; |
||||
String result = (String) method.invoke(new AbstractCommandExecutor(null, null, null) { |
||||
@Override |
||||
protected String buildCommandFilePath() { |
||||
return null; |
||||
} |
||||
|
||||
@Override |
||||
protected String commandInterpreter() { |
||||
return null; |
||||
} |
||||
|
||||
@Override |
||||
protected void createCommandFileIfNotExists(String execCommand, String commandFile) throws IOException { |
||||
logger.info("unit test"); |
||||
} |
||||
}, arg1s); |
||||
} catch (Exception e) { |
||||
logger.error(e.getMessage()); |
||||
} |
||||
} |
||||
|
||||
@Test |
||||
public void testConvertFile2List() { |
||||
Class<AbstractCommandExecutor> shellCommandExecutorClass = AbstractCommandExecutor.class; |
||||
try { |
||||
Method method = shellCommandExecutorClass.getDeclaredMethod("convertFile2List", String.class); |
||||
method.setAccessible(true); |
||||
Object[] arg1s = {"/opt/1.txt"}; |
||||
List<String> result = (List<String>) method.invoke(new AbstractCommandExecutor(null, null, null) { |
||||
@Override |
||||
protected String buildCommandFilePath() { |
||||
return null; |
||||
} |
||||
|
||||
@Override |
||||
protected String commandInterpreter() { |
||||
return null; |
||||
} |
||||
|
||||
@Override |
||||
protected void createCommandFileIfNotExists(String execCommand, String commandFile) throws IOException { |
||||
logger.info("unit test"); |
||||
} |
||||
}, arg1s); |
||||
Assert.assertTrue(true); |
||||
} catch (Exception e) { |
||||
logger.error(e.getMessage()); |
||||
} |
||||
} |
||||
} |
@ -1,144 +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.server.worker.sql; |
||||
|
||||
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.utils.LoggerUtils; |
||||
import org.apache.dolphinscheduler.dao.entity.TaskInstance; |
||||
import org.apache.dolphinscheduler.server.worker.task.AbstractTask; |
||||
import org.apache.dolphinscheduler.server.worker.task.TaskProps; |
||||
import org.apache.dolphinscheduler.service.bean.SpringApplicationContext; |
||||
import org.apache.dolphinscheduler.service.process.ProcessService; |
||||
|
||||
import java.util.Date; |
||||
|
||||
import org.junit.Before; |
||||
import org.junit.Ignore; |
||||
import org.junit.Test; |
||||
import org.slf4j.Logger; |
||||
import org.slf4j.LoggerFactory; |
||||
|
||||
/** |
||||
* python shell command executor test |
||||
*/ |
||||
@Ignore |
||||
public class SqlExecutorTest { |
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(SqlExecutorTest.class); |
||||
|
||||
private ProcessService processService = null; |
||||
|
||||
@Before |
||||
public void before() { |
||||
processService = SpringApplicationContext.getBean(ProcessService.class); |
||||
} |
||||
|
||||
@Test |
||||
public void test() throws Exception { |
||||
String nodeName = "mysql sql test"; |
||||
String taskAppId = "51_11282_263978"; |
||||
String tenantCode = "hdfs"; |
||||
int taskInstId = 7; |
||||
sharedTestSqlTask(nodeName, taskAppId, tenantCode, taskInstId); |
||||
} |
||||
|
||||
@Test |
||||
public void testClickhouse() throws Exception { |
||||
String nodeName = "ClickHouse sql test"; |
||||
String taskAppId = "1_11_20"; |
||||
String tenantCode = "default"; |
||||
int taskInstId = 20; |
||||
sharedTestSqlTask(nodeName, taskAppId, tenantCode, taskInstId); |
||||
} |
||||
|
||||
@Test |
||||
public void testOracle() throws Exception { |
||||
String nodeName = "oracle sql test"; |
||||
String taskAppId = "2_13_25"; |
||||
String tenantCode = "demo"; |
||||
int taskInstId = 25; |
||||
sharedTestSqlTask(nodeName, taskAppId, tenantCode, taskInstId); |
||||
} |
||||
|
||||
@Test |
||||
public void testSQLServer() throws Exception { |
||||
String nodeName = "SQL Server sql test"; |
||||
String taskAppId = "3_14_27"; |
||||
String tenantCode = "demo"; |
||||
int taskInstId = 27; |
||||
sharedTestSqlTask(nodeName, taskAppId, tenantCode, taskInstId); |
||||
} |
||||
|
||||
/** |
||||
* Basic test template for SQLTasks, mainly test different types of DBMS types |
||||
* |
||||
* @param nodeName node name for selected task |
||||
* @param taskAppId task app id |
||||
* @param tenantCode tenant code |
||||
* @param taskInstId task instance id |
||||
*/ |
||||
private void sharedTestSqlTask(String nodeName, String taskAppId, String tenantCode, int taskInstId) throws Exception { |
||||
TaskProps taskProps = new TaskProps(); |
||||
taskProps.setExecutePath(""); |
||||
// processDefineId_processInstanceId_taskInstanceId
|
||||
taskProps.setTaskAppId(taskAppId); |
||||
// set tenant -> task execute linux user
|
||||
taskProps.setTenantCode(tenantCode); |
||||
taskProps.setTaskStartTime(new Date()); |
||||
taskProps.setTaskTimeout(360000); |
||||
taskProps.setTaskInstanceId(taskInstId); |
||||
taskProps.setTaskName(nodeName); |
||||
taskProps.setCmdTypeIfComplement(CommandType.START_PROCESS); |
||||
|
||||
|
||||
TaskInstance taskInstance = processService.findTaskInstanceById(taskInstId); |
||||
|
||||
taskProps.setTaskParams(taskInstance.getTaskParams()); |
||||
|
||||
|
||||
// custom logger
|
||||
Logger taskLogger = LoggerFactory.getLogger(LoggerUtils.buildTaskId(LoggerUtils.TASK_LOGGER_INFO_PREFIX, |
||||
1L, |
||||
1, |
||||
taskInstance.getProcessInstanceId(), |
||||
taskInstance.getId())); |
||||
|
||||
//AbstractTask task = TaskManager.newTask(taskInstance.getTaskType(), taskProps, taskLogger);
|
||||
AbstractTask task = null; |
||||
|
||||
logger.info("task info : {}", task); |
||||
|
||||
// job init
|
||||
task.init(); |
||||
|
||||
// job handle
|
||||
task.handle(); |
||||
ExecutionStatus status = ExecutionStatus.SUCCESS; |
||||
|
||||
if (task.getExitStatusCode() == Constants.EXIT_CODE_SUCCESS) { |
||||
status = ExecutionStatus.SUCCESS; |
||||
} else if (task.getExitStatusCode() == Constants.EXIT_CODE_KILL) { |
||||
status = ExecutionStatus.KILL; |
||||
} else { |
||||
status = ExecutionStatus.FAILURE; |
||||
} |
||||
|
||||
logger.info(status.toString()); |
||||
} |
||||
} |
@ -1,58 +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.server.worker.task; |
||||
|
||||
import org.junit.Assert; |
||||
import org.junit.Test; |
||||
import org.slf4j.Logger; |
||||
import org.slf4j.LoggerFactory; |
||||
|
||||
public class PythonCommandExecutorTest { |
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(PythonCommandExecutorTest.class); |
||||
|
||||
@Test |
||||
public void testGetPythonHome() { |
||||
String path = System.getProperty("user.dir") + "/script/env/dolphinscheduler_env.sh"; |
||||
if (path.contains("dolphinscheduler-server/")) { |
||||
path = path.replace("dolphinscheduler-server/", ""); |
||||
} |
||||
String pythonHome = PythonCommandExecutor.getPythonHome(path); |
||||
logger.info(pythonHome); |
||||
Assert.assertNotNull(pythonHome); |
||||
} |
||||
|
||||
@Test |
||||
public void testGetPythonCommand() { |
||||
String pythonCommand = PythonCommandExecutor.getPythonCommand(null); |
||||
Assert.assertEquals(PythonCommandExecutor.PYTHON, pythonCommand); |
||||
pythonCommand = PythonCommandExecutor.getPythonCommand(""); |
||||
Assert.assertEquals(PythonCommandExecutor.PYTHON, pythonCommand); |
||||
pythonCommand = PythonCommandExecutor.getPythonCommand("/usr/bin/python"); |
||||
Assert.assertEquals("/usr/bin/python", pythonCommand); |
||||
pythonCommand = PythonCommandExecutor.getPythonCommand("/usr/local/bin/python2"); |
||||
Assert.assertEquals("/usr/local/bin/python2", pythonCommand); |
||||
pythonCommand = PythonCommandExecutor.getPythonCommand("/opt/python/bin/python3.8"); |
||||
Assert.assertEquals("/opt/python/bin/python3.8", pythonCommand); |
||||
pythonCommand = PythonCommandExecutor.getPythonCommand("/opt/soft/python"); |
||||
Assert.assertEquals("/opt/soft/python/bin/python", pythonCommand); |
||||
pythonCommand = PythonCommandExecutor.getPythonCommand("/opt/soft/python-3.8"); |
||||
Assert.assertEquals("/opt/soft/python-3.8/bin/python", pythonCommand); |
||||
} |
||||
|
||||
} |
@ -1,115 +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.server.worker.task; |
||||
|
||||
import static org.mockito.ArgumentMatchers.anyString; |
||||
|
||||
import org.apache.dolphinscheduler.common.enums.TaskType; |
||||
import org.apache.dolphinscheduler.server.entity.TaskExecutionContext; |
||||
import org.apache.dolphinscheduler.server.worker.task.shell.ShellTask; |
||||
import org.apache.dolphinscheduler.server.worker.task.shell.ShellTaskTest; |
||||
|
||||
import java.nio.file.Files; |
||||
import java.nio.file.Paths; |
||||
import java.util.Date; |
||||
import java.util.HashMap; |
||||
import java.util.Map; |
||||
|
||||
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; |
||||
import org.slf4j.Logger; |
||||
import org.slf4j.LoggerFactory; |
||||
|
||||
/** |
||||
* shell task return test. |
||||
*/ |
||||
@RunWith(PowerMockRunner.class) |
||||
@PrepareForTest({ShellTask.class}) |
||||
public class ShellTaskReturnTest { |
||||
private static final Logger logger = LoggerFactory.getLogger(ShellTaskTest.class); |
||||
|
||||
private ShellTask shellTask; |
||||
private ShellCommandExecutor shellCommandExecutor; |
||||
private TaskExecutionContext taskExecutionContext; |
||||
private CommandExecuteResult commandExecuteResult; |
||||
|
||||
@Before |
||||
public void before() throws Exception { |
||||
System.setProperty("log4j2.disable.jmx", Boolean.TRUE.toString()); |
||||
shellCommandExecutor = PowerMockito.mock(ShellCommandExecutor.class); |
||||
PowerMockito.whenNew(ShellCommandExecutor.class).withAnyArguments().thenReturn(shellCommandExecutor); |
||||
taskExecutionContext = new TaskExecutionContext(); |
||||
taskExecutionContext.setTaskInstanceId(1); |
||||
taskExecutionContext.setTaskName("kris test"); |
||||
taskExecutionContext.setTaskType(TaskType.SHELL.getDesc()); |
||||
taskExecutionContext.setHost("127.0.0.1:1234"); |
||||
taskExecutionContext.setExecutePath("/tmp"); |
||||
taskExecutionContext.setLogPath("/log"); |
||||
taskExecutionContext.setTaskJson( |
||||
"{\"conditionResult\":\"{\\\"successNode\\\":[\\\"\\\"]," |
||||
+ "\\\"failedNode\\\":[\\\"\\\"]}\",\"conditionsTask\":false," |
||||
+ "\"depList\":[],\"dependence\":\"{}\",\"forbidden\":false,\"id\":\"" |
||||
+ "tasks-16849\",\"maxRetryTimes\":0,\"name\":\"shell test 001\"," |
||||
+ "\"params\":\"{\\\"rawScript\\\":\\\"#!/bin/sh\\\\necho $[yyyy-MM-dd HH:mm:ss +3]\\\\necho \\\\\\\" ?? " |
||||
+ "${time1} \\\\\\\"\\\\necho \\\\\\\" ????? ${time2}\\\\\\\"\\\\n\\\"," |
||||
+ "\\\"localParams\\\":[{\\\"prop\\\":\\\"time1\\\",\\\"direct\\\":\\\"IN\\\",\\\"type\\\":" |
||||
+ "\\\"VARCHAR\\\",\\\"value\\\":\\\"$[yyyy-MM-dd HH:mm:ss]\\\"}," |
||||
+ "{\\\"prop\\\":\\\"time2\\\",\\\"direct\\\":\\\"IN\\\",\\\"type\\\":\\\"VARCHAR\\\",\\\"value\\\":\\\"${time_gb}\\\"}" |
||||
+ "],\\\"resourceList\\\":[]}\",\"preTasks\":\"[]\",\"retryInterval\":1," |
||||
+ "\"runFlag\":\"NORMAL\",\"taskInstancePriority\":\"MEDIUM\",\"taskTimeoutParameter\":" |
||||
+ "{\"enable\":false,\"interval\":0},\"timeout\":\"{\\\"enable\\\":false,\\\"strategy\\\":\\\"\\\"}\"," |
||||
+ "\"type\":\"SHELL\",\"workerGroup\":\"default\"}"); |
||||
taskExecutionContext.setProcessInstanceId(1); |
||||
taskExecutionContext.setGlobalParams("[{\"direct\":\"IN\",\"prop\":\"time_gb\",\"type\":\"VARCHAR\",\"value\":\"2020-12-16 17:18:33\"}]"); |
||||
taskExecutionContext.setExecutorId(1); |
||||
taskExecutionContext.setCmdTypeIfComplement(5); |
||||
taskExecutionContext.setTenantCode("roo"); |
||||
taskExecutionContext.setScheduleTime(new Date()); |
||||
taskExecutionContext.setQueue("default"); |
||||
taskExecutionContext.setTaskParams( |
||||
"{\"rawScript\":\"#!/bin/sh\\necho $[yyyy-MM-dd HH:mm:ss +3]\\necho \\\" ?? ${time1} \\\"\\necho \\\" ????? ${time2}\\\"\\n\",\"localParams\":" |
||||
+ |
||||
"[{\"prop\":\"time1\",\"direct\":\"OUT\",\"type\":\"VARCHAR\",\"value\":\"$[yyyy-MM-dd HH:mm:ss]\"},{\"prop\":\"time2\",\"direct\":\"IN\",\"type\":\"VARCHAR" |
||||
+ "\",\"value\":\"${time_gb}\"}],\"resourceList\":[]}"); |
||||
Map<String, String> definedParams = new HashMap<>(); |
||||
definedParams.put("time_gb", "2020-12-16 00:00:00"); |
||||
taskExecutionContext.setDefinedParams(definedParams); |
||||
PowerMockito.mockStatic(Files.class); |
||||
PowerMockito.when(Files.exists(Paths.get(anyString()))).thenReturn(true); |
||||
commandExecuteResult = new CommandExecuteResult(); |
||||
commandExecuteResult.setAppIds("appId"); |
||||
commandExecuteResult.setExitStatusCode(0); |
||||
commandExecuteResult.setProcessId(1); |
||||
} |
||||
|
||||
@Test |
||||
public void testShellReturnString() { |
||||
shellTask = new ShellTask(taskExecutionContext, logger); |
||||
shellTask.init(); |
||||
try { |
||||
PowerMockito.when(shellCommandExecutor.run(anyString())).thenReturn(commandExecuteResult); |
||||
} catch (Exception e) { |
||||
e.printStackTrace(); |
||||
} |
||||
} |
||||
|
||||
} |
@ -1,192 +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.server.worker.task; |
||||
|
||||
import org.apache.dolphinscheduler.common.enums.TaskType; |
||||
import org.apache.dolphinscheduler.common.process.Property; |
||||
import org.apache.dolphinscheduler.common.task.sql.SqlParameters; |
||||
import org.apache.dolphinscheduler.common.utils.JSONUtils; |
||||
import org.apache.dolphinscheduler.common.utils.LoggerUtils; |
||||
import org.apache.dolphinscheduler.server.entity.SQLTaskExecutionContext; |
||||
import org.apache.dolphinscheduler.server.entity.TaskExecutionContext; |
||||
import org.apache.dolphinscheduler.server.worker.cache.impl.TaskExecutionContextCacheManagerImpl; |
||||
import org.apache.dolphinscheduler.server.worker.task.shell.ShellTask; |
||||
import org.apache.dolphinscheduler.server.worker.task.sql.SqlTask; |
||||
import org.apache.dolphinscheduler.service.alert.AlertClientService; |
||||
import org.apache.dolphinscheduler.service.bean.SpringApplicationContext; |
||||
|
||||
import java.util.Date; |
||||
import java.util.HashMap; |
||||
import java.util.List; |
||||
import java.util.Map; |
||||
|
||||
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; |
||||
import org.slf4j.Logger; |
||||
import org.slf4j.LoggerFactory; |
||||
|
||||
@RunWith(PowerMockRunner.class) |
||||
@PrepareForTest({SpringApplicationContext.class}) |
||||
public class TaskManagerTest { |
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(TaskManagerTest.class); |
||||
|
||||
private TaskExecutionContext taskExecutionContext; |
||||
|
||||
private Logger taskLogger; |
||||
|
||||
private TaskExecutionContextCacheManagerImpl taskExecutionContextCacheManager; |
||||
|
||||
private AlertClientService alertClientService; |
||||
|
||||
@Before |
||||
public void before() { |
||||
// init task execution context, logger
|
||||
taskExecutionContext = new TaskExecutionContext(); |
||||
taskExecutionContext.setProcessId(12345); |
||||
taskExecutionContext.setProcessInstanceId(1); |
||||
taskExecutionContext.setTaskInstanceId(1); |
||||
taskExecutionContext.setProcessDefineCode(1L); |
||||
taskExecutionContext.setProcessDefineVersion(1); |
||||
taskExecutionContext.setTaskType(TaskType.SHELL.getDesc()); |
||||
taskExecutionContext.setFirstSubmitTime(new Date()); |
||||
taskExecutionContext.setDelayTime(0); |
||||
taskExecutionContext.setLogPath("/tmp/test.log"); |
||||
taskExecutionContext.setHost("localhost"); |
||||
taskExecutionContext.setExecutePath("/tmp/dolphinscheduler/exec/process/1/2/3/4"); |
||||
|
||||
taskLogger = LoggerFactory.getLogger(LoggerUtils.buildTaskId( |
||||
LoggerUtils.TASK_LOGGER_INFO_PREFIX, |
||||
taskExecutionContext.getProcessDefineCode(), |
||||
taskExecutionContext.getProcessDefineVersion(), |
||||
taskExecutionContext.getProcessInstanceId(), |
||||
taskExecutionContext.getTaskInstanceId() |
||||
)); |
||||
|
||||
taskExecutionContextCacheManager = new TaskExecutionContextCacheManagerImpl(); |
||||
taskExecutionContextCacheManager.cacheTaskExecutionContext(taskExecutionContext); |
||||
|
||||
PowerMockito.mockStatic(SpringApplicationContext.class); |
||||
PowerMockito.when(SpringApplicationContext.getBean(TaskExecutionContextCacheManagerImpl.class)) |
||||
.thenReturn(taskExecutionContextCacheManager); |
||||
|
||||
alertClientService = PowerMockito.mock(AlertClientService.class); |
||||
} |
||||
|
||||
@Test |
||||
public void testNewTask() { |
||||
|
||||
taskExecutionContext.setTaskType(TaskType.SHELL.getDesc()); |
||||
Assert.assertNotNull(TaskManager.newTask(taskExecutionContext, taskLogger, alertClientService)); |
||||
taskExecutionContext.setTaskType(TaskType.WATERDROP.getDesc()); |
||||
Assert.assertNotNull(TaskManager.newTask(taskExecutionContext, taskLogger, alertClientService)); |
||||
taskExecutionContext.setTaskType(TaskType.HTTP.getDesc()); |
||||
Assert.assertNotNull(TaskManager.newTask(taskExecutionContext, taskLogger, alertClientService)); |
||||
taskExecutionContext.setTaskType(TaskType.MR.getDesc()); |
||||
Assert.assertNotNull(TaskManager.newTask(taskExecutionContext, taskLogger, alertClientService)); |
||||
taskExecutionContext.setTaskType(TaskType.SPARK.getDesc()); |
||||
Assert.assertNotNull(TaskManager.newTask(taskExecutionContext, taskLogger, alertClientService)); |
||||
taskExecutionContext.setTaskType(TaskType.FLINK.getDesc()); |
||||
Assert.assertNotNull(TaskManager.newTask(taskExecutionContext, taskLogger, alertClientService)); |
||||
taskExecutionContext.setTaskType(TaskType.PYTHON.getDesc()); |
||||
Assert.assertNotNull(TaskManager.newTask(taskExecutionContext, taskLogger, alertClientService)); |
||||
taskExecutionContext.setTaskType(TaskType.DATAX.getDesc()); |
||||
Assert.assertNotNull(TaskManager.newTask(taskExecutionContext, taskLogger, alertClientService)); |
||||
taskExecutionContext.setTaskType(TaskType.SQOOP.getDesc()); |
||||
Assert.assertNotNull(TaskManager.newTask(taskExecutionContext, taskLogger, alertClientService)); |
||||
|
||||
} |
||||
|
||||
@Test(expected = IllegalArgumentException.class) |
||||
public void testNewTaskIsNull() { |
||||
taskExecutionContext.setTaskType(null); |
||||
TaskManager.newTask(taskExecutionContext, taskLogger, alertClientService); |
||||
} |
||||
|
||||
@Test(expected = IllegalArgumentException.class) |
||||
public void testNewTaskIsNotExists() { |
||||
taskExecutionContext.setTaskType("ttt"); |
||||
TaskManager.newTask(taskExecutionContext, taskLogger, alertClientService); |
||||
} |
||||
|
||||
@Test |
||||
public void testShellTaskReturnString() { |
||||
taskExecutionContext.setTaskInstanceId(1); |
||||
taskExecutionContext.setTaskName("kris test"); |
||||
taskExecutionContext.setTaskType(TaskType.SHELL.getDesc()); |
||||
taskExecutionContext.setHost("127.0.0.1:1234"); |
||||
taskExecutionContext.setExecutePath("/tmp"); |
||||
taskExecutionContext.setLogPath("/log"); |
||||
taskExecutionContext.setTaskJson( |
||||
"{\"conditionResult\":\"{\\\"successNode\\\":[\\\"\\\"],\\\"failedNode\\\":[\\\"\\\"]}\"," |
||||
+ "\"conditionsTask\":false,\"depList\":[],\"dependence\":\"{}\",\"forbidden\":false,\"id\":\"" |
||||
+ "tasks-16849\",\"maxRetryTimes\":0,\"name\":\"shell test 001\"," |
||||
+ "\"params\":\"{\\\"rawScript\\\":\\\"#!/bin/sh\\\\necho $[yyyy-MM-dd HH:mm:ss +3]\\\\necho \\\\\\\" ?? " |
||||
+ "${time1} \\\\\\\"\\\\necho \\\\\\\" ????? ${time2}\\\\\\\"\\\\n\\\"," |
||||
+ "\\\"localParams\\\":[{\\\"prop\\\":\\\"time1\\\",\\\"direct\\\":\\\"OUT\\\",\\\"type\\\":" |
||||
+ "\\\"VARCHAR\\\",\\\"value\\\":\\\"$[yyyy-MM-dd HH:mm:ss]\\\"}," |
||||
+ "{\\\"prop\\\":\\\"time2\\\",\\\"direct\\\":\\\"IN\\\",\\\"type\\\":\\\"VARCHAR\\\",\\\"value\\\":\\\"${time_gb}\\\"}" |
||||
+ "],\\\"resourceList\\\":[]}\",\"preTasks\":\"[]\",\"retryInterval\":1,\"runFlag\":\"NORMAL\",\"taskInstancePriority\":\"MEDIUM\",\"taskTimeoutParameter\":" |
||||
+ "{\"enable\":false,\"interval\":0},\"timeout\":\"{\\\"enable\\\":false,\\\"strategy\\\":\\\"\\\"}\",\"type\":\"SHELL\",\"workerGroup\":\"default\"}"); |
||||
taskExecutionContext.setProcessInstanceId(1); |
||||
taskExecutionContext.setGlobalParams("[{\"direct\":\"IN\",\"prop\":\"time_gb\",\"type\":\"VARCHAR\",\"value\":\"2020-12-16 17:18:33\"}]"); |
||||
taskExecutionContext.setExecutorId(1); |
||||
taskExecutionContext.setCmdTypeIfComplement(5); |
||||
taskExecutionContext.setTenantCode("roo"); |
||||
taskExecutionContext.setScheduleTime(new Date()); |
||||
taskExecutionContext.setQueue("default"); |
||||
taskExecutionContext.setTaskParams( |
||||
"{\"rawScript\":\"#!/bin/sh\\necho $[yyyy-MM-dd HH:mm:ss +3]\\necho \\\" ?? ${time1} \\\"\\necho \\\" ????? ${time2}\\\"\\n\",\"localParams\":" |
||||
+ |
||||
"[{\"prop\":\"time1\",\"direct\":\"OUT\",\"type\":\"VARCHAR\",\"value\":\"$[yyyy-MM-dd HH:mm:ss]\"},{\"prop\":\"time2\",\"direct\":\"IN\",\"type\":\"VARCHAR" |
||||
+ "\",\"value\":\"${time_gb}\"}],\"resourceList\":[]}"); |
||||
Map<String, String> definedParams = new HashMap<>(); |
||||
definedParams.put("time_gb", "2020-12-16 00:00:00"); |
||||
taskExecutionContext.setDefinedParams(definedParams); |
||||
ShellTask shellTask = (ShellTask) TaskManager.newTask(taskExecutionContext, taskLogger, alertClientService); |
||||
} |
||||
|
||||
@Test |
||||
public void testSqlTaskReturnString() { |
||||
String params = "{\"user\":\"root\",\"password\":\"123456\",\"address\":\"jdbc:mysql://127.0.0.1:3306\"," |
||||
+ "\"database\":\"test\",\"jdbcUrl\":\"jdbc:mysql://127.0.0.1:3306/test\"}"; |
||||
taskExecutionContext = new TaskExecutionContext(); |
||||
taskExecutionContext.setTaskParams("{\"localParams\":[{\"prop\":\"ret\", \"direct\":\"OUT\", \"type\":\"VARCHAR\", \"value\":\"\"}]," |
||||
+ "\"type\":\"POSTGRESQL\",\"datasource\":1,\"sql\":\"insert into tb_1 values('1','2')\"," |
||||
+ "\"sqlType\":1}"); |
||||
taskExecutionContext.setExecutePath("/tmp"); |
||||
taskExecutionContext.setTaskAppId("1"); |
||||
taskExecutionContext.setTenantCode("root"); |
||||
taskExecutionContext.setStartTime(new Date()); |
||||
taskExecutionContext.setTaskTimeout(10000); |
||||
taskExecutionContext.setLogPath("/tmp/dx"); |
||||
|
||||
SQLTaskExecutionContext sqlTaskExecutionContext = new SQLTaskExecutionContext(); |
||||
sqlTaskExecutionContext.setConnectionParams(params); |
||||
taskExecutionContext.setSqlTaskExecutionContext(sqlTaskExecutionContext); |
||||
SqlTask sqlTask = new SqlTask(taskExecutionContext, logger, null); |
||||
SqlParameters sqlParameters = JSONUtils.parseObject(taskExecutionContext.getTaskParams(), SqlParameters.class); |
||||
List<Property> properties = sqlParameters.getLocalParams(); |
||||
sqlTask.setNonQuerySqlReturn("sql return", properties); |
||||
} |
||||
} |
@ -1,77 +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.server.worker.task; |
||||
|
||||
import static org.junit.Assert.assertNotNull; |
||||
|
||||
import org.apache.dolphinscheduler.common.enums.DataType; |
||||
import org.apache.dolphinscheduler.common.enums.Direct; |
||||
import org.apache.dolphinscheduler.common.process.Property; |
||||
import org.apache.dolphinscheduler.common.task.shell.ShellParameters; |
||||
import org.apache.dolphinscheduler.common.task.sql.SqlParameters; |
||||
|
||||
import java.util.ArrayList; |
||||
import java.util.List; |
||||
|
||||
import org.junit.Test; |
||||
import org.junit.runner.RunWith; |
||||
import org.powermock.modules.junit4.PowerMockRunner; |
||||
import org.slf4j.Logger; |
||||
import org.slf4j.LoggerFactory; |
||||
|
||||
/** |
||||
* shell task return test. |
||||
*/ |
||||
@RunWith(PowerMockRunner.class) |
||||
public class TaskParamsTest { |
||||
private static final Logger logger = LoggerFactory.getLogger(TaskParamsTest.class); |
||||
|
||||
@Test |
||||
public void testDealOutParam() { |
||||
List<Property> properties = new ArrayList<>(); |
||||
Property property = new Property(); |
||||
property.setProp("test1"); |
||||
property.setDirect(Direct.OUT); |
||||
property.setType(DataType.VARCHAR); |
||||
property.setValue("test1"); |
||||
properties.add(property); |
||||
|
||||
ShellParameters shellParameters = new ShellParameters(); |
||||
String resultShell = "key1=value1$VarPoolkey2=value2"; |
||||
shellParameters.varPool = new ArrayList<>(); |
||||
shellParameters.setLocalParams(properties); |
||||
shellParameters.dealOutParam(resultShell); |
||||
assertNotNull(shellParameters.getVarPool().get(0)); |
||||
|
||||
String sqlResult = "[{\"id\":6,\"test1\":\"6\"},{\"id\":70002,\"test1\":\"+1\"}]"; |
||||
SqlParameters sqlParameters = new SqlParameters(); |
||||
String sqlResult1 = "[{\"id\":6,\"test1\":\"6\"}]"; |
||||
sqlParameters.setLocalParams(properties); |
||||
sqlParameters.varPool = new ArrayList<>(); |
||||
sqlParameters.dealOutParam(sqlResult1); |
||||
assertNotNull(sqlParameters.getVarPool().get(0)); |
||||
|
||||
property.setType(DataType.LIST); |
||||
properties.clear(); |
||||
properties.add(property); |
||||
sqlParameters.setLocalParams(properties); |
||||
sqlParameters.dealOutParam(sqlResult); |
||||
assertNotNull(sqlParameters.getVarPool().get(0)); |
||||
} |
||||
|
||||
} |
@ -1,493 +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.server.worker.task.datax; |
||||
|
||||
import static org.apache.dolphinscheduler.common.enums.CommandType.START_PROCESS; |
||||
|
||||
import org.apache.dolphinscheduler.common.datasource.BaseConnectionParam; |
||||
import org.apache.dolphinscheduler.common.datasource.DatasourceUtil; |
||||
import org.apache.dolphinscheduler.common.enums.DbType; |
||||
import org.apache.dolphinscheduler.common.task.datax.DataxParameters; |
||||
import org.apache.dolphinscheduler.common.utils.JSONUtils; |
||||
import org.apache.dolphinscheduler.dao.entity.DataSource; |
||||
import org.apache.dolphinscheduler.dao.entity.ProcessInstance; |
||||
import org.apache.dolphinscheduler.server.entity.DataxTaskExecutionContext; |
||||
import org.apache.dolphinscheduler.server.entity.TaskExecutionContext; |
||||
import org.apache.dolphinscheduler.server.utils.DataxUtils; |
||||
import org.apache.dolphinscheduler.server.worker.task.ShellCommandExecutor; |
||||
import org.apache.dolphinscheduler.server.worker.task.TaskProps; |
||||
import org.apache.dolphinscheduler.service.bean.SpringApplicationContext; |
||||
import org.apache.dolphinscheduler.service.process.ProcessService; |
||||
|
||||
import java.lang.reflect.Method; |
||||
import java.util.Arrays; |
||||
import java.util.Date; |
||||
import java.util.List; |
||||
import java.util.UUID; |
||||
|
||||
import org.junit.After; |
||||
import org.junit.Assert; |
||||
import org.junit.Before; |
||||
import org.junit.Ignore; |
||||
import org.junit.Test; |
||||
import org.mockito.Mockito; |
||||
import org.powermock.api.mockito.PowerMockito; |
||||
import org.slf4j.Logger; |
||||
import org.slf4j.LoggerFactory; |
||||
import org.springframework.context.ApplicationContext; |
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode; |
||||
import com.fasterxml.jackson.databind.node.ObjectNode; |
||||
|
||||
/** |
||||
* DataxTask Tester. |
||||
*/ |
||||
public class DataxTaskTest { |
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(DataxTaskTest.class); |
||||
|
||||
private static final String CONNECTION_PARAMS = " {\n" |
||||
+ " \"user\":\"root\",\n" |
||||
+ " \"password\":\"123456\",\n" |
||||
+ " \"address\":\"jdbc:mysql://127.0.0.1:3306\",\n" |
||||
+ " \"database\":\"test\",\n" |
||||
+ " \"jdbcUrl\":\"jdbc:mysql://127.0.0.1:3306/test\"\n" |
||||
+ "}"; |
||||
|
||||
private DataxTask dataxTask; |
||||
|
||||
private ProcessService processService; |
||||
|
||||
private ShellCommandExecutor shellCommandExecutor; |
||||
|
||||
private ApplicationContext applicationContext; |
||||
|
||||
private TaskExecutionContext taskExecutionContext; |
||||
private final TaskProps props = new TaskProps(); |
||||
|
||||
@Before |
||||
public void before() |
||||
throws Exception { |
||||
setTaskParems(0); |
||||
} |
||||
|
||||
private void setTaskParems(Integer customConfig) { |
||||
|
||||
processService = Mockito.mock(ProcessService.class); |
||||
shellCommandExecutor = Mockito.mock(ShellCommandExecutor.class); |
||||
|
||||
applicationContext = Mockito.mock(ApplicationContext.class); |
||||
SpringApplicationContext springApplicationContext = new SpringApplicationContext(); |
||||
springApplicationContext.setApplicationContext(applicationContext); |
||||
Mockito.when(applicationContext.getBean(ProcessService.class)).thenReturn(processService); |
||||
|
||||
TaskProps props = new TaskProps(); |
||||
props.setExecutePath("/tmp"); |
||||
props.setTaskAppId(String.valueOf(System.currentTimeMillis())); |
||||
props.setTaskInstanceId(1); |
||||
props.setTenantCode("1"); |
||||
props.setEnvFile(".dolphinscheduler_env.sh"); |
||||
props.setTaskStartTime(new Date()); |
||||
props.setTaskTimeout(0); |
||||
if (customConfig == 1) { |
||||
props.setTaskParams( |
||||
"{\n" |
||||
+ " \"customConfig\":1,\n" |
||||
+ " \"localParams\":[\n" |
||||
+ " {\n" |
||||
+ " \"prop\":\"test\",\n" |
||||
+ " \"value\":\"38294729\"\n" |
||||
+ " }\n" |
||||
+ " ],\n" |
||||
+ " \"json\":\"" |
||||
+ "{\"job\":{\"setting\":{\"speed\":{\"byte\":1048576},\"errorLimit\":{\"record\":0,\"percentage\":0.02}},\"content\":[" |
||||
+ "{\"reader\":{\"name\":\"rdbmsreader\",\"parameter\":{\"username\":\"xxx\",\"password\":\"${test}\",\"column\":[\"id\",\"name\"],\"splitPk\":\"pk\",\"" |
||||
+ "connection\":[{\"querySql\":[\"SELECT * from dual\"],\"jdbcUrl\":[\"jdbc:dm://ip:port/database\"]}],\"fetchSize\":1024,\"where\":\"1 = 1\"}},\"" |
||||
+ "writer\":{\"name\":\"streamwriter\",\"parameter\":{\"print\":true}}}]}}\"\n" |
||||
+ "}"); |
||||
|
||||
} else { |
||||
props.setTaskParams( |
||||
"{\n" |
||||
+ " \"customConfig\":0,\n" |
||||
+ " \"targetTable\":\"test\",\n" |
||||
+ " \"postStatements\":[\n" |
||||
+ " \"delete from test\"\n" |
||||
+ " ],\n" |
||||
+ " \"jobSpeedByte\":0,\n" |
||||
+ " \"jobSpeedRecord\":1000,\n" |
||||
+ " \"dtType\":\"MYSQL\",\n" |
||||
+ " \"dataSource\":1,\n" |
||||
+ " \"dsType\":\"MYSQL\",\n" |
||||
+ " \"dataTarget\":2,\n" |
||||
+ " \"sql\":\"select 1 as test from dual\",\n" |
||||
+ " \"preStatements\":[\n" |
||||
+ " \"delete from test\"\n" |
||||
+ " ]\n" |
||||
+ "}"); |
||||
} |
||||
|
||||
taskExecutionContext = Mockito.mock(TaskExecutionContext.class); |
||||
Mockito.when(taskExecutionContext.getTaskParams()).thenReturn(props.getTaskParams()); |
||||
Mockito.when(taskExecutionContext.getExecutePath()).thenReturn("/tmp"); |
||||
Mockito.when(taskExecutionContext.getTaskAppId()).thenReturn(UUID.randomUUID().toString()); |
||||
Mockito.when(taskExecutionContext.getTenantCode()).thenReturn("root"); |
||||
Mockito.when(taskExecutionContext.getStartTime()).thenReturn(new Date()); |
||||
Mockito.when(taskExecutionContext.getTaskTimeout()).thenReturn(10000); |
||||
Mockito.when(taskExecutionContext.getLogPath()).thenReturn("/tmp/dx"); |
||||
|
||||
DataxTaskExecutionContext dataxTaskExecutionContext = new DataxTaskExecutionContext(); |
||||
dataxTaskExecutionContext.setSourcetype(0); |
||||
dataxTaskExecutionContext.setTargetType(0); |
||||
dataxTaskExecutionContext.setSourceConnectionParams(CONNECTION_PARAMS); |
||||
dataxTaskExecutionContext.setTargetConnectionParams(CONNECTION_PARAMS); |
||||
Mockito.when(taskExecutionContext.getDataxTaskExecutionContext()).thenReturn(dataxTaskExecutionContext); |
||||
|
||||
dataxTask = PowerMockito.spy(new DataxTask(taskExecutionContext, logger)); |
||||
dataxTask.init(); |
||||
props.setCmdTypeIfComplement(START_PROCESS); |
||||
|
||||
Mockito.when(processService.findDataSourceById(1)).thenReturn(getDataSource()); |
||||
Mockito.when(processService.findDataSourceById(2)).thenReturn(getDataSource()); |
||||
Mockito.when(processService.findProcessInstanceByTaskId(1)).thenReturn(getProcessInstance()); |
||||
|
||||
String fileName = String.format("%s/%s_node.sh", props.getExecutePath(), props.getTaskAppId()); |
||||
try { |
||||
Mockito.when(shellCommandExecutor.run(fileName)).thenReturn(null); |
||||
} catch (Exception e) { |
||||
e.printStackTrace(); |
||||
} |
||||
|
||||
dataxTask = PowerMockito.spy(new DataxTask(taskExecutionContext, logger)); |
||||
dataxTask.init(); |
||||
} |
||||
|
||||
private DataSource getDataSource() { |
||||
DataSource dataSource = new DataSource(); |
||||
dataSource.setType(DbType.MYSQL); |
||||
dataSource.setConnectionParams(CONNECTION_PARAMS); |
||||
dataSource.setUserId(1); |
||||
return dataSource; |
||||
} |
||||
|
||||
private ProcessInstance getProcessInstance() { |
||||
ProcessInstance processInstance = new ProcessInstance(); |
||||
processInstance.setCommandType(START_PROCESS); |
||||
processInstance.setScheduleTime(new Date()); |
||||
return processInstance; |
||||
} |
||||
|
||||
@After |
||||
public void after() |
||||
throws Exception { |
||||
} |
||||
|
||||
/** |
||||
* Method: DataxTask() |
||||
*/ |
||||
@Test |
||||
public void testDataxTask() |
||||
throws Exception { |
||||
TaskProps props = new TaskProps(); |
||||
props.setExecutePath("/tmp"); |
||||
props.setTaskAppId(String.valueOf(System.currentTimeMillis())); |
||||
props.setTaskInstanceId(1); |
||||
props.setTenantCode("1"); |
||||
Assert.assertNotNull(new DataxTask(null, logger)); |
||||
} |
||||
|
||||
/** |
||||
* Method: init |
||||
*/ |
||||
@Test |
||||
public void testInit() |
||||
throws Exception { |
||||
try { |
||||
dataxTask.init(); |
||||
} catch (Exception e) { |
||||
Assert.fail(e.getMessage()); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Method: handle() |
||||
*/ |
||||
@Test |
||||
public void testHandle() |
||||
throws Exception { |
||||
} |
||||
|
||||
/** |
||||
* Method: cancelApplication() |
||||
*/ |
||||
@Test |
||||
public void testCancelApplication() |
||||
throws Exception { |
||||
try { |
||||
dataxTask.cancelApplication(true); |
||||
} catch (Exception e) { |
||||
Assert.fail(e.getMessage()); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Method: parsingSqlColumnNames(DbType dsType, DbType dtType, BaseDataSource |
||||
* dataSourceCfg, String sql) |
||||
*/ |
||||
@Test |
||||
public void testParsingSqlColumnNames() |
||||
throws Exception { |
||||
try { |
||||
BaseConnectionParam dataSource = (BaseConnectionParam) DatasourceUtil.buildConnectionParams( |
||||
getDataSource().getType(), |
||||
getDataSource().getConnectionParams()); |
||||
|
||||
Method method = DataxTask.class.getDeclaredMethod("parsingSqlColumnNames", DbType.class, DbType.class, BaseConnectionParam.class, String.class); |
||||
method.setAccessible(true); |
||||
String[] columns = (String[]) method.invoke(dataxTask, DbType.MYSQL, DbType.MYSQL, dataSource, "select 1 as a, 2 as `table` from dual"); |
||||
|
||||
Assert.assertNotNull(columns); |
||||
|
||||
Assert.assertTrue(columns.length == 2); |
||||
|
||||
Assert.assertEquals("[`a`, `table`]", Arrays.toString(columns)); |
||||
} catch (Exception e) { |
||||
Assert.fail(e.getMessage()); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Method: tryGrammaticalParsingSqlColumnNames(DbType dbType, String sql) |
||||
*/ |
||||
@Test |
||||
public void testTryGrammaticalAnalysisSqlColumnNames() |
||||
throws Exception { |
||||
try { |
||||
Method method = DataxTask.class.getDeclaredMethod("tryGrammaticalAnalysisSqlColumnNames", DbType.class, String.class); |
||||
method.setAccessible(true); |
||||
String[] columns = (String[]) method.invoke(dataxTask, DbType.MYSQL, "select t1.a, t1.b from test t1 union all select a, t2.b from (select a, b from test) t2"); |
||||
|
||||
Assert.assertNotNull(columns); |
||||
|
||||
Assert.assertTrue(columns.length == 2); |
||||
|
||||
Assert.assertEquals("[a, b]", Arrays.toString(columns)); |
||||
} catch (Exception e) { |
||||
Assert.fail(e.getMessage()); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Method: tryExecuteSqlResolveColumnNames(BaseDataSource baseDataSource, |
||||
* String sql) |
||||
*/ |
||||
@Test |
||||
public void testTryExecuteSqlResolveColumnNames() |
||||
throws Exception { |
||||
// TODO: Test goes here...
|
||||
} |
||||
|
||||
/** |
||||
* Method: buildDataxJsonFile() |
||||
*/ |
||||
@Test |
||||
@Ignore("method not found") |
||||
public void testBuildDataxJsonFile() |
||||
throws Exception { |
||||
|
||||
try { |
||||
setTaskParems(1); |
||||
Method method = DataxTask.class.getDeclaredMethod("buildDataxJsonFile"); |
||||
method.setAccessible(true); |
||||
String filePath = (String) method.invoke(dataxTask, null); |
||||
Assert.assertNotNull(filePath); |
||||
} catch (Exception e) { |
||||
Assert.fail(e.getMessage()); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Method: buildDataxJsonFile() |
||||
*/ |
||||
@Test |
||||
@Ignore("method not found") |
||||
public void testBuildDataxJsonFile0() |
||||
throws Exception { |
||||
try { |
||||
setTaskParems(0); |
||||
Method method = DataxTask.class.getDeclaredMethod("buildDataxJsonFile"); |
||||
method.setAccessible(true); |
||||
String filePath = (String) method.invoke(dataxTask, null); |
||||
Assert.assertNotNull(filePath); |
||||
} catch (Exception e) { |
||||
Assert.fail(e.getMessage()); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Method: buildDataxJobContentJson() |
||||
*/ |
||||
@Test |
||||
public void testBuildDataxJobContentJson() |
||||
throws Exception { |
||||
try { |
||||
Method method = DataxTask.class.getDeclaredMethod("buildDataxJobContentJson"); |
||||
method.setAccessible(true); |
||||
List<ObjectNode> contentList = (List<ObjectNode>) method.invoke(dataxTask, null); |
||||
Assert.assertNotNull(contentList); |
||||
|
||||
ObjectNode content = contentList.get(0); |
||||
JsonNode reader = JSONUtils.parseObject(content.path("reader").toString()); |
||||
Assert.assertNotNull(reader); |
||||
Assert.assertEquals("{\"name\":\"mysqlreader\",\"parameter\":{\"username\":\"root\"," |
||||
+ "\"password\":\"123456\",\"connection\":[{\"querySql\":[\"select 1 as test from dual\"]," |
||||
+ "\"jdbcUrl\":[\"jdbc:mysql://127.0.0.1:3306/test?allowLoadLocalInfile=false" |
||||
+ "&autoDeserialize=false&allowLocalInfile=false&allowUrlInLocalInfile=false\"]}]}}", |
||||
reader.toString()); |
||||
|
||||
String readerPluginName = reader.path("name").asText(); |
||||
Assert.assertEquals(DataxUtils.DATAX_READER_PLUGIN_MYSQL, readerPluginName); |
||||
|
||||
JsonNode writer = JSONUtils.parseObject(content.path("writer").toString()); |
||||
Assert.assertNotNull(writer); |
||||
Assert.assertEquals("{\"name\":\"mysqlwriter\",\"parameter\":{\"username\":\"root\"," |
||||
+ "\"password\":\"123456\",\"column\":[\"`test`\"],\"connection\":[{\"table\":[\"test\"]," |
||||
+ "\"jdbcUrl\":\"jdbc:mysql://127.0.0.1:3306/test?allowLoadLocalInfile=false&" |
||||
+ "autoDeserialize=false&allowLocalInfile=false&allowUrlInLocalInfile=false\"}]," |
||||
+ "\"preSql\":[\"delete from test\"],\"postSql\":[\"delete from test\"]}}", |
||||
writer.toString()); |
||||
|
||||
String writerPluginName = writer.path("name").asText(); |
||||
Assert.assertEquals(DataxUtils.DATAX_WRITER_PLUGIN_MYSQL, writerPluginName); |
||||
|
||||
} catch (Exception e) { |
||||
Assert.fail(e.getMessage()); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Method: buildDataxJobSettingJson() |
||||
*/ |
||||
@Test |
||||
public void testBuildDataxJobSettingJson() |
||||
throws Exception { |
||||
try { |
||||
Method method = DataxTask.class.getDeclaredMethod("buildDataxJobSettingJson"); |
||||
method.setAccessible(true); |
||||
JsonNode setting = (JsonNode) method.invoke(dataxTask, null); |
||||
Assert.assertNotNull(setting); |
||||
Assert.assertEquals("{\"channel\":1,\"record\":1000}", setting.get("speed").toString()); |
||||
Assert.assertEquals("{\"record\":0,\"percentage\":0}", setting.get("errorLimit").toString()); |
||||
} catch (Exception e) { |
||||
Assert.fail(e.getMessage()); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Method: buildDataxCoreJson() |
||||
*/ |
||||
@Test |
||||
public void testBuildDataxCoreJson() |
||||
throws Exception { |
||||
try { |
||||
Method method = DataxTask.class.getDeclaredMethod("buildDataxCoreJson"); |
||||
method.setAccessible(true); |
||||
ObjectNode coreConfig = (ObjectNode) method.invoke(dataxTask, null); |
||||
Assert.assertNotNull(coreConfig); |
||||
Assert.assertNotNull(coreConfig.get("transport")); |
||||
} catch (Exception e) { |
||||
Assert.fail(e.getMessage()); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Method: buildShellCommandFile(String jobConfigFilePath) |
||||
*/ |
||||
@Test |
||||
@Ignore("method not found") |
||||
public void testBuildShellCommandFile() |
||||
throws Exception { |
||||
try { |
||||
Method method = DataxTask.class.getDeclaredMethod("buildShellCommandFile", String.class); |
||||
method.setAccessible(true); |
||||
Assert.assertNotNull(method.invoke(dataxTask, "test.json")); |
||||
} catch (Exception e) { |
||||
Assert.fail(e.getMessage()); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Method: getParameters |
||||
*/ |
||||
@Test |
||||
public void testGetParameters() |
||||
throws Exception { |
||||
Assert.assertTrue(dataxTask.getParameters() != null); |
||||
} |
||||
|
||||
/** |
||||
* Method: notNull(Object obj, String message) |
||||
*/ |
||||
@Test |
||||
public void testNotNull() |
||||
throws Exception { |
||||
try { |
||||
Method method = DataxTask.class.getDeclaredMethod("notNull", Object.class, String.class); |
||||
method.setAccessible(true); |
||||
method.invoke(dataxTask, "abc", "test throw RuntimeException"); |
||||
} catch (Exception e) { |
||||
Assert.fail(e.getMessage()); |
||||
} |
||||
} |
||||
|
||||
@Test |
||||
public void testGetPythonCommand() { |
||||
String pythonCommand = dataxTask.getPythonCommand(); |
||||
Assert.assertEquals("python2.7", pythonCommand); |
||||
pythonCommand = dataxTask.getPythonCommand(""); |
||||
Assert.assertEquals("python2.7", pythonCommand); |
||||
pythonCommand = dataxTask.getPythonCommand("/usr/bin/python"); |
||||
Assert.assertEquals("/usr/bin/python2.7", pythonCommand); |
||||
pythonCommand = dataxTask.getPythonCommand("/usr/local/bin/python2"); |
||||
Assert.assertEquals("/usr/local/bin/python2.7", pythonCommand); |
||||
pythonCommand = dataxTask.getPythonCommand("/opt/python/bin/python3.8"); |
||||
Assert.assertEquals("/opt/python/bin/python2.7", pythonCommand); |
||||
pythonCommand = dataxTask.getPythonCommand("/opt/soft/python"); |
||||
Assert.assertEquals("/opt/soft/python/bin/python2.7", pythonCommand); |
||||
} |
||||
|
||||
@Test |
||||
public void testLoadJvmEnv() { |
||||
DataxTask dataxTask = new DataxTask(null,null); |
||||
DataxParameters dataxParameters = new DataxParameters(); |
||||
dataxParameters.setXms(0); |
||||
dataxParameters.setXmx(-100); |
||||
|
||||
String actual = dataxTask.loadJvmEnv(dataxParameters); |
||||
|
||||
String except = " --jvm=\"-Xms1G -Xmx1G\" "; |
||||
Assert.assertEquals(except,actual); |
||||
|
||||
dataxParameters.setXms(13); |
||||
dataxParameters.setXmx(14); |
||||
actual = dataxTask.loadJvmEnv(dataxParameters); |
||||
except = " --jvm=\"-Xms13G -Xmx14G\" "; |
||||
Assert.assertEquals(except,actual); |
||||
|
||||
} |
||||
} |
@ -1,208 +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.server.worker.task.http; |
||||
|
||||
import static org.apache.dolphinscheduler.common.enums.CommandType.*; |
||||
|
||||
import java.io.IOException; |
||||
import java.util.Date; |
||||
|
||||
import org.apache.dolphinscheduler.common.enums.HttpCheckCondition; |
||||
import org.apache.dolphinscheduler.common.enums.HttpMethod; |
||||
import org.apache.dolphinscheduler.common.task.http.HttpParameters; |
||||
import org.apache.dolphinscheduler.common.utils.JSONUtils; |
||||
import org.apache.dolphinscheduler.common.utils.OSUtils; |
||||
import org.apache.dolphinscheduler.dao.entity.ProcessInstance; |
||||
import org.apache.dolphinscheduler.server.entity.TaskExecutionContext; |
||||
import org.apache.dolphinscheduler.server.worker.task.ShellCommandExecutor; |
||||
import org.apache.dolphinscheduler.server.worker.task.TaskProps; |
||||
import org.apache.dolphinscheduler.service.bean.SpringApplicationContext; |
||||
import org.apache.dolphinscheduler.service.process.ProcessService; |
||||
import org.apache.http.client.methods.CloseableHttpResponse; |
||||
import org.apache.http.client.methods.RequestBuilder; |
||||
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 org.springframework.context.ApplicationContext; |
||||
|
||||
|
||||
@RunWith(PowerMockRunner.class) |
||||
@PrepareForTest(OSUtils.class) |
||||
@PowerMockIgnore({"javax.management.*","javax.net.ssl.*"}) |
||||
public class HttpTaskTest { |
||||
private static final Logger logger = LoggerFactory.getLogger(HttpTaskTest.class); |
||||
|
||||
|
||||
|
||||
private HttpTask httpTask; |
||||
|
||||
private ProcessService processService; |
||||
|
||||
private ShellCommandExecutor shellCommandExecutor; |
||||
|
||||
private ApplicationContext applicationContext; |
||||
private TaskExecutionContext taskExecutionContext; |
||||
|
||||
@Before |
||||
public void before() throws Exception { |
||||
taskExecutionContext = new TaskExecutionContext(); |
||||
|
||||
PowerMockito.mockStatic(OSUtils.class); |
||||
processService = PowerMockito.mock(ProcessService.class); |
||||
shellCommandExecutor = PowerMockito.mock(ShellCommandExecutor.class); |
||||
|
||||
applicationContext = PowerMockito.mock(ApplicationContext.class); |
||||
SpringApplicationContext springApplicationContext = new SpringApplicationContext(); |
||||
springApplicationContext.setApplicationContext(applicationContext); |
||||
PowerMockito.when(applicationContext.getBean(ProcessService.class)).thenReturn(processService); |
||||
|
||||
TaskProps props = new TaskProps(); |
||||
props.setExecutePath("/tmp"); |
||||
props.setTaskAppId(String.valueOf(System.currentTimeMillis())); |
||||
props.setTaskInstanceId(1); |
||||
props.setTenantCode("1"); |
||||
props.setEnvFile(".dolphinscheduler_env.sh"); |
||||
props.setTaskStartTime(new Date()); |
||||
props.setTaskTimeout(0); |
||||
props.setTaskParams( |
||||
"{\"localParams\":[],\"httpParams\":[],\"url\":\"https://github.com/\",\"httpMethod\":\"GET\"," + |
||||
"\"httpCheckCondition\":\"STATUS_CODE_DEFAULT\",\"condition\":\"https://github.com/\"," + |
||||
"\"connectTimeout\":\"1000\",\"socketTimeout\":\"1000\"}"); |
||||
|
||||
|
||||
taskExecutionContext = Mockito.mock(TaskExecutionContext.class); |
||||
Mockito.when(taskExecutionContext.getTaskParams()).thenReturn(props.getTaskParams()); |
||||
Mockito.when(taskExecutionContext.getExecutePath()).thenReturn("/tmp"); |
||||
Mockito.when(taskExecutionContext.getTaskAppId()).thenReturn("1"); |
||||
Mockito.when(taskExecutionContext.getTenantCode()).thenReturn("root"); |
||||
Mockito.when(taskExecutionContext.getStartTime()).thenReturn(new Date()); |
||||
Mockito.when(taskExecutionContext.getTaskTimeout()).thenReturn(10000); |
||||
Mockito.when(taskExecutionContext.getLogPath()).thenReturn("/tmp/dx"); |
||||
|
||||
httpTask = new HttpTask(taskExecutionContext, logger); |
||||
httpTask.init(); |
||||
|
||||
} |
||||
|
||||
@Test |
||||
public void testGetParameters() { |
||||
Assert.assertNotNull(httpTask.getParameters()); |
||||
} |
||||
|
||||
|
||||
@Test |
||||
public void testCheckParameters() { |
||||
Assert.assertTrue(httpTask.getParameters().checkParameters()); |
||||
} |
||||
|
||||
|
||||
@Test |
||||
public void testGenerator(){ |
||||
String paramJson = "{\"localParams\":[],\"httpParams\":[],\"url\":\"https://github.com/\"," + |
||||
"\"httpMethod\":\"GET\",\"httpCheckCondition\":\"STATUS_CODE_DEFAULT\",\"condition\":\"\",\"connectTimeout\":\"10000\",\"socketTimeout\":\"10000\"}"; |
||||
HttpParameters httpParameters = JSONUtils.parseObject(paramJson, HttpParameters.class); |
||||
|
||||
|
||||
Assert.assertEquals(10000,httpParameters.getConnectTimeout() ); |
||||
Assert.assertEquals(10000,httpParameters.getSocketTimeout()); |
||||
Assert.assertEquals("https://github.com/",httpParameters.getUrl()); |
||||
Assert.assertEquals(HttpMethod.GET,httpParameters.getHttpMethod()); |
||||
Assert.assertEquals(HttpCheckCondition.STATUS_CODE_DEFAULT,httpParameters.getHttpCheckCondition()); |
||||
Assert.assertEquals("",httpParameters.getCondition()); |
||||
|
||||
} |
||||
|
||||
@Test |
||||
public void testHandle(){ |
||||
boolean flag = true ; |
||||
try { |
||||
httpTask.handle(); |
||||
} catch (Exception e) { |
||||
flag = false ; |
||||
e.printStackTrace(); |
||||
} |
||||
|
||||
Assert.assertTrue(flag); |
||||
|
||||
} |
||||
|
||||
@Test |
||||
public void testSendRequest(){ |
||||
|
||||
CloseableHttpClient client = httpTask.createHttpClient(); |
||||
|
||||
String statusCode = null; |
||||
String body = null; |
||||
|
||||
try { |
||||
|
||||
CloseableHttpResponse response = httpTask.sendRequest(client) ; |
||||
statusCode = String.valueOf(httpTask.getStatusCode(response)); |
||||
body = httpTask.getResponseBody(response); |
||||
int exitStatusCode = httpTask.validResponse(body, statusCode); |
||||
|
||||
Assert.assertNotEquals(-1,exitStatusCode); |
||||
|
||||
} catch (IOException e) { |
||||
e.printStackTrace(); |
||||
}; |
||||
} |
||||
|
||||
@Test |
||||
public void testValidResponse(){ |
||||
String body = "body"; |
||||
String statusCode = "200" ; |
||||
|
||||
int exitStatusCode = httpTask.validResponse(body,statusCode); |
||||
Assert.assertNotEquals(-1,exitStatusCode); |
||||
|
||||
} |
||||
|
||||
@Test |
||||
public void testAppendMessage(){ |
||||
httpTask.appendMessage("message"); |
||||
|
||||
Assert.assertEquals("message",httpTask.getOutput()); |
||||
} |
||||
|
||||
@Test |
||||
public void testCreateHttpClient(){ |
||||
Assert.assertNotNull(httpTask.createHttpClient()); |
||||
} |
||||
|
||||
@Test |
||||
public void testCreateRequestBuilder(){ |
||||
RequestBuilder requestBuilder = httpTask.createRequestBuilder(); |
||||
Assert.assertEquals(RequestBuilder.get().getMethod(),requestBuilder.getMethod()); |
||||
} |
||||
|
||||
private ProcessInstance getProcessInstance() { |
||||
ProcessInstance processInstance = new ProcessInstance(); |
||||
processInstance.setCommandType(START_PROCESS); |
||||
processInstance.setScheduleTime(new Date()); |
||||
return processInstance; |
||||
} |
||||
} |
@ -1,119 +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.server.worker.task.procedure; |
||||
|
||||
import org.apache.dolphinscheduler.common.Constants; |
||||
import org.apache.dolphinscheduler.server.entity.ProcedureTaskExecutionContext; |
||||
import org.apache.dolphinscheduler.server.entity.TaskExecutionContext; |
||||
import org.apache.dolphinscheduler.server.worker.task.TaskProps; |
||||
import org.apache.dolphinscheduler.service.bean.SpringApplicationContext; |
||||
import org.apache.dolphinscheduler.service.process.ProcessService; |
||||
|
||||
import java.sql.CallableStatement; |
||||
import java.sql.Connection; |
||||
import java.sql.DriverManager; |
||||
import java.sql.SQLException; |
||||
import java.util.Date; |
||||
|
||||
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; |
||||
import org.slf4j.Logger; |
||||
import org.slf4j.LoggerFactory; |
||||
import org.springframework.context.ApplicationContext; |
||||
|
||||
@RunWith(PowerMockRunner.class) |
||||
@PrepareForTest({ProcedureTask.class,DriverManager.class}) |
||||
public class ProcedureTaskTest { |
||||
private static final Logger logger = LoggerFactory.getLogger(ProcedureTaskTest.class); |
||||
|
||||
private static final String CONNECTION_PARAMS = "{\"user\":\"root\",\"password\":\"123456\",\"address\":\"jdbc:mysql://127.0.0.1:3306\"," |
||||
+ "\"database\":\"test\",\"jdbcUrl\":\"jdbc:mysql://127.0.0.1:3306/test\"}"; |
||||
|
||||
private ProcedureTask procedureTask; |
||||
|
||||
private ProcessService processService; |
||||
|
||||
private ApplicationContext applicationContext; |
||||
|
||||
private TaskExecutionContext taskExecutionContext; |
||||
|
||||
@Before |
||||
public void before() throws Exception { |
||||
taskExecutionContext = new TaskExecutionContext(); |
||||
processService = PowerMockito.mock(ProcessService.class); |
||||
applicationContext = PowerMockito.mock(ApplicationContext.class); |
||||
SpringApplicationContext springApplicationContext = new SpringApplicationContext(); |
||||
springApplicationContext.setApplicationContext(applicationContext); |
||||
PowerMockito.when(applicationContext.getBean(ProcessService.class)).thenReturn(processService); |
||||
|
||||
TaskProps props = new TaskProps(); |
||||
props.setExecutePath("/tmp"); |
||||
props.setTaskAppId(String.valueOf(System.currentTimeMillis())); |
||||
props.setTaskInstanceId(1); |
||||
props.setTenantCode("1"); |
||||
props.setEnvFile(".dolphinscheduler_env.sh"); |
||||
props.setTaskStartTime(new Date()); |
||||
props.setTaskTimeout(0); |
||||
props.setTaskParams( |
||||
"{\"localParams\":[],\"type\":\"POSTGRESQL\",\"datasource\":1,\"method\":\"add\"}"); |
||||
|
||||
taskExecutionContext = PowerMockito.mock(TaskExecutionContext.class); |
||||
PowerMockito.when(taskExecutionContext.getTaskParams()).thenReturn(props.getTaskParams()); |
||||
PowerMockito.when(taskExecutionContext.getExecutePath()).thenReturn("/tmp"); |
||||
PowerMockito.when(taskExecutionContext.getTaskAppId()).thenReturn("1"); |
||||
PowerMockito.when(taskExecutionContext.getTenantCode()).thenReturn("root"); |
||||
PowerMockito.when(taskExecutionContext.getStartTime()).thenReturn(new Date()); |
||||
PowerMockito.when(taskExecutionContext.getTaskTimeout()).thenReturn(10000); |
||||
PowerMockito.when(taskExecutionContext.getLogPath()).thenReturn("/tmp/dx"); |
||||
|
||||
ProcedureTaskExecutionContext procedureTaskExecutionContext = new ProcedureTaskExecutionContext(); |
||||
procedureTaskExecutionContext.setConnectionParams(CONNECTION_PARAMS); |
||||
PowerMockito.when(taskExecutionContext.getProcedureTaskExecutionContext()).thenReturn(procedureTaskExecutionContext); |
||||
|
||||
procedureTask = new ProcedureTask(taskExecutionContext, logger); |
||||
procedureTask.init(); |
||||
} |
||||
|
||||
@Test |
||||
public void testGetParameters() { |
||||
Assert.assertNotNull(procedureTask.getParameters()); |
||||
} |
||||
|
||||
@Test |
||||
public void testHandle() throws SQLException { |
||||
|
||||
Connection connection = PowerMockito.mock(Connection.class); |
||||
PowerMockito.mockStatic(DriverManager.class); |
||||
PowerMockito.when(DriverManager.getConnection(Mockito.any(), Mockito.any(), Mockito.any())).thenReturn(connection); |
||||
CallableStatement callableStatement = PowerMockito.mock(CallableStatement.class); |
||||
PowerMockito.when(connection.prepareCall(Mockito.any())).thenReturn(callableStatement); |
||||
try { |
||||
procedureTask.handle(); |
||||
Assert.assertEquals(Constants.EXIT_CODE_SUCCESS,procedureTask.getExitStatusCode()); |
||||
} catch (Exception e) { |
||||
Assert.fail(e.getMessage()); |
||||
} |
||||
} |
||||
|
||||
} |
@ -1,125 +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.server.worker.task.shell; |
||||
|
||||
import static org.mockito.ArgumentMatchers.anyString; |
||||
|
||||
import org.apache.dolphinscheduler.common.enums.TaskType; |
||||
import org.apache.dolphinscheduler.common.utils.ParameterUtils; |
||||
import org.apache.dolphinscheduler.server.entity.TaskExecutionContext; |
||||
import org.apache.dolphinscheduler.server.worker.task.CommandExecuteResult; |
||||
import org.apache.dolphinscheduler.server.worker.task.ShellCommandExecutor; |
||||
import org.apache.dolphinscheduler.service.bean.SpringApplicationContext; |
||||
|
||||
import java.nio.file.Files; |
||||
import java.nio.file.Paths; |
||||
import java.sql.DriverManager; |
||||
import java.util.ArrayList; |
||||
import java.util.Date; |
||||
import java.util.HashMap; |
||||
import java.util.Map; |
||||
|
||||
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; |
||||
import org.slf4j.Logger; |
||||
import org.slf4j.LoggerFactory; |
||||
|
||||
/** |
||||
* shell task test. |
||||
*/ |
||||
@RunWith(PowerMockRunner.class) |
||||
@PrepareForTest(value = {ShellTask.class, DriverManager.class, SpringApplicationContext.class, ParameterUtils.class}) |
||||
public class ShellTaskTest { |
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(ShellTaskTest.class); |
||||
|
||||
private ShellTask shellTask; |
||||
private ShellCommandExecutor shellCommandExecutor; |
||||
private TaskExecutionContext taskExecutionContext; |
||||
private CommandExecuteResult commandExecuteResult; |
||||
|
||||
@Before |
||||
public void before() throws Exception { |
||||
System.setProperty("log4j2.disable.jmx", Boolean.TRUE.toString()); |
||||
shellCommandExecutor = PowerMockito.mock(ShellCommandExecutor.class); |
||||
PowerMockito.whenNew(ShellCommandExecutor.class).withAnyArguments().thenReturn(shellCommandExecutor); |
||||
taskExecutionContext = new TaskExecutionContext(); |
||||
taskExecutionContext.setTaskInstanceId(1); |
||||
taskExecutionContext.setTaskName("kris test"); |
||||
taskExecutionContext.setTaskType(TaskType.SHELL.getDesc()); |
||||
taskExecutionContext.setHost("127.0.0.1:1234"); |
||||
taskExecutionContext.setExecutePath("/tmp"); |
||||
taskExecutionContext.setLogPath("/log"); |
||||
taskExecutionContext.setTaskJson( |
||||
"{\"conditionResult\":\"{\\\"successNode\\\":[\\\"\\\"],\\\"failedNode\\\":[\\\"\\\"]}\",\"conditionsTask\":false,\"depList\":[],\"dependence\":\"{}\",\"forbidden\":false,\"id\":\"" |
||||
+ |
||||
"tasks-16849\",\"maxRetryTimes\":0,\"name\":\"shell test 001\",\"params\":\"{\\\"rawScript\\\":\\\"#!/bin/sh\\\\necho $[yyyy-MM-dd HH:mm:ss +3]\\\\necho \\\\\\\" ?? " |
||||
+ "${time1} \\\\\\\"\\\\necho \\\\\\\" ????? ${time2}\\\\\\\"\\\\n\\\",\\\"localParams\\\":[{\\\"prop\\\":\\\"time1\\\",\\\"direct\\\":\\\"OUT\\\",\\\"type\\\":" |
||||
+ "\\\"VARCHAR\\\",\\\"value\\\":\\\"$[yyyy-MM-dd HH:mm:ss]\\\"},{\\\"prop\\\":\\\"time2\\\",\\\"direct\\\":\\\"IN\\\",\\\"type\\\":\\\"VARCHAR\\\",\\\"value\\\":\\\"${time_gb}\\\"}" |
||||
+ "],\\\"resourceList\\\":[]}\",\"preTasks\":\"[]\",\"retryInterval\":1,\"runFlag\":\"NORMAL\",\"taskInstancePriority\":\"MEDIUM\",\"taskTimeoutParameter\":" |
||||
+ "{\"enable\":false,\"interval\":0},\"timeout\":\"{\\\"enable\\\":false,\\\"strategy\\\":\\\"\\\"}\",\"type\":\"SHELL\",\"workerGroup\":\"default\"}"); |
||||
taskExecutionContext.setProcessInstanceId(1); |
||||
taskExecutionContext.setGlobalParams("[{\"direct\":\"IN\",\"prop\":\"time_gb\",\"type\":\"VARCHAR\",\"value\":\"2020-12-16 17:18:33\"}]"); |
||||
taskExecutionContext.setExecutorId(1); |
||||
taskExecutionContext.setCmdTypeIfComplement(5); |
||||
taskExecutionContext.setTenantCode("roo"); |
||||
taskExecutionContext.setScheduleTime(new Date()); |
||||
taskExecutionContext.setQueue("default"); |
||||
taskExecutionContext.setVarPool("[{\"direct\":\"IN\",\"prop\":\"test\",\"type\":\"VARCHAR\",\"value\":\"\"}]"); |
||||
taskExecutionContext.setTaskParams( |
||||
"{\"rawScript\":\"#!/bin/sh\\necho $[yyyy-MM-dd HH:mm:ss +3]\\necho \\\" ?? ${time1} \\\"\\necho \\\" ????? ${time2}\\\"\\n\",\"localParams\":" |
||||
+ |
||||
"[{\"prop\":\"time1\",\"direct\":\"OUT\",\"type\":\"VARCHAR\",\"value\":\"$[yyyy-MM-dd HH:mm:ss]\"},{\"prop\":\"time2\",\"direct\":\"IN\",\"type\":\"VARCHAR" |
||||
+ "\",\"value\":\"${time_gb}\"}],\"resourceList\":[]}"); |
||||
Map<String, String> definedParams = new HashMap<>(); |
||||
definedParams.put("time_gb", "2020-12-16 00:00:00"); |
||||
taskExecutionContext.setDefinedParams(definedParams); |
||||
PowerMockito.mockStatic(Files.class); |
||||
PowerMockito.when(Files.exists(Paths.get(anyString()))).thenReturn(true); |
||||
commandExecuteResult = new CommandExecuteResult(); |
||||
commandExecuteResult.setAppIds("appId"); |
||||
commandExecuteResult.setExitStatusCode(0); |
||||
commandExecuteResult.setProcessId(1); |
||||
} |
||||
|
||||
@Test |
||||
public void testComplementData() throws Exception { |
||||
shellTask = new ShellTask(taskExecutionContext, logger); |
||||
shellTask.init(); |
||||
shellTask.getParameters().setVarPool(taskExecutionContext.getVarPool()); |
||||
shellCommandExecutor.isSuccessOfYarnState(new ArrayList<>()); |
||||
shellCommandExecutor.isSuccessOfYarnState(null); |
||||
PowerMockito.when(shellCommandExecutor.run(anyString())).thenReturn(commandExecuteResult); |
||||
shellTask.handle(); |
||||
} |
||||
|
||||
@Test |
||||
public void testStartProcess() throws Exception { |
||||
taskExecutionContext.setCmdTypeIfComplement(0); |
||||
shellTask = new ShellTask(taskExecutionContext, logger); |
||||
shellTask.init(); |
||||
shellTask.getParameters().setVarPool(taskExecutionContext.getVarPool()); |
||||
PowerMockito.when(shellCommandExecutor.run(anyString())).thenReturn(commandExecuteResult); |
||||
shellTask.handle(); |
||||
} |
||||
|
||||
} |
@ -1,134 +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.server.worker.task.spark; |
||||
|
||||
import org.apache.dolphinscheduler.common.utils.ParameterUtils; |
||||
import org.apache.dolphinscheduler.common.utils.placeholder.PlaceholderUtils; |
||||
import org.apache.dolphinscheduler.common.utils.placeholder.PropertyPlaceholderHelper; |
||||
import org.apache.dolphinscheduler.server.entity.TaskExecutionContext; |
||||
import org.apache.dolphinscheduler.service.bean.SpringApplicationContext; |
||||
import org.apache.dolphinscheduler.service.process.ProcessService; |
||||
|
||||
import java.util.Date; |
||||
|
||||
import org.junit.Assert; |
||||
import org.junit.Before; |
||||
import org.junit.Test; |
||||
import org.junit.runner.RunWith; |
||||
import org.mockito.Mockito; |
||||
import org.powermock.core.classloader.annotations.PrepareForTest; |
||||
import org.powermock.modules.junit4.PowerMockRunner; |
||||
import org.slf4j.Logger; |
||||
import org.slf4j.LoggerFactory; |
||||
import org.springframework.context.ApplicationContext; |
||||
|
||||
@RunWith(PowerMockRunner.class) |
||||
@PrepareForTest({ParameterUtils.class, PlaceholderUtils.class, PropertyPlaceholderHelper.class}) |
||||
public class SparkTaskTest { |
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(SparkTaskTest.class); |
||||
|
||||
private TaskExecutionContext taskExecutionContext; |
||||
|
||||
private ApplicationContext applicationContext; |
||||
|
||||
private ProcessService processService; |
||||
|
||||
private SparkTask spark2Task; |
||||
|
||||
String spark1Params = "{" |
||||
+ "\"mainArgs\":\"\", " |
||||
+ "\"driverMemory\":\"1G\", " |
||||
+ "\"executorMemory\":\"2G\", " |
||||
+ "\"programType\":\"SCALA\", " |
||||
+ "\"mainClass\":\"basicetl.GlobalUserCar\", " |
||||
+ "\"driverCores\":\"2\", " |
||||
+ "\"deployMode\":\"cluster\", " |
||||
+ "\"executorCores\":2, " |
||||
+ "\"mainJar\":{\"res\":\"test-1.0-SNAPSHOT.jar\"}, " |
||||
+ "\"sparkVersion\":\"SPARK1\", " |
||||
+ "\"numExecutors\":\"10\", " |
||||
+ "\"localParams\":[], " |
||||
+ "\"others\":\"\", " |
||||
+ "\"resourceList\":[]" |
||||
+ "}"; |
||||
|
||||
String spark2Params = "{" |
||||
+ "\"mainArgs\":\"\", " |
||||
+ "\"driverMemory\":\"1G\", " |
||||
+ "\"executorMemory\":\"2G\", " |
||||
+ "\"programType\":\"SCALA\", " |
||||
+ "\"mainClass\":\"basicetl.GlobalUserCar\", " |
||||
+ "\"driverCores\":\"2\", " |
||||
+ "\"deployMode\":\"cluster\", " |
||||
+ "\"executorCores\":2, " |
||||
+ "\"mainJar\":{\"res\":\"test-1.0-SNAPSHOT.jar\"}, " |
||||
+ "\"sparkVersion\":\"SPARK2\", " |
||||
+ "\"numExecutors\":\"10\", " |
||||
+ "\"localParams\":[], " |
||||
+ "\"others\":\"\", " |
||||
+ "\"resourceList\":[]" |
||||
+ "}"; |
||||
|
||||
@Before |
||||
public void setTaskExecutionContext() { |
||||
taskExecutionContext = new TaskExecutionContext(); |
||||
taskExecutionContext.setTaskParams(spark2Params); |
||||
taskExecutionContext.setQueue("dev"); |
||||
taskExecutionContext.setTaskAppId(String.valueOf(System.currentTimeMillis())); |
||||
taskExecutionContext.setTenantCode("1"); |
||||
taskExecutionContext.setEnvFile(".dolphinscheduler_env.sh"); |
||||
taskExecutionContext.setStartTime(new Date()); |
||||
taskExecutionContext.setTaskTimeout(0); |
||||
|
||||
processService = Mockito.mock(ProcessService.class); |
||||
applicationContext = Mockito.mock(ApplicationContext.class); |
||||
SpringApplicationContext springApplicationContext = new SpringApplicationContext(); |
||||
springApplicationContext.setApplicationContext(applicationContext); |
||||
Mockito.when(applicationContext.getBean(ProcessService.class)).thenReturn(processService); |
||||
|
||||
spark2Task = new SparkTask(taskExecutionContext, logger); |
||||
spark2Task.init(); |
||||
} |
||||
|
||||
@Test |
||||
public void testSparkTaskInit() { |
||||
|
||||
TaskExecutionContext sparkTaskCtx = new TaskExecutionContext(); |
||||
SparkTask sparkTask = new SparkTask(sparkTaskCtx, logger); |
||||
sparkTask.init(); |
||||
sparkTask.getParameters(); |
||||
Assert.assertNull(sparkTaskCtx.getTaskParams()); |
||||
|
||||
String spark2Command = spark2Task.buildCommand(); |
||||
String spark2Expected = "${SPARK_HOME2}/bin/spark-submit --master yarn --deploy-mode cluster " |
||||
+ "--class basicetl.GlobalUserCar --driver-cores 2 --driver-memory 1G --num-executors 10 " |
||||
+ "--executor-cores 2 --executor-memory 2G --queue dev test-1.0-SNAPSHOT.jar"; |
||||
Assert.assertEquals(spark2Expected, spark2Command); |
||||
|
||||
taskExecutionContext.setTaskParams(spark1Params); |
||||
|
||||
SparkTask spark1Task = new SparkTask(taskExecutionContext, logger); |
||||
spark1Task.init(); |
||||
String spark1Command = spark1Task.buildCommand(); |
||||
String spark1Expected = "${SPARK_HOME1}/bin/spark-submit --master yarn --deploy-mode cluster " |
||||
+ "--class basicetl.GlobalUserCar --driver-cores 2 --driver-memory 1G --num-executors 10 " |
||||
+ "--executor-cores 2 --executor-memory 2G --queue dev test-1.0-SNAPSHOT.jar"; |
||||
Assert.assertEquals(spark1Expected, spark1Command); |
||||
} |
||||
} |
@ -1,241 +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.server.worker.task.sql; |
||||
|
||||
import static org.junit.Assert.assertEquals; |
||||
import static org.junit.Assert.assertTrue; |
||||
import static org.junit.Assert.fail; |
||||
|
||||
import org.apache.dolphinscheduler.common.Constants; |
||||
import org.apache.dolphinscheduler.common.datasource.DatasourceUtil; |
||||
import org.apache.dolphinscheduler.common.process.Property; |
||||
import org.apache.dolphinscheduler.common.task.sql.SqlParameters; |
||||
import org.apache.dolphinscheduler.common.utils.ParameterUtils; |
||||
import org.apache.dolphinscheduler.dao.AlertDao; |
||||
import org.apache.dolphinscheduler.remote.command.alert.AlertSendResponseCommand; |
||||
import org.apache.dolphinscheduler.server.entity.SQLTaskExecutionContext; |
||||
import org.apache.dolphinscheduler.server.entity.TaskExecutionContext; |
||||
import org.apache.dolphinscheduler.server.worker.task.TaskProps; |
||||
import org.apache.dolphinscheduler.service.alert.AlertClientService; |
||||
import org.apache.dolphinscheduler.service.bean.SpringApplicationContext; |
||||
|
||||
import java.sql.Connection; |
||||
import java.sql.PreparedStatement; |
||||
import java.sql.ResultSet; |
||||
import java.sql.ResultSetMetaData; |
||||
import java.util.Date; |
||||
import java.util.HashMap; |
||||
import java.util.Map; |
||||
|
||||
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; |
||||
import org.powermock.reflect.Whitebox; |
||||
import org.slf4j.Logger; |
||||
import org.slf4j.LoggerFactory; |
||||
|
||||
/** |
||||
* sql task test |
||||
*/ |
||||
@RunWith(PowerMockRunner.class) |
||||
@PrepareForTest(value = {SqlTask.class, DatasourceUtil.class, SpringApplicationContext.class, |
||||
ParameterUtils.class, AlertSendResponseCommand.class}) |
||||
public class SqlTaskTest { |
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(SqlTaskTest.class); |
||||
|
||||
private static final String CONNECTION_PARAMS = "{\"user\":\"root\",\"password\":\"123456\",\"address\":\"jdbc:mysql://127.0.0.1:3306\"," |
||||
+ "\"database\":\"test\",\"jdbcUrl\":\"jdbc:mysql://127.0.0.1:3306/test\"}"; |
||||
|
||||
private SqlTask sqlTask; |
||||
|
||||
private TaskExecutionContext taskExecutionContext; |
||||
|
||||
private AlertClientService alertClientService; |
||||
@Before |
||||
public void before() throws Exception { |
||||
taskExecutionContext = new TaskExecutionContext(); |
||||
|
||||
TaskProps props = new TaskProps(); |
||||
props.setExecutePath("/tmp"); |
||||
props.setTaskAppId(String.valueOf(System.currentTimeMillis())); |
||||
props.setTaskInstanceId(1); |
||||
props.setTenantCode("1"); |
||||
props.setEnvFile(".dolphinscheduler_env.sh"); |
||||
props.setTaskStartTime(new Date()); |
||||
props.setTaskTimeout(0); |
||||
props.setTaskParams( |
||||
"{\"localParams\":[{\"prop\":\"ret\", \"direct\":\"OUT\", \"type\":\"VARCHAR\", \"value\":\"\"}]," |
||||
+ "\"type\":\"POSTGRESQL\",\"datasource\":1,\"sql\":\"insert into tb_1 values('1','2')\"," |
||||
+ "\"sqlType\":1}"); |
||||
|
||||
taskExecutionContext = PowerMockito.mock(TaskExecutionContext.class); |
||||
PowerMockito.when(taskExecutionContext.getTaskParams()).thenReturn(props.getTaskParams()); |
||||
PowerMockito.when(taskExecutionContext.getExecutePath()).thenReturn("/tmp"); |
||||
PowerMockito.when(taskExecutionContext.getTaskAppId()).thenReturn("1"); |
||||
PowerMockito.when(taskExecutionContext.getTenantCode()).thenReturn("root"); |
||||
PowerMockito.when(taskExecutionContext.getStartTime()).thenReturn(new Date()); |
||||
PowerMockito.when(taskExecutionContext.getTaskTimeout()).thenReturn(10000); |
||||
PowerMockito.when(taskExecutionContext.getLogPath()).thenReturn("/tmp/dx"); |
||||
PowerMockito.when(taskExecutionContext.getVarPool()).thenReturn("[{\"direct\":\"IN\",\"prop\":\"test\",\"type\":\"VARCHAR\",\"value\":\"\"}]"); |
||||
|
||||
SQLTaskExecutionContext sqlTaskExecutionContext = new SQLTaskExecutionContext(); |
||||
sqlTaskExecutionContext.setConnectionParams(CONNECTION_PARAMS); |
||||
PowerMockito.when(taskExecutionContext.getSqlTaskExecutionContext()).thenReturn(sqlTaskExecutionContext); |
||||
|
||||
PowerMockito.mockStatic(SpringApplicationContext.class); |
||||
PowerMockito.when(SpringApplicationContext.getBean(Mockito.any())).thenReturn(new AlertDao()); |
||||
alertClientService = PowerMockito.mock(AlertClientService.class); |
||||
sqlTask = new SqlTask(taskExecutionContext, logger, alertClientService); |
||||
sqlTask.getParameters().setVarPool(taskExecutionContext.getVarPool()); |
||||
sqlTask.init(); |
||||
} |
||||
|
||||
@Test |
||||
public void testGetParameters() { |
||||
Assert.assertNotNull(sqlTask.getParameters()); |
||||
} |
||||
|
||||
@Test |
||||
public void testHandle() throws Exception { |
||||
Connection connection = PowerMockito.mock(Connection.class); |
||||
PreparedStatement preparedStatement = PowerMockito.mock(PreparedStatement.class); |
||||
PowerMockito.when(connection.prepareStatement(Mockito.any())).thenReturn(preparedStatement); |
||||
PowerMockito.mockStatic(ParameterUtils.class); |
||||
PowerMockito.when(ParameterUtils.replaceScheduleTime(Mockito.any(), Mockito.any())).thenReturn("insert into tb_1 values('1','2')"); |
||||
PowerMockito.mockStatic(DatasourceUtil.class); |
||||
PowerMockito.when(DatasourceUtil.getConnection(Mockito.any(), Mockito.any())).thenReturn(connection); |
||||
|
||||
sqlTask.handle(); |
||||
assertEquals(Constants.EXIT_CODE_SUCCESS, sqlTask.getExitStatusCode()); |
||||
} |
||||
|
||||
@Test |
||||
public void testResultProcess() throws Exception { |
||||
// test input null and will not throw a exception
|
||||
AlertSendResponseCommand mockResponseCommand = PowerMockito.mock(AlertSendResponseCommand.class); |
||||
PowerMockito.when(mockResponseCommand.getResStatus()).thenReturn(true); |
||||
PowerMockito.when(alertClientService.sendAlert(0, "null query result sets", "[]")).thenReturn(mockResponseCommand); |
||||
String result = Whitebox.invokeMethod(sqlTask, "resultProcess", null); |
||||
Assert.assertNotNull(result); |
||||
} |
||||
|
||||
@Test |
||||
public void testResultProcess02() throws Exception { |
||||
// test input not null
|
||||
ResultSet resultSet = PowerMockito.mock(ResultSet.class); |
||||
ResultSetMetaData mockResultMetaData = PowerMockito.mock(ResultSetMetaData.class); |
||||
PowerMockito.when(resultSet.getMetaData()).thenReturn(mockResultMetaData); |
||||
PowerMockito.when(mockResultMetaData.getColumnCount()).thenReturn(2); |
||||
PowerMockito.when(resultSet.next()).thenReturn(true); |
||||
PowerMockito.when(resultSet.getObject(Mockito.anyInt())).thenReturn(1); |
||||
PowerMockito.when(mockResultMetaData.getColumnLabel(Mockito.anyInt())).thenReturn("a"); |
||||
|
||||
AlertSendResponseCommand mockResponseCommand = PowerMockito.mock(AlertSendResponseCommand.class); |
||||
PowerMockito.when(mockResponseCommand.getResStatus()).thenReturn(true); |
||||
PowerMockito.when(alertClientService.sendAlert(Mockito.anyInt(), Mockito.anyString(), Mockito.anyString())).thenReturn(mockResponseCommand); |
||||
|
||||
String result = Whitebox.invokeMethod(sqlTask, "resultProcess", resultSet); |
||||
Assert.assertNotNull(result); |
||||
} |
||||
|
||||
@Test |
||||
public void shouldntThrowNullPointerException_When_SqlParamsMapIsNull_printReplacedSql() { |
||||
try { |
||||
sqlTask.printReplacedSql("", "", "", null); |
||||
assertTrue(true); |
||||
} catch (NullPointerException err) { |
||||
fail(); |
||||
} |
||||
} |
||||
|
||||
@Test |
||||
public void shouldntPutPropertyInSqlParamsMap_When_paramNameIsNotFoundInparamsPropsMap_setSqlParamsMap() { |
||||
Map<Integer, Property> sqlParamsMap = new HashMap<>(); |
||||
Map<String, Property> paramsPropsMap = new HashMap<>(); |
||||
paramsPropsMap.put("validPropertyName", new Property()); |
||||
|
||||
taskExecutionContext = PowerMockito.mock(TaskExecutionContext.class); |
||||
PowerMockito.when(taskExecutionContext.getTaskInstanceId()).thenReturn(1); |
||||
|
||||
sqlTask.setSqlParamsMap("notValidPropertyName", "(notValidPropertyName)", sqlParamsMap, paramsPropsMap); |
||||
|
||||
assertEquals(0, sqlParamsMap.size()); |
||||
} |
||||
|
||||
@Test |
||||
public void testQueryBySQLUsingLimit() throws Exception { |
||||
TaskExecutionContext localTaskExecutionContext; |
||||
TaskProps props = new TaskProps(); |
||||
props.setExecutePath("/tmp"); |
||||
props.setTaskAppId(String.valueOf(System.currentTimeMillis())); |
||||
props.setTaskInstanceId(1); |
||||
props.setTenantCode("1"); |
||||
props.setEnvFile(".dolphinscheduler_env.sh"); |
||||
props.setTaskStartTime(new Date()); |
||||
props.setTaskTimeout(0); |
||||
props.setTaskParams( |
||||
"{\"localParams\":[{\"prop\":\"ret\", \"direct\":\"OUT\", \"type\":\"VARCHAR\", \"value\":\"\"}]," |
||||
+ "\"type\":\"POSTGRESQL\",\"datasource\":1,\"sql\":\"SELECT * FROM tb_1\"," |
||||
+ "\"sqlType\":0, \"limit\":1, \"sendEmail\":\"false\"}"); |
||||
|
||||
localTaskExecutionContext = PowerMockito.mock(TaskExecutionContext.class); |
||||
PowerMockito.when(localTaskExecutionContext.getTaskParams()).thenReturn(props.getTaskParams()); |
||||
PowerMockito.when(localTaskExecutionContext.getExecutePath()).thenReturn("/tmp"); |
||||
PowerMockito.when(localTaskExecutionContext.getTaskAppId()).thenReturn("1"); |
||||
PowerMockito.when(localTaskExecutionContext.getTenantCode()).thenReturn("root"); |
||||
PowerMockito.when(localTaskExecutionContext.getStartTime()).thenReturn(new Date()); |
||||
PowerMockito.when(localTaskExecutionContext.getTaskTimeout()).thenReturn(10000); |
||||
PowerMockito.when(localTaskExecutionContext.getLogPath()).thenReturn("/tmp/dx"); |
||||
|
||||
SQLTaskExecutionContext sqlTaskExecutionContext = new SQLTaskExecutionContext(); |
||||
sqlTaskExecutionContext.setConnectionParams(CONNECTION_PARAMS); |
||||
PowerMockito.when(localTaskExecutionContext.getSqlTaskExecutionContext()).thenReturn(sqlTaskExecutionContext); |
||||
|
||||
PowerMockito.mockStatic(SpringApplicationContext.class); |
||||
PowerMockito.when(SpringApplicationContext.getBean(Mockito.any())).thenReturn(new AlertDao()); |
||||
AlertClientService localAlertClientService = PowerMockito.mock(AlertClientService.class); |
||||
SqlTask localSqlTask = new SqlTask(localTaskExecutionContext, logger, localAlertClientService); |
||||
localSqlTask.init(); |
||||
|
||||
ResultSet resultSet = PowerMockito.mock(ResultSet.class); |
||||
ResultSetMetaData mockResultMetaData = PowerMockito.mock(ResultSetMetaData.class); |
||||
PowerMockito.when(resultSet.getMetaData()).thenReturn(mockResultMetaData); |
||||
PowerMockito.when(mockResultMetaData.getColumnCount()).thenReturn(2); |
||||
PowerMockito.when(resultSet.next()).thenReturn(true); |
||||
PowerMockito.when(resultSet.getObject(Mockito.anyInt())).thenReturn(1); |
||||
PowerMockito.when(mockResultMetaData.getColumnLabel(Mockito.anyInt())).thenReturn("a"); |
||||
|
||||
AlertSendResponseCommand mockResponseCommand = PowerMockito.mock(AlertSendResponseCommand.class); |
||||
PowerMockito.when(mockResponseCommand.getResStatus()).thenReturn(true); |
||||
PowerMockito.when(localAlertClientService.sendAlert(Mockito.anyInt(), Mockito.anyString(), Mockito.anyString())) |
||||
.thenReturn(mockResponseCommand); |
||||
|
||||
String result = Whitebox.invokeMethod(localSqlTask, "resultProcess", resultSet); |
||||
Assert.assertEquals(1, ((SqlParameters) localSqlTask.getParameters()).getLimit()); |
||||
|
||||
// In fact, the target table has 2 rows, as we set the limit to 1, if the limit works, the `resultProcess` method
|
||||
// should return [{"a":1}] rather then [{"a":1},{"a":1}]
|
||||
Assert.assertEquals("[{\"a\":1}]", result); |
||||
} |
||||
} |
@ -1,228 +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.server.worker.task.sqoop; |
||||
|
||||
import org.apache.dolphinscheduler.common.task.sqoop.SqoopParameters; |
||||
import org.apache.dolphinscheduler.common.utils.JSONUtils; |
||||
import org.apache.dolphinscheduler.server.entity.SqoopTaskExecutionContext; |
||||
import org.apache.dolphinscheduler.server.entity.TaskExecutionContext; |
||||
import org.apache.dolphinscheduler.server.worker.task.sqoop.generator.SqoopJobGenerator; |
||||
import org.apache.dolphinscheduler.service.bean.SpringApplicationContext; |
||||
import org.apache.dolphinscheduler.service.process.ProcessService; |
||||
|
||||
import java.util.ArrayList; |
||||
import java.util.Collections; |
||||
import java.util.Date; |
||||
import java.util.List; |
||||
import java.util.concurrent.LinkedBlockingQueue; |
||||
|
||||
import org.junit.Assert; |
||||
import org.junit.Before; |
||||
import org.junit.Test; |
||||
import org.junit.runner.RunWith; |
||||
import org.mockito.Mockito; |
||||
import org.mockito.junit.MockitoJUnitRunner; |
||||
import org.slf4j.Logger; |
||||
import org.slf4j.LoggerFactory; |
||||
import org.springframework.context.ApplicationContext; |
||||
|
||||
/** |
||||
* sqoop task test |
||||
*/ |
||||
@RunWith(MockitoJUnitRunner.Silent.class) |
||||
public class SqoopTaskTest { |
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(SqoopTaskTest.class); |
||||
|
||||
private SqoopTask sqoopTask; |
||||
|
||||
@Before |
||||
public void before() { |
||||
ProcessService processService = Mockito.mock(ProcessService.class); |
||||
ApplicationContext applicationContext = Mockito.mock(ApplicationContext.class); |
||||
SpringApplicationContext springApplicationContext = new SpringApplicationContext(); |
||||
springApplicationContext.setApplicationContext(applicationContext); |
||||
Mockito.when(applicationContext.getBean(ProcessService.class)).thenReturn(processService); |
||||
|
||||
TaskExecutionContext taskExecutionContext = new TaskExecutionContext(); |
||||
taskExecutionContext.setTaskAppId(String.valueOf(System.currentTimeMillis())); |
||||
taskExecutionContext.setTenantCode("1"); |
||||
taskExecutionContext.setEnvFile(".dolphinscheduler_env.sh"); |
||||
taskExecutionContext.setStartTime(new Date()); |
||||
taskExecutionContext.setTaskTimeout(0); |
||||
taskExecutionContext.setTaskParams("{\"jobName\":\"sqoop_import\",\"jobType\":\"TEMPLATE\",\"concurrency\":1," |
||||
+ "\"modelType\":\"import\",\"sourceType\":\"MYSQL\",\"targetType\":\"HIVE\",\"sourceParams\":\"{\\\"srcDatasource\\\":2,\\\"srcTable\\\":\\\"person_2\\\"," |
||||
+ "\\\"srcQueryType\\\":\\\"1\\\",\\\"srcQuerySql\\\":\\\"SELECT * FROM person_2\\\",\\\"srcColumnType\\\":\\\"0\\\"," |
||||
+ "\\\"srcColumns\\\":\\\"\\\",\\\"srcConditionList\\\":[],\\\"mapColumnHive\\\":[]," |
||||
+ "\\\"mapColumnJava\\\":[{\\\"prop\\\":\\\"id\\\",\\\"direct\\\":\\\"IN\\\",\\\"type\\\":\\\"VARCHAR\\\",\\\"value\\\":\\\"Integer\\\"}]}\"" |
||||
+ ",\"targetParams\":\"{\\\"hiveDatabase\\\":\\\"stg\\\",\\\"hiveTable\\\":\\\"person_internal_2\\\",\\\"createHiveTable\\\":true," |
||||
+ "\\\"dropDelimiter\\\":false,\\\"hiveOverWrite\\\":true,\\\"replaceDelimiter\\\":\\\"\\\",\\\"hivePartitionKey\\\":\\\"date\\\"," |
||||
+ "\\\"hivePartitionValue\\\":\\\"2020-02-16\\\"}\",\"localParams\":[]}"); |
||||
|
||||
sqoopTask = new SqoopTask(taskExecutionContext, logger); |
||||
//test sqoop task init method
|
||||
sqoopTask.init(); |
||||
} |
||||
|
||||
/** |
||||
* test SqoopJobGenerator |
||||
*/ |
||||
@Test |
||||
public void testGenerator() { |
||||
TaskExecutionContext mysqlTaskExecutionContext = getMysqlTaskExecutionContext(); |
||||
|
||||
//sqoop TEMPLATE job
|
||||
//import mysql to HDFS with hadoop
|
||||
String mysqlToHdfs = |
||||
"{\"jobName\":\"sqoop_import\",\"hadoopCustomParams\":[{\"prop\":\"mapreduce.map.memory.mb\",\"direct\":\"IN\",\"type\":\"VARCHAR\",\"value\":\"4096\"}]," |
||||
+ "\"sqoopAdvancedParams\":[{\"prop\":\"--direct\",\"direct\":\"IN\",\"type\":\"VARCHAR\",\"value\":\"\"}],\"jobType\":\"TEMPLATE\",\"concurrency\":1," |
||||
+ "\"modelType\":\"import\",\"sourceType\":\"MYSQL\",\"targetType\":\"HDFS\"," |
||||
+ "\"sourceParams\":\"{\\\"srcDatasource\\\":2,\\\"srcTable\\\":\\\"person_2\\\",\\\"srcQueryType\\\":\\\"0\\\",\\\"srcQuerySql\\\":\\\"\\\",\\\"srcColumnType\\\":\\\"0\\\"," |
||||
+ "\\\"srcColumns\\\":\\\"\\\",\\\"srcConditionList\\\":[],\\\"mapColumnHive\\\":[],\\\"mapColumnJava\\\":[]}\",\"targetParams\":\"{\\\"targetPath\\\":\\\"/ods/tmp/test/person7\\\"," |
||||
+ "\\\"deleteTargetDir\\\":true,\\\"fileType\\\":\\\"--as-textfile\\\",\\\"compressionCodec\\\":\\\"\\\",\\\"fieldsTerminated\\\":\\\"@\\\"," |
||||
+ "\\\"linesTerminated\\\":\\\"\\\\\\\\n\\\"}\",\"localParams\":[]}"; |
||||
SqoopParameters mysqlToHdfsParams = JSONUtils.parseObject(mysqlToHdfs, SqoopParameters.class); |
||||
SqoopJobGenerator generator = new SqoopJobGenerator(); |
||||
String mysqlToHdfsScript = generator.generateSqoopJob(mysqlToHdfsParams, mysqlTaskExecutionContext); |
||||
String mysqlToHdfsExpected = |
||||
"sqoop import -D mapred.job.name=sqoop_import -D mapreduce.map.memory.mb=4096 --direct -m 1 --connect " |
||||
+ "\"jdbc:mysql://192.168.0.111:3306/test?allowLoadLocalInfile=false&autoDeserialize=false&allowLocalInfile=false&allowUrlInLocalInfile=false\" " |
||||
+ "--username kylo --password \"123456\" --table person_2 --target-dir /ods/tmp/test/person7 --as-textfile " |
||||
+ "--delete-target-dir --fields-terminated-by '@' --lines-terminated-by '\\n' --null-non-string 'NULL' --null-string 'NULL'"; |
||||
Assert.assertEquals(mysqlToHdfsExpected, mysqlToHdfsScript); |
||||
|
||||
//export hdfs to mysql using update mode
|
||||
String hdfsToMysql = "{\"jobName\":\"sqoop_import\",\"jobType\":\"TEMPLATE\",\"concurrency\":1,\"modelType\":\"export\",\"sourceType\":\"HDFS\"," |
||||
+ "\"targetType\":\"MYSQL\",\"sourceParams\":\"{\\\"exportDir\\\":\\\"/ods/tmp/test/person7\\\"}\"," |
||||
+ "\"targetParams\":\"{\\\"targetDatasource\\\":2,\\\"targetTable\\\":\\\"person_3\\\",\\\"targetColumns\\\":\\\"id,name,age,sex,create_time\\\"," |
||||
+ "\\\"preQuery\\\":\\\"\\\",\\\"isUpdate\\\":true,\\\"targetUpdateKey\\\":\\\"id\\\",\\\"targetUpdateMode\\\":\\\"allowinsert\\\"," |
||||
+ "\\\"fieldsTerminated\\\":\\\"@\\\",\\\"linesTerminated\\\":\\\"\\\\\\\\n\\\"}\",\"localParams\":[]}"; |
||||
SqoopParameters hdfsToMysqlParams = JSONUtils.parseObject(hdfsToMysql, SqoopParameters.class); |
||||
String hdfsToMysqlScript = generator.generateSqoopJob(hdfsToMysqlParams, mysqlTaskExecutionContext); |
||||
String hdfsToMysqlScriptExpected = |
||||
"sqoop export -D mapred.job.name=sqoop_import -m 1 --export-dir /ods/tmp/test/person7 --connect " |
||||
+ "\"jdbc:mysql://192.168.0.111:3306/test?allowLoadLocalInfile=false&autoDeserialize=false&allowLocalInfile=false&allowUrlInLocalInfile=false\" " |
||||
+ "--username kylo --password \"123456\" --table person_3 --columns id,name,age,sex,create_time --fields-terminated-by '@' " |
||||
+ "--lines-terminated-by '\\n' --update-key id --update-mode allowinsert"; |
||||
Assert.assertEquals(hdfsToMysqlScriptExpected, hdfsToMysqlScript); |
||||
|
||||
//export hive to mysql
|
||||
String hiveToMysql = |
||||
"{\"jobName\":\"sqoop_import\",\"jobType\":\"TEMPLATE\",\"concurrency\":1,\"modelType\":\"export\",\"sourceType\":\"HIVE\"," |
||||
+ "\"targetType\":\"MYSQL\",\"sourceParams\":\"{\\\"hiveDatabase\\\":\\\"stg\\\",\\\"hiveTable\\\":\\\"person_internal\\\"," |
||||
+ "\\\"hivePartitionKey\\\":\\\"date\\\",\\\"hivePartitionValue\\\":\\\"2020-02-17\\\"}\"," |
||||
+ "\"targetParams\":\"{\\\"targetDatasource\\\":2,\\\"targetTable\\\":\\\"person_3\\\",\\\"targetColumns\\\":\\\"\\\",\\\"preQuery\\\":\\\"\\\"," |
||||
+ "\\\"isUpdate\\\":false,\\\"targetUpdateKey\\\":\\\"\\\",\\\"targetUpdateMode\\\":\\\"allowinsert\\\",\\\"fieldsTerminated\\\":\\\"@\\\"," |
||||
+ "\\\"linesTerminated\\\":\\\"\\\\\\\\n\\\"}\",\"localParams\":[]}"; |
||||
SqoopParameters hiveToMysqlParams = JSONUtils.parseObject(hiveToMysql, SqoopParameters.class); |
||||
String hiveToMysqlScript = generator.generateSqoopJob(hiveToMysqlParams, mysqlTaskExecutionContext); |
||||
String hiveToMysqlExpected = |
||||
"sqoop export -D mapred.job.name=sqoop_import -m 1 --hcatalog-database stg --hcatalog-table person_internal --hcatalog-partition-keys date " |
||||
+ "--hcatalog-partition-values 2020-02-17 --connect \"jdbc:mysql://192.168.0.111:3306/test?allowLoadLocalInfile=" |
||||
+ "false&autoDeserialize=false&allowLocalInfile=false&allowUrlInLocalInfile=false\" --username kylo --password \"123456\" --table person_3 " |
||||
+ "--fields-terminated-by '@' --lines-terminated-by '\\n'"; |
||||
Assert.assertEquals(hiveToMysqlExpected, hiveToMysqlScript); |
||||
|
||||
//import mysql to hive
|
||||
String mysqlToHive = |
||||
"{\"jobName\":\"sqoop_import\",\"jobType\":\"TEMPLATE\",\"concurrency\":1,\"modelType\":\"import\",\"sourceType\":\"MYSQL\",\"targetType\":\"HIVE\"," |
||||
+ "\"sourceParams\":\"{\\\"srcDatasource\\\":2,\\\"srcTable\\\":\\\"person_2\\\",\\\"srcQueryType\\\":\\\"1\\\"," |
||||
+ "\\\"srcQuerySql\\\":\\\"SELECT * FROM person_2\\\",\\\"srcColumnType\\\":\\\"0\\\",\\\"srcColumns\\\":\\\"\\\",\\\"srcConditionList\\\":[]," |
||||
+ "\\\"mapColumnHive\\\":[],\\\"mapColumnJava\\\":[{\\\"prop\\\":\\\"id\\\",\\\"direct\\\":\\\"IN\\\",\\\"type\\\":\\\"VARCHAR\\\",\\\"value\\\":\\\"Integer\\\"}]}\"," |
||||
+ "\"targetParams\":\"{\\\"hiveDatabase\\\":\\\"stg\\\",\\\"hiveTable\\\":\\\"person_internal_2\\\",\\\"createHiveTable\\\":true,\\\"dropDelimiter\\\":false," |
||||
+ "\\\"hiveOverWrite\\\":true,\\\"replaceDelimiter\\\":\\\"\\\",\\\"hivePartitionKey\\\":\\\"date\\\",\\\"hivePartitionValue\\\":\\\"2020-02-16\\\"}\",\"localParams\":[]}"; |
||||
SqoopParameters mysqlToHiveParams = JSONUtils.parseObject(mysqlToHive, SqoopParameters.class); |
||||
String mysqlToHiveScript = generator.generateSqoopJob(mysqlToHiveParams, mysqlTaskExecutionContext); |
||||
String mysqlToHiveExpected = |
||||
"sqoop import -D mapred.job.name=sqoop_import -m 1 --connect \"jdbc:mysql://192.168.0.111:3306/" |
||||
+ "test?allowLoadLocalInfile=false&autoDeserialize=false&allowLocalInfile=false&allowUrlInLocalInfile=false\" " |
||||
+ "--username kylo --password \"123456\" " |
||||
+ "--query \"SELECT * FROM person_2 WHERE \\$CONDITIONS\" --map-column-java id=Integer --hive-import --hive-database stg --hive-table person_internal_2 " |
||||
+ "--create-hive-table --hive-overwrite --delete-target-dir --hive-partition-key date --hive-partition-value 2020-02-16"; |
||||
Assert.assertEquals(mysqlToHiveExpected, mysqlToHiveScript); |
||||
|
||||
//sqoop CUSTOM job
|
||||
String sqoopCustomString = "{\"jobType\":\"CUSTOM\",\"localParams\":[],\"customShell\":\"sqoop import\"}"; |
||||
SqoopParameters sqoopCustomParams = JSONUtils.parseObject(sqoopCustomString, SqoopParameters.class); |
||||
String sqoopCustomScript = generator.generateSqoopJob(sqoopCustomParams, new TaskExecutionContext()); |
||||
String sqoopCustomExpected = "sqoop import"; |
||||
Assert.assertEquals(sqoopCustomExpected, sqoopCustomScript); |
||||
|
||||
} |
||||
|
||||
/** |
||||
* get taskExecutionContext include mysql |
||||
* |
||||
* @return TaskExecutionContext |
||||
*/ |
||||
private TaskExecutionContext getMysqlTaskExecutionContext() { |
||||
TaskExecutionContext taskExecutionContext = new TaskExecutionContext(); |
||||
SqoopTaskExecutionContext sqoopTaskExecutionContext = new SqoopTaskExecutionContext(); |
||||
String mysqlSourceConnectionParams = |
||||
"{\"address\":\"jdbc:mysql://192.168.0.111:3306\",\"database\":\"test\",\"jdbcUrl\":\"jdbc:mysql://192.168.0.111:3306/test\",\"user\":\"kylo\",\"password\":\"123456\"}"; |
||||
String mysqlTargetConnectionParams = |
||||
"{\"address\":\"jdbc:mysql://192.168.0.111:3306\",\"database\":\"test\",\"jdbcUrl\":\"jdbc:mysql://192.168.0.111:3306/test\",\"user\":\"kylo\",\"password\":\"123456\"}"; |
||||
sqoopTaskExecutionContext.setDataSourceId(2); |
||||
sqoopTaskExecutionContext.setDataTargetId(2); |
||||
sqoopTaskExecutionContext.setSourcetype(0); |
||||
sqoopTaskExecutionContext.setTargetConnectionParams(mysqlTargetConnectionParams); |
||||
sqoopTaskExecutionContext.setSourceConnectionParams(mysqlSourceConnectionParams); |
||||
sqoopTaskExecutionContext.setTargetType(0); |
||||
taskExecutionContext.setSqoopTaskExecutionContext(sqoopTaskExecutionContext); |
||||
return taskExecutionContext; |
||||
} |
||||
|
||||
@Test |
||||
public void testGetParameters() { |
||||
Assert.assertNotNull(sqoopTask.getParameters()); |
||||
} |
||||
|
||||
/** |
||||
* Method: init |
||||
*/ |
||||
@Test |
||||
public void testInit() { |
||||
try { |
||||
sqoopTask.init(); |
||||
} catch (Exception e) { |
||||
Assert.fail(e.getMessage()); |
||||
} |
||||
} |
||||
|
||||
@Test |
||||
public void testLogHandler() throws InterruptedException { |
||||
LinkedBlockingQueue<String> loggerBuffer = new LinkedBlockingQueue<>(); |
||||
Thread thread1 = new Thread(() -> { |
||||
for (int i = 0; i < 10; i++) { |
||||
loggerBuffer.add("test add log"); |
||||
} |
||||
}); |
||||
Thread thread2 = new Thread(() -> { |
||||
for (int i = 0; i < 10; i++) { |
||||
sqoopTask.logHandle(loggerBuffer); |
||||
} |
||||
}); |
||||
thread1.start(); |
||||
thread2.start(); |
||||
thread1.join(); |
||||
thread2.join(); |
||||
// if no exception throw, assert true
|
||||
Assert.assertTrue(true); |
||||
} |
||||
|
||||
} |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue