Compare commits

...

17 Commits

Author SHA1 Message Date
郑明仁 706a341b0b update 2019-08-19 08:38:18 +08:00
郑明仁 0d29d7a136 优化 2019-08-16 10:16:51 +08:00
郑明仁 9b08265ada 优化 2019-08-16 09:59:47 +08:00
郑明仁 ef97c856d1 修改评测脚本设置 2019-08-15 17:19:28 +08:00
郑明仁 a903f54b44 update 2019-08-15 17:02:18 +08:00
郑明仁 2ac89342bc update 2019-08-15 09:04:08 +08:00
郑明仁 1245e1ce28 单个文件评测 2019-08-14 17:09:04 +08:00
郑明仁 02d32b147c update 2019-08-14 16:13:36 +08:00
郑明仁 44ee8144a4 update 2019-08-14 15:54:05 +08:00
郑明仁 385c245977 update 2019-08-14 15:52:33 +08:00
郑明仁 c3ff401bb4 update 2019-08-14 15:50:59 +08:00
郑明仁 05801ad68b update 2019-08-14 15:07:04 +08:00
郑明仁 1975fd04c6 update 2019-08-14 14:52:01 +08:00
郑明仁 0f5b3404be update 2019-08-14 14:48:08 +08:00
郑明仁 420b5023da update 2019-08-14 14:45:59 +08:00
郑明仁 0a16a8c0ae update single 2019-08-14 14:15:02 +08:00
郑明仁 25cdc66972 single_file_eva 2019-08-14 11:11:18 +08:00
15 changed files with 679 additions and 8 deletions

View File

@ -84,6 +84,9 @@ public class AppConfig {
@Value("${k8s.serverUrl}")
private String k8sServerUrl;
@Value("${singleEvaCode}")
private String singleEvaCode;
private String bridgeInstanceName = IpUtils.getLocalIp();
public String getServerUrl() {
@ -222,4 +225,7 @@ public class AppConfig {
return bridgeInstanceName;
}
public String getSingleEvaCode() {
return singleEvaCode;
}
}

View File

@ -20,6 +20,10 @@ public abstract class TpUtils {
return tpiWorkspace + File.separator + tpiRepoName;
}
public static String buildCodeFileNamePath(String codeFileName) {
return "src" + File.separator + codeFileName;
}
/**
* 转化评测pod类型
*

View File

@ -3,6 +3,7 @@ package com.educoder.bridge.game.controller;
import java.io.File;
import java.time.LocalDateTime;
import com.educoder.bridge.game.thread.SingleEvaThread;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -212,6 +213,113 @@ public class GameController {
return response;
}
/**
* 单个文件评测
*/
@RequestMapping(path = "/singleEvaluate")
@ApiOperation(value = "单个文件评测", httpMethod = "POST", produces = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
public JSONObject singleEvaluate(
@ApiParam(name = "tpiID", required = true, value = "实训实例的ID") @RequestParam String tpiID,
@ApiParam(name = "buildID", required = true, value = "本次评测ID") @RequestParam String buildID,
@ApiParam(name = "isPublished", required = false, value = "实训是否已经发布1代表调试模式实训未发布") @RequestParam Integer isPublished,
@ApiParam(name = "instanceChallenge", required = true, value = "当前处在第几关") @RequestParam String instanceChallenge,
@ApiParam(name = "testCases", required = true, value = "测试用例") @RequestParam String testCases,
@ApiParam(name = "codeFileName", required = true, value = "代码文件名") @RequestParam String codeFileName,
@ApiParam(name = "evaScriptType", required = true, value = "代码评测脚本类型") @RequestParam String evaScriptType,
@ApiParam(name = "codeFile", required = true, value = "代码文件") @RequestParam String codeFile,
@ApiParam(name = "timeLimit", required = false, value = "时间限制") Integer timeLimit,
@ApiParam(name = "resubmit", required = true, value = "是否是重复评测") @RequestParam String resubmit,
@ApiParam(name = "needPortMapping", required = false, value = "容器中需要被映射的端口") Integer needPortMapping,
@ApiParam(name = "podType", required = true, value = "pod类型(0.evaluate1.webssh2.evassh)") @RequestParam Integer podType,
@ApiParam(name = "file", required = false, value = "需要传文件的实训,给出文件存放路径(一个目录)及文件类型") String file,
@ApiParam(name = "containers", required = true, value = "需要使用的容器,base64编码") @RequestParam String containers,
@ApiParam(name = "sec_key", required = false, value = "每一次评测的唯一标识") String sec_key) throws Exception {
logger.info("[start]单个文件评测tpiID: {}, buildID: {}, isPublished: {}, instanceChallenge: {}, "
+ "testCases: {}, codeFile: {}, timeLimit: {}, resubmit: {}, "
+ "needPortMapping: {}, podType: {}, file: {}, containers: {}, sec_key: {}",
tpiID, buildID, isPublished, instanceChallenge, testCases, codeFile, timeLimit, resubmit,
needPortMapping, podType, file, containers, sec_key);
// 记录开始时间
LocalDateTime requestTime = LocalDateTime.now();
String evaluateStartTime = requestTime.toString();
JSONObject cost = new JSONObject();
cost.put("evaluateStartTime", evaluateStartTime);
JedisUtil.set("timeCost:" + tpiID + ":" + buildID, cost.toJSONString());
JSONObject response = new JSONObject();
// 参数处理
needPortMapping = needPortMapping == null ? 0 : needPortMapping;
timeLimit = timeLimit == null ? Integer.parseInt(appConfig.getDefaultTimeLimit()) : timeLimit;
testCases = Base64Util.decode(testCases);
containers = Base64Util.decode(containers);
// 每次评测均生成新评测脚本
String tpiWorkspace = TpUtils.buildTpiWorkspace(appConfig.getWorkspace(), tpiID);
gameService.generateEvaluateShellScript(tpiWorkspace, evaScriptType);
codeFile = Base64Util.decode(codeFile);
codeFileName = TpUtils.buildCodeFileNamePath(codeFileName);
gameService.generateEvaluateCodeFile(tpiWorkspace, codeFileName, codeFile);
String tpiRepoPath = TpUtils.buildTpiRepoPath(tpiWorkspace, appConfig.getSingleEvaCode());
JSONObject buildParams = new JSONObject(true);
buildParams.put("tpiID", tpiID);
buildParams.put("buildID", buildID);
buildParams.put("isPublished", isPublished);
buildParams.put("instanceChallenge", instanceChallenge);
buildParams.put("testCases", testCases);
buildParams.put("timeLimit", timeLimit);
buildParams.put("resubmit", resubmit);
buildParams.put("needPortMapping", needPortMapping);
buildParams.put("podType", podType);
buildParams.put("containers", containers);
buildParams.put("codeFileName", codeFileName);
buildParams.put("sec_key", sec_key);
buildParams.put("tpiRepoPath", tpiRepoPath);
// 若实训生成文件 todo:这个处理方式好2b扩展性极差
if (!StringUtils.isEmpty(file)) {
file = Base64Util.decode(file);
buildParams.put("file", file);
// 清空目标文件夹以防止影响此次评测结果
GameHelper.clearFiles(tpiRepoPath + File.separator
+ JSONObject.parseObject(file).getString("path"));
}
// podName
String podName = podType != 2 ? "evaluate-" + tpiID : "evassh-" + tpiID;
BridgePod bridgePod = bridgePodService.createBridgePod(podName, tpiID, requestTime, sec_key);
buildParams.put("bridgePodId", bridgePod.getId());
// 若需要端口映射服务则分配端口将podName-port键值对存储于redis
String port = "-1";
if (needPortMapping != -1) {
port = portService.allocatePort() + "";
JedisUtil.hset("port", podName, port);
}
sendSingleToKafka(buildParams, tpiID, requestTime);
response.put("ableToCreate", 1);
response.put("costTime", System.currentTimeMillis() - TimeHelper.convertTimeToMillis(evaluateStartTime));
response.put("waitNum", 0);
response.put("code", 0);
response.put("port", port);
response.put("msg", "评测完成");
logger.info("[end]单个文件评测tpiID: {}, buildID: {}", tpiID, buildID);
return response;
}
private void sendSingleToKafka(JSONObject buildparams, String tpiID, final LocalDateTime requestTime) {
SingleEvaThread singleEvaThread = gameService.getSingleEvaThread(buildparams);
threadPoolTaskExecutor.execute(singleEvaThread);
}
private void sendToKafka(JSONObject buildParams, String tpiID, final LocalDateTime requestTime) {
BuildThread buildThread = gameService.getBuildThread(buildParams);
threadPoolTaskExecutor.execute(buildThread);

View File

@ -13,11 +13,12 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.educoder.bridge.game.thread.SingleEvaThread;
import com.educoder.bridge.k8s.service.EvaScriptService;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
@ -67,6 +68,9 @@ public class GameService {
@Autowired
ResourceFileService resourceFileService;
@Autowired
private EvaScriptService evaScriptService;
private static final Logger logger = LoggerFactory.getLogger(GameService.class);
/**
@ -679,7 +683,18 @@ public class GameService {
BuildThread buildThread = (BuildThread) BeanFactory.getObejct("BuildThread");
buildThread.setBuildParams(buildParams);
return buildThread;
}
/**
* 根据单个文件评测信息构建一个singleEvaThread
*
* @param buildParams
* @return
*/
public SingleEvaThread getSingleEvaThread(JSONObject buildParams) {
SingleEvaThread singleEvaThread = (SingleEvaThread) BeanFactory.getObejct("singleEvaThread");
singleEvaThread.setBuildParams(buildParams);
return singleEvaThread;
}
/**
@ -824,4 +839,52 @@ public class GameService {
return result;
}
public void generateEvaluateShellScript(String tpiWorkspace, String evaScriptType) throws GameException {
logger.debug("tpiWorkspace: {}, evaScriptType: {}", tpiWorkspace, evaScriptType);
// 获取脚本
String script = evaScriptService.getScriptByType(evaScriptType);
if (StringUtils.isEmpty(script)) {
logger.error("生成评测脚本失败: 无该类型评测脚本");
throw new GameException(-1, "生成评测脚本失败: 无该类型评测脚本");
}
script = Base64Util.decode(script);
script = script.replace("WORKSPACE", TpUtils.buildTpiRepoPath(tpiWorkspace, appConfig.getSingleEvaCode().split("/")[0]));
try {
// 写脚本到工作空间目录下
FileUtils.deleteQuietly(new File(tpiWorkspace + File.separator + "evaluate.sh"));
FileUtils.writeStringToFile(new File(tpiWorkspace + File.separator + "evaluate.sh"), script, "UTF-8");
} catch (Exception e) {
logger.error("生成评测脚本失败!{}", e);
throw new GameException(-1, "生成评测脚本失败");
}
try {
String content = resourceFileService.getResourceFileContent("evaluate/execeva.sh");
FileUtils.deleteQuietly(new File(tpiWorkspace + File.separator + "execeva.sh"));
FileUtils.writeStringToFile(new File(tpiWorkspace + File.separator + "execeva.sh"), content, "UTF-8");
} catch (Exception e) {
logger.error("生成评测脚本execeva失败!{}", e);
throw new GameException(-1, "生成评测脚本execeva失败");
}
}
public void generateEvaluateCodeFile(String tpiWorkspace, String codeFileName, String codeFile) throws GameException {
logger.debug("生成评测代码文件: tpiWorkspace: {}, codeFileName: {}", tpiWorkspace, codeFileName);
String codeFilePath = tpiWorkspace + File.separator + appConfig.getSingleEvaCode() + File.separator + codeFileName;
try {
// 写脚本到工作空间目录下
FileUtils.deleteQuietly(new File(codeFilePath));
FileUtils.writeStringToFile(new File(codeFilePath), codeFile, "UTF-8");
} catch (Exception e) {
logger.error("生成评测代码文件失败!{}", e);
throw new GameException(-1, "生成评测代码文件失败");
}
}
}

View File

@ -1,6 +1,7 @@
package com.educoder.bridge.game.service;
import java.io.File;
import java.time.Duration;
import java.time.Instant;
@ -50,7 +51,7 @@ public class KubernetesService {
* 在pod中执行评测脚本
*/
public void executeShellInPod(JSONObject buildParams, Pod pod, int needPortMapping, int timeLimit, int isPublished,
int instanceChallenge, String testCases) {
int instanceChallenge, String testCases, Boolean isSingleEva) {
String podName = pod.getMetadata().getName();
logger.debug("podName: {}, needPortMapping: {}, timeLimit: {}, isPublished: {}, instanceChallenge: {}", podName,
needPortMapping, timeLimit, isPublished, instanceChallenge);
@ -67,7 +68,11 @@ public class KubernetesService {
String buildID = buildParams.getString("buildID");
String tpiWorkspace = TpUtils.buildTpiWorkspace(appConfig.getWorkspace(), tpiID);
String shFile = tpiWorkspace + "/evaluate.sh";
String command = " timeout " + timeLimit + " kubectl exec " + podName + " timeout " + timeLimit + " bash " + shFile + " " + instanceChallenge + " " + ins;
String command = " timeout " + timeLimit + " kubectl exec " + podName + " timeout " + timeLimit + " bash " + shFile + " " + instanceChallenge + " " + ins;
if (isSingleEva) {
String codeFileName = buildParams.getString("codeFileName");
command = " timeout " + timeLimit + " kubectl exec " + podName + " timeout " + timeLimit + " bash " + shFile + " " + codeFileName + " " + ins;
}
logger.info("evaluate command: {}", command);
// 为pod的score加1若pod之前不存在则score为1
JedisUtil.zup("taskNum", podName);

View File

@ -179,7 +179,7 @@ public class BuildThread extends Thread {
: buildParams.getInteger("executeTime");
kubernetesService.executeShellInPod(buildParams, podRef.getPod(), buildParams.getInteger("needPortMapping"),
executeTimeLimit, buildParams.getInteger("isPublished"), buildParams.getInteger("instanceChallenge"),
buildParams.getString("testCases"));
buildParams.getString("testCases"), Boolean.FALSE);
}

View File

@ -0,0 +1,127 @@
package com.educoder.bridge.game.thread;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.educoder.bridge.common.constant.BuildResultCsts;
import com.educoder.bridge.common.settings.AppConfig;
import com.educoder.bridge.common.utils.GameHelper;
import com.educoder.bridge.game.model.PodRef;
import com.educoder.bridge.game.service.GameService;
import com.educoder.bridge.game.service.K8sService;
import com.educoder.bridge.game.service.KubernetesService;
import com.educoder.bridge.k8s.service.RunPodService;
import io.fabric8.kubernetes.api.model.Pod;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;
import java.time.Duration;
import java.time.Instant;
import java.util.HashMap;
import java.util.Map;
/**
* 单个文件评测线程
*/
@Service("singleEvaThread")
@Scope("prototype")
public class SingleEvaThread extends Thread {
private final Logger logger = LoggerFactory.getLogger(getClass());
@Autowired
private GameService gameService;
@Autowired
private KubernetesService kubernetesService;
@Autowired
private K8sService k8sService;
@Autowired
private RunPodService runPodService;
private JSONObject buildParams;
public SingleEvaThread() {
}
public SingleEvaThread(JSONObject buildParams) {
this();
this.buildParams = buildParams;
}
public void setBuildParams(JSONObject buildParams) {
this.buildParams = buildParams;
}
public JSONObject getBuildParams() {
return buildParams;
}
@Override
public void run() {
String tpiID = buildParams.getString("tpiID");
String buildID = buildParams.getString("buildID");
Map<String, String> podInLabels = new HashMap<>(1);
Map<String, String> podNotInLabels = new HashMap<>(1);
podInLabels.put("tpiID", tpiID);
podInLabels.put("type", "evaluate,evassh");
String type = buildParams.getInteger("podType") != 2 ? "evaluate" : "evassh";
String testCases = buildParams.getString("testCases");
String out = GameHelper.getTextMsgResult("服务启动中...");
gameService.encapsulateStepByStepResult(out, buildParams, testCases);
Instant podStartInstant = Instant.now();
// 设立(重设)对应pod的定时删除任务这个时间必须大于${timeLimit}确保脚本执行期间pod不会中途死 单位
int timeLimit = buildParams.getInteger("timeLimit");
gameService.reTiming(type + "-" + tpiID, timeLimit + 60);
// 查询 pod
Pod pod = k8sService.getK8sRunningPod(podInLabels, podNotInLabels);
// 如果pod不存在还将创建
pod = runPodService.createRunPod(pod, buildParams, tpiID, type, timeLimit);
final PodRef podRef = new PodRef();
if (pod != null) {
podRef.setPod(pod);
String podName = pod.getMetadata().getName();
double createPodAndSvcCost = (double) Duration.between(podStartInstant, Instant.now()).toMillis()
/ 1000;
podRef.setCreatePodAndSvcCost(createPodAndSvcCost);
// 设立(重设)对应pod的定时删除任务这个时间必须大于${timeLimit}确保脚本执行期间pod不会中途死 单位
gameService.reTiming(podName, timeLimit + 60);
}
JSONArray cases = JSONArray.parseArray(testCases);
if (podRef.getPod() == null) {
logger.error("实训 {} 创建 pod 失败", tpiID);
String msg = GameHelper.getResult("系统繁忙,请稍后重试", cases.size(), BuildResultCsts.DOWNLOAD_STATUS_SUCCESS,
BuildResultCsts.CREATE_POD_STATUS_FAIL);
gameService.encapsulateBuildResult(msg, buildParams, testCases);
return;
}
// 记录创建pod耗时
GameHelper.setTimeCostInJedis("timeCost:" + tpiID + ":" + buildID, "createPod",
String.format("%.3f", podRef.getCreatePodAndSvcCost()));
out = GameHelper.getTextMsgResult("服务启动完成");
gameService.encapsulateStepByStepResult(out, buildParams, testCases);
// 在pod中执行评测脚本
Integer executeTimeLimit = buildParams.getInteger("executeTime") == null ? buildParams.getInteger("timeLimit")
: buildParams.getInteger("executeTime");
kubernetesService.executeShellInPod(buildParams, podRef.getPod(), buildParams.getInteger("needPortMapping"),
executeTimeLimit, buildParams.getInteger("isPublished"), buildParams.getInteger("instanceChallenge"),
buildParams.getString("testCases"), Boolean.TRUE);
}
@Override
public String toString() {
return "singleEvaThread{" + buildParams.toJSONString() + '}';
}
}

View File

@ -0,0 +1,62 @@
package com.educoder.bridge.k8s.controller;
import com.alibaba.fastjson.JSONObject;
import com.educoder.bridge.k8s.model.EvaluatingScript;
import com.educoder.bridge.k8s.service.EvaScriptService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import java.time.LocalDateTime;
/**
* 评测脚本相关的接口
*/
@Api(value = "script", hidden = true)
@RestController
@RequestMapping("/script")
public class ScriptController {
private final Logger logger = LoggerFactory.getLogger(getClass());
@Autowired
private EvaScriptService evaScriptService;
/**
* 设置评测脚本
*/
@RequestMapping(path = "/set", method = RequestMethod.POST)
@ApiOperation(value = "设置评测脚本", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
public JSONObject set(
@ApiParam(name = "scriptType", required = true, value = "脚本类型") @RequestParam("scriptType") String scriptType,
@ApiParam(name = "script", required = true, value = "脚本") @RequestParam("script") String script
) throws Exception {
logger.info("[start]设置评测脚本, type: {}, script: {}", scriptType, script);
JSONObject response = new JSONObject();
LocalDateTime now = LocalDateTime.now();
EvaluatingScript evaluatingScript = evaScriptService.getEvaluatingScriptByType(scriptType);
if (evaluatingScript == null) {
evaluatingScript = new EvaluatingScript();
evaluatingScript.setScriptType(scriptType);
evaluatingScript.setScript(script);
evaluatingScript.setCreateTime(now);
evaluatingScript.setUpdateTime(now);
evaScriptService.saveEvaluationScript(evaluatingScript);
} else {
evaluatingScript.setScript(script);
evaluatingScript.setUpdateTime(now);
evaScriptService.updateEvaluatingScript(evaluatingScript);
}
response.put("code", 0);
response.put("msg", "设置评测脚本成功");
logger.info("[end]设置评测脚本");
return response;
}
}

View File

@ -0,0 +1,19 @@
package com.educoder.bridge.k8s.dao;
import com.educoder.bridge.k8s.model.EvaluatingScript;
public interface EvaScriptMapper {
int deleteByPrimaryKey(Long id);
int insert(EvaluatingScript record);
int insertSelective(EvaluatingScript record);
EvaluatingScript selectByPrimaryKey(Long id);
int updateByPrimaryKey(EvaluatingScript record);
EvaluatingScript selectScriptByType(String scriptType);
EvaluatingScript selectEvaScriptForUpdate(String scriptType);
}

View File

@ -0,0 +1,66 @@
package com.educoder.bridge.k8s.model;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import java.time.LocalDateTime;
/**
* 单个文件评测脚本
*/
@ApiModel(value = "evaluating_script", description = "单个文件评测脚本")
public class EvaluatingScript {
@ApiModelProperty(value = "脚本ID")
private long id;
@ApiModelProperty(value = "脚本类型")
private String scriptType;
@ApiModelProperty(value = "脚本")
private String script;
private LocalDateTime createTime;
private LocalDateTime updateTime;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getScriptType() {
return scriptType;
}
public void setScriptType(String scriptType) {
this.scriptType = scriptType;
}
public String getScript() {
return script;
}
public void setScript(String script) {
this.script = script;
}
public LocalDateTime getCreateTime() {
return createTime;
}
public void setCreateTime(LocalDateTime createTime) {
this.createTime = createTime;
}
public LocalDateTime getUpdateTime() {
return updateTime;
}
public void setUpdateTime(LocalDateTime updateTime) {
this.updateTime = updateTime;
}
}

View File

@ -0,0 +1,40 @@
package com.educoder.bridge.k8s.service;
import com.educoder.bridge.k8s.dao.EvaScriptMapper;
import com.educoder.bridge.k8s.model.EvaluatingScript;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* 评测脚本服务
*/
@Service("evaScriptService")
public class EvaScriptService {
private final Logger logger = LoggerFactory.getLogger(getClass());
@Autowired
private EvaScriptMapper evaScriptMapper;
public void saveEvaluationScript(EvaluatingScript evaluatingScript) {
evaScriptMapper.insert(evaluatingScript);
}
public String getScriptByType(String evaScriptType) {
EvaluatingScript evaluatingScript = evaScriptMapper.selectScriptByType(evaScriptType);
if (evaluatingScript != null) {
return evaluatingScript.getScript();
}
return null;
}
public EvaluatingScript getEvaluatingScriptByType(String scriptType) {
return evaScriptMapper.selectEvaScriptForUpdate(scriptType);
}
public void updateEvaluatingScript(EvaluatingScript evaluatingScript) {
evaScriptMapper.updateByPrimaryKey(evaluatingScript);
}
}

View File

@ -74,4 +74,6 @@ dbpool.minIdle=100
vncPort=6901
#kafka
bootstrapServersConfig=172.16.94.173:9092
bootstrapServersConfig=172.16.94.173:9092
singleEvaCode=code

View File

@ -0,0 +1,124 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.educoder.bridge.k8s.dao.EvaScriptMapper">
<resultMap id="BaseResultMap"
type="com.educoder.bridge.k8s.model.EvaluatingScript">
<id column="id" property="id" jdbcType="BIGINT" />
<result column="script_type" property="scriptType" jdbcType="VARCHAR" />
<result column="script" property="script" jdbcType="VARCHAR" />
<result column="create_time" property="createTime"
jdbcType="TIMESTAMP" />
<result column="update_time" property="updateTime"
jdbcType="TIMESTAMP" />
</resultMap>
<sql id="Base_Column_List">
id, script_type, script, create_time, update_time
</sql>
<select id="selectByPrimaryKey" resultMap="BaseResultMap"
parameterType="java.lang.Long">
select
<include refid="Base_Column_List" />
from evaluating_script
where id = #{id,jdbcType=BIGINT}
</select>
<delete id="deleteByPrimaryKey" parameterType="java.lang.Long">
delete from
evaluating_script
where id = #{id,jdbcType=BIGINT}
</delete>
<insert id="insert"
parameterType="com.educoder.bridge.k8s.model.EvaluatingScript">
insert into evaluating_script (id, script_type, script,
create_time,
update_time)
values (#{id,jdbcType=BIGINT}, #{scriptType,jdbcType=VARCHAR},
#{script,jdbcType=VARCHAR},
#{createTime,jdbcType=TIMESTAMP},
#{updateTime,jdbcType=TIMESTAMP})
</insert>
<insert id="insertSelective"
parameterType="com.educoder.bridge.k8s.model.EvaluatingScript">
insert into evaluating_script
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="id != null">
id,
</if>
<if test="scriptType != null">
script_type,
</if>
<if test="script != null">
script,
</if>
<if test="createTime != null">
create_time,
</if>
<if test="updateTime != null">
update_time,
</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="id != null">
#{id,jdbcType=BIGINT},
</if>
<if test="scriptType != null">
#{scriptType,jdbcType=VARCHAR},
</if>
<if test="script != null">
#{script,jdbcType=VARCHAR},
</if>
<if test="createTime != null">
#{createTime,jdbcType=TIMESTAMP},
</if>
<if test="updateTime != null">
#{updateTime,jdbcType=TIMESTAMP},
</if>
</trim>
</insert>
<update id="updateByPrimaryKeySelective"
parameterType="com.educoder.bridge.k8s.model.EvaluatingScript">
update evaluating_script
<set>
<if test="scriptType != null">
script_type = #{scriptType,jdbcType=VARCHAR},
</if>
<if test="script != null">
script = #{script,jdbcType=VARCHAR},
</if>
<if test="createTime != null">
create_time = #{createTime,jdbcType=TIMESTAMP},
</if>
<if test="updateTime != null">
update_time = #{updateTime,jdbcType=TIMESTAMP},
</if>
</set>
where id = #{id,jdbcType=BIGINT}
</update>
<update id="updateByPrimaryKey"
parameterType="com.educoder.bridge.k8s.model.EvaluatingScript">
update evaluating_script
set script_type = #{scriptType,jdbcType=VARCHAR},
script = #{script,jdbcType=VARCHAR},
create_time =
#{createTime,jdbcType=TIMESTAMP},
update_time =
#{updateTime,jdbcType=TIMESTAMP}
where id = #{id,jdbcType=BIGINT}
</update>
<select id="selectScriptByType" resultMap="BaseResultMap"
parameterType="java.lang.String">
select
<include refid="Base_Column_List" />
from evaluating_script
where script_type = #{scriptType,jdbcType=VARCHAR}
</select>
<select id="selectEvaScriptForUpdate" resultMap="BaseResultMap"
parameterType="java.lang.String">
select
<include refid="Base_Column_List" />
from evaluating_script
where script_type = #{scriptType,jdbcType=VARCHAR} for update
</select>
</mapper>

View File

@ -66,6 +66,8 @@
<!-- 静态文件 -->
<mvc:exclude-mapping path="/manifest.json" />
<mvc:exclude-mapping path="/static/**" />
<!-- k8s包 -->
<mvc:exclude-mapping path="/script/**" />
<!-- 拦截器 -->
<bean class="com.educoder.bridge.user.interceptor.AuthorizationInterceptor"></bean>
</mvc:interceptor>

View File

@ -53,11 +53,54 @@ public class Base64UtilTest {
@Test
public void test3() {
String str = "W3siaW5wdXQiOiIiLCJvdXRwdXQiOiJtYXN0ZXI6XG5ITWFzdGVyXG5cbkpwc1xuXG5OYW1lTm9kZVxuXG5RdW9ydW1QZWVyTWFpblxuXG5SZXNvdXJjZU1hbmFnZXJcblxuU2Vjb25kYXJ5TmFtZU5vZGVcblxuc2xhdmUxOlxuRGF0YU5vZGVcblxuSFJlZ2lvblNlcnZlclxuXG5KcHNcblxuTmFtZU5vZGVcblxuUXVvcnVtUGVlck1haW5cblxuc2xhdmUyOlxuRGF0YU5vZGVcblxuSE1hc3RlclxuXG5IUmVnaW9uU2VydmVyXG5cbkpwc1xuXG5RdW9ydW1QZWVyTWFpblxuXG4ifV0=";
str = Base64Util.decode(str);
String str = "#!/bin/bash\n" +
"cd WORKSPACE\n" +
"\n" +
"# 执行命令\n" +
"executeCommand=\"bash \"\n" +
"\n" +
"# 获取测试用例的输入(请勿改动此行语句)\n" +
"input=$2; OLD_IFS=\"$IFS\"; IFS=,; ins=($input); IFS=\"$OLD_IFS\"\n" +
"\n" +
"compileResult=$(echo -n \"compile successfully\" | base64)\n" +
"\n" +
"# 执行函数\n" +
"execute(){\n" +
" # 当前关卡的执行目标文件\n" +
" sourceClassName=$1\n" +
" # 循环检测数据库是否已启动\n" +
" while :;\n" +
" do\n" +
" sqlcmd -S localhost -U sa -P '<123123Aa!@>' -Q \"SELECT Name from sys.Databases\" 2>&1 >/dev/null\n" +
" if [ $? -eq 0 ];then\n" +
" break\n" +
" else\n" +
" sleep 1\n" +
" fi\n" +
" done\n" +
"\t# 循环获取各测试用例下的实际输出\n" +
" output=''\n" +
" i=0\n" +
" while [[ i -lt ${#ins[*]} ]]; do\n" +
" result=$(echo \"${ins[$i]}\" | base64 -d | $executeCommand $sourceClassName | tr -s ' ' |tr ' ' '\\t' 2>&1 | base64)\n" +
" #拼接输出结果\n" +
" output=$output\\\"$result\\\",\n" +
" let i++\n" +
" done\n" +
" output=\"[${output%?}]\"\n" +
"}\n" +
"execute $1\n" +
"\n" +
"# 返回评测结果\n" +
"returnResult(){\n" +
" result=\"{\\\"compileResult\\\":\\\"$compileResult\\\",\\\"out\\\":$output}\"\n" +
" echo $result\n" +
"}\n" +
"returnResult";
str = Base64Util.encode(str);
System.out.println(str);
System.out.println("**********************");
str = "bWFzdGVyOg0KSE1hc3Rlcg0NCkpwcw0NCk5hbWVOb2RlDQ0KUXVvcnVtUGVlck1haW4NDQpSZXNvdXJjZU1hbmFnZXINDQpTZWNvbmRhcnlOYW1lTm9kZQ0NCnNsYXZlMToNCkRhdGFOb2RlDQ0KSFJlZ2lvblNlcnZlcg0NCkpwcw0NCk5hbWVOb2RlDQ0KUXVvcnVtUGVlck1haW4NDQpzbGF2ZTI6DQpEYXRhTm9kZQ0NCkhNYXN0ZXINDQpIUmVnaW9uU2VydmVyDQ0KSnBzDQ0KUXVvcnVtUGVlck1haW4NDQo";
str = "W3siaW1hZ2UiOiJzcWxzZXJ2ZXItc3NoOnYxLjAiLCJjcHVMaW1pdCI6MSwiY3B1UmVxdWVzdCI6MC4xLCJtZW1vcnlMaW1pdCI6IjIwMDBNIiwibWVtb3J5UmVxdWVzdCI6IjEwMDAwTSIsInJlc291cmNlTGltaXQiOiIxMDAwMEsiLCJ0eXBlIjoibWFpbiJ9XQ==";
str = Base64Util.decode(str);
System.out.println(str);
System.out.println("!!!!!!!!!!!!!!!!!!!!!!!!!!!");