fix: ASW-164 playbook 添加 cancel 接口

This commit is contained in:
zhangshuai
2024-11-14 14:28:30 +08:00
parent 8b540ba127
commit 7eb847d7bf
2 changed files with 55 additions and 8 deletions

View File

@@ -1,6 +1,7 @@
package net.geedge.api.controller; package net.geedge.api.controller;
import cn.hutool.core.codec.Base32Codec; import cn.hutool.core.codec.Base32Codec;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.io.FileUtil; import cn.hutool.core.io.FileUtil;
import cn.hutool.core.thread.ThreadUtil; import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.log.Log; import cn.hutool.log.Log;
@@ -29,6 +30,8 @@ public class APIController {
private final AdbUtil adbUtil; private final AdbUtil adbUtil;
static final List<Thread> ACTIVE_TASKS = Collections.synchronizedList(new ArrayList<>());
@Autowired @Autowired
public APIController(EnvApiYml envApiYml) { public APIController(EnvApiYml envApiYml) {
this.adbUtil = AdbUtil.getInstance(envApiYml.getAdb(), new CommandExec(null)); this.adbUtil = AdbUtil.getInstance(envApiYml.getAdb(), new CommandExec(null));
@@ -305,6 +308,7 @@ public class APIController {
T.FileUtil.del(destination); T.FileUtil.del(destination);
} }
PlaybookRunnable playbookRunnable = new PlaybookRunnable(apiYml, apkFile, playbookAirDir, id, packageName); PlaybookRunnable playbookRunnable = new PlaybookRunnable(apiYml, apkFile, playbookAirDir, id, packageName);
playbookRunnable.setName(T.StrUtil.concat(true, id, "-", apkFile.getName()));
ThreadUtil.execAsync(playbookRunnable); ThreadUtil.execAsync(playbookRunnable);
return R.ok(); return R.ok();
} }
@@ -319,6 +323,20 @@ public class APIController {
return R.ok().putData(status); return R.ok().putData(status);
} }
@DeleteMapping("/playbook/{id}")
public R cancel(@PathVariable("id") String id){
if (T.StrUtil.isEmpty(id)) {
throw new APIException(RCode.BAD_REQUEST);
}
if (CollUtil.isNotEmpty(ACTIVE_TASKS)) {
ACTIVE_TASKS.stream().filter(thread -> T.StrUtil.startWith(thread.getName(), id)).forEach(thread -> {
log.info(String.format("playbook thread: %s has been canceled", thread.getName()));
thread.interrupt();
});
}
return R.ok();
}
@GetMapping("/playbook/{id}/log") @GetMapping("/playbook/{id}/log")
public R getJobResultLog(@PathVariable("id") String id, public R getJobResultLog(@PathVariable("id") String id,
@@ -388,6 +406,7 @@ public class APIController {
private File apkFile; private File apkFile;
private String packageName; private String packageName;
private File playbookDir; private File playbookDir;
private boolean interrupt;
public PlaybookRunnable(EnvApiYml envApiYml, File apkFile, File playbookDir, String tid, String packageName) { public PlaybookRunnable(EnvApiYml envApiYml, File apkFile, File playbookDir, String tid, String packageName) {
this.envApiYml = envApiYml; this.envApiYml = envApiYml;
@@ -395,10 +414,12 @@ public class APIController {
this.apkFile = apkFile; this.apkFile = apkFile;
this.packageName = packageName; this.packageName = packageName;
this.playbookDir = playbookDir; this.playbookDir = playbookDir;
this.interrupt = false;
} }
@Override @Override
public void run() { public void run() {
ACTIVE_TASKS.add(this);
File logFile = FileUtil.file(Constant.TEMP_PATH, tid, "result.log"); File logFile = FileUtil.file(Constant.TEMP_PATH, tid, "result.log");
File statusFile = FileUtil.file(Constant.TEMP_PATH, tid, "result.json"); File statusFile = FileUtil.file(Constant.TEMP_PATH, tid, "result.json");
AdbUtil.CommandResult tcpdumpPackage = null; AdbUtil.CommandResult tcpdumpPackage = null;
@@ -414,6 +435,7 @@ public class APIController {
T.FileUtil.writeString(T.JSONUtil.toJsonStr(resultMap), statusFile, "UTF-8"); T.FileUtil.writeString(T.JSONUtil.toJsonStr(resultMap), statusFile, "UTF-8");
// install apk // install apk
if (interrupt) return;
AdbUtil.CommandResult install = adbUtil.install(apkFile.getAbsolutePath(), true, true); AdbUtil.CommandResult install = adbUtil.install(apkFile.getAbsolutePath(), true, true);
if (0 != install.exitCode()) { if (0 != install.exitCode()) {
T.FileUtil.appendString(String.format("ERROR: Install apk failed: exit code %s \n", install.exitCode()), logFile, "UTF-8"); T.FileUtil.appendString(String.format("ERROR: Install apk failed: exit code %s \n", install.exitCode()), logFile, "UTF-8");
@@ -421,6 +443,7 @@ public class APIController {
} }
// clear app data // clear app data
if (interrupt) return;
AdbUtil.CommandResult clearData = adbUtil.clearAppData(packageName); AdbUtil.CommandResult clearData = adbUtil.clearAppData(packageName);
if (0 != clearData.exitCode()) { if (0 != clearData.exitCode()) {
T.FileUtil.appendString(String.format("ERROR: Clear %s data error: exit code %s \n", packageName, install.exitCode()), logFile, "UTF-8"); T.FileUtil.appendString(String.format("ERROR: Clear %s data error: exit code %s \n", packageName, install.exitCode()), logFile, "UTF-8");
@@ -428,6 +451,7 @@ public class APIController {
} }
// star tcpdump: package name // star tcpdump: package name
if (interrupt) return;
tcpdumpPackage = adbUtil.startTcpdump(packageName); tcpdumpPackage = adbUtil.startTcpdump(packageName);
if (0 != tcpdumpPackage.exitCode()) { if (0 != tcpdumpPackage.exitCode()) {
T.FileUtil.appendString(String.format("ERROR: Start tcpdump %s failed: exit code %s \n", packageName, tcpdumpPackage.exitCode()), logFile, "UTF-8"); T.FileUtil.appendString(String.format("ERROR: Start tcpdump %s failed: exit code %s \n", packageName, tcpdumpPackage.exitCode()), logFile, "UTF-8");
@@ -435,6 +459,7 @@ public class APIController {
} }
// star tcpdump: all // star tcpdump: all
if (interrupt) return;
tcpdumpAll = adbUtil.startTcpdump(T.StrUtil.EMPTY); tcpdumpAll = adbUtil.startTcpdump(T.StrUtil.EMPTY);
if (0 != tcpdumpAll.exitCode()) { if (0 != tcpdumpAll.exitCode()) {
T.FileUtil.appendString(String.format("ERROR: Start tcpdump all failed: exit code %s \n", tcpdumpAll.exitCode()), logFile, "UTF-8"); T.FileUtil.appendString(String.format("ERROR: Start tcpdump all failed: exit code %s \n", tcpdumpAll.exitCode()), logFile, "UTF-8");
@@ -442,6 +467,7 @@ public class APIController {
} }
// exec playbook // exec playbook
if (interrupt) return;
AdbUtil.CommandResult airtestResult = adbUtil.execPlaybook(playbookDir.getPath(), logFile); AdbUtil.CommandResult airtestResult = adbUtil.execPlaybook(playbookDir.getPath(), logFile);
if (0 != airtestResult.exitCode()) { if (0 != airtestResult.exitCode()) {
T.FileUtil.appendString(String.format("ERROR: Exec playbook failed: exit code %s \n", airtestResult.exitCode()), logFile, "UTF-8"); T.FileUtil.appendString(String.format("ERROR: Exec playbook failed: exit code %s \n", airtestResult.exitCode()), logFile, "UTF-8");
@@ -449,9 +475,11 @@ public class APIController {
} }
// stop package tcpdump // stop package tcpdump
if (interrupt) return;
stopTcpdump(tcpdumpPackage, logFile, packageName); stopTcpdump(tcpdumpPackage, logFile, packageName);
// stop all tcpdump // stop all tcpdump
if (interrupt) return;
stopTcpdump(tcpdumpAll, logFile, T.StrUtil.EMPTY); stopTcpdump(tcpdumpAll, logFile, T.StrUtil.EMPTY);
resultMap = T.MapUtil.builder() resultMap = T.MapUtil.builder()
@@ -464,17 +492,28 @@ public class APIController {
.put("status", "error") .put("status", "error")
.build(); .build();
T.FileUtil.writeString(T.JSONUtil.toJsonStr(resultMap), statusFile, "UTF-8"); T.FileUtil.writeString(T.JSONUtil.toJsonStr(resultMap), statusFile, "UTF-8");
AdbUtil.CommandResult packageTcpdump = adbUtil.stopTcpdump(tcpdumpPackage.output());
adbUtil.execShellCommand(String.format("shell rm -rf %s", packageTcpdump.output()));
AdbUtil.CommandResult allTcpdump = adbUtil.stopTcpdump(tcpdumpAll.output());
adbUtil.execShellCommand(String.format("shell rm -rf %s", allTcpdump.output()));
} finally { } finally {
if (T.StrUtil.isNotEmpty(tcpdumpPackage.output())){
AdbUtil.CommandResult packageTcpdump = adbUtil.stopTcpdump(tcpdumpPackage.output());
adbUtil.execShellCommand(String.format("shell rm -rf %s", packageTcpdump.output()));
}
if (T.StrUtil.isNotEmpty(tcpdumpAll.output())){
AdbUtil.CommandResult allTcpdump = adbUtil.stopTcpdump(tcpdumpAll.output());
adbUtil.execShellCommand(String.format("shell rm -rf %s", allTcpdump.output()));
}
adbUtil.stopApp(packageName); adbUtil.stopApp(packageName);
T.FileUtil.appendString(String.format("Job succeeded"), logFile, "UTF-8"); T.FileUtil.appendString(String.format("Job succeeded"), logFile, "UTF-8");
ACTIVE_TASKS.remove(this);
} }
} }
@Override
public void interrupt() {
super.interrupt();
this.interrupt = true;
adbUtil.setInterrupt(true);
}
private void stopTcpdump(AdbUtil.CommandResult tcpdump, File logFile, String packageName) { private void stopTcpdump(AdbUtil.CommandResult tcpdump, File logFile, String packageName) {
// stop tcpdump // stop tcpdump
AdbUtil.CommandResult stopTcpdump = adbUtil.stopTcpdump(tcpdump.output()); AdbUtil.CommandResult stopTcpdump = adbUtil.stopTcpdump(tcpdump.output());

View File

@@ -9,9 +9,7 @@ import net.geedge.common.Constant;
import net.geedge.common.RCode; import net.geedge.common.RCode;
import net.geedge.common.T; import net.geedge.common.T;
import java.io.BufferedReader; import java.io.*;
import java.io.File;
import java.io.InputStreamReader;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.util.*; import java.util.*;
import java.util.concurrent.*; import java.util.concurrent.*;
@@ -37,6 +35,8 @@ public class AdbUtil {
private CommandExec commandExec; private CommandExec commandExec;
private boolean interrupt;
private ExecutorService threadPool; private ExecutorService threadPool;
@@ -44,6 +44,10 @@ public class AdbUtil {
return T.StrUtil.isNotEmpty(this.serial) ? serial : String.format("%s:%s", this.host, this.port); return T.StrUtil.isNotEmpty(this.serial) ? serial : String.format("%s:%s", this.host, this.port);
} }
public void setInterrupt(boolean interrupt) {
this.interrupt = interrupt;
}
public record CommandResult(Integer exitCode, String output) { public record CommandResult(Integer exitCode, String output) {
} }
@@ -870,6 +874,10 @@ public class AdbUtil {
bufferedReader = new BufferedReader(inputStreamReader); bufferedReader = new BufferedReader(inputStreamReader);
String line; String line;
while ((line = bufferedReader.readLine()) != null) { while ((line = bufferedReader.readLine()) != null) {
if (T.ObjectUtil.isNotNull(interrupt) && interrupt){
log.info("[PlaybookRunnable] [execPlaybook] [stop exec playbook]");
process.destroyForcibly();
}
// 处理每一行输出 // 处理每一行输出
T.FileUtil.appendString(T.StrUtil.concat(true, line, "\n"), logFile, "UTF-8"); T.FileUtil.appendString(T.StrUtil.concat(true, line, "\n"), logFile, "UTF-8");
} }