Merge remote-tracking branch 'origin/dev' into dev

This commit is contained in:
Captain.B 2020-03-23 17:11:40 +08:00
commit 17bf685d05
5 changed files with 161 additions and 5 deletions

View File

@ -1,6 +1,6 @@
package io.metersphere.commons.constants; package io.metersphere.commons.constants;
public enum ResourceTypeEnum { public enum ResourcePoolTypeEnum {
/** /**
* k8s 资源池 * k8s 资源池
*/ */

View File

@ -0,0 +1,41 @@
package io.metersphere.dto;
public class KubernetesDTO {
private String masterUrl;
private String token;
private Integer maxConcurrency;
private Boolean validate;
public String getMasterUrl() {
return masterUrl;
}
public void setMasterUrl(String masterUrl) {
this.masterUrl = masterUrl;
}
public String getToken() {
return token;
}
public void setToken(String token) {
this.token = token;
}
public Integer getMaxConcurrency() {
return maxConcurrency;
}
public void setMaxConcurrency(Integer maxConcurrency) {
this.maxConcurrency = maxConcurrency;
}
public Boolean getValidate() {
return validate;
}
public void setValidate(Boolean validate) {
this.validate = validate;
}
}

View File

@ -0,0 +1,40 @@
package io.metersphere.dto;
public class NodeDTO {
private String ip;
private Integer port;
private Integer maxConcurrency;
private Boolean validate;
public String getIp() {
return ip;
}
public void setIp(String ip) {
this.ip = ip;
}
public Integer getPort() {
return port;
}
public void setPort(Integer port) {
this.port = port;
}
public Integer getMaxConcurrency() {
return maxConcurrency;
}
public void setMaxConcurrency(Integer maxConcurrency) {
this.maxConcurrency = maxConcurrency;
}
public Boolean getValidate() {
return validate;
}
public void setValidate(Boolean validate) {
this.validate = validate;
}
}

View File

@ -1,12 +1,23 @@
package io.metersphere.service; package io.metersphere.service;
import com.alibaba.fastjson.JSON;
import io.metersphere.base.domain.TestResourcePool; import io.metersphere.base.domain.TestResourcePool;
import io.metersphere.base.domain.TestResourcePoolExample; import io.metersphere.base.domain.TestResourcePoolExample;
import io.metersphere.base.mapper.TestResourcePoolMapper; import io.metersphere.base.mapper.TestResourcePoolMapper;
import io.metersphere.commons.constants.ResourcePoolTypeEnum;
import io.metersphere.commons.utils.BeanUtils;
import io.metersphere.controller.request.resourcepool.QueryResourcePoolRequest; import io.metersphere.controller.request.resourcepool.QueryResourcePoolRequest;
import io.metersphere.dto.KubernetesDTO;
import io.metersphere.dto.NodeDTO;
import io.metersphere.engine.kubernetes.provider.ClientCredential;
import io.metersphere.engine.kubernetes.provider.KubernetesProvider;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.RestTemplate;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.util.List; import java.util.List;
@ -19,6 +30,8 @@ import java.util.UUID;
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public class TestResourcePoolService { public class TestResourcePoolService {
private final static String nodeControllerUrl = "%s:%s/status";
@Resource @Resource
private TestResourcePoolMapper testResourcePoolMapper; private TestResourcePoolMapper testResourcePoolMapper;
@ -27,6 +40,7 @@ public class TestResourcePoolService {
testResourcePool.setCreateTime(System.currentTimeMillis()); testResourcePool.setCreateTime(System.currentTimeMillis());
testResourcePool.setUpdateTime(System.currentTimeMillis()); testResourcePool.setUpdateTime(System.currentTimeMillis());
testResourcePool.setStatus("1"); testResourcePool.setStatus("1");
validateTestResourcePool(testResourcePool);
testResourcePoolMapper.insertSelective(testResourcePool); testResourcePoolMapper.insertSelective(testResourcePool);
return testResourcePool; return testResourcePool;
} }
@ -37,6 +51,7 @@ public class TestResourcePoolService {
public void updateTestResourcePool(TestResourcePool testResourcePool) { public void updateTestResourcePool(TestResourcePool testResourcePool) {
testResourcePool.setUpdateTime(System.currentTimeMillis()); testResourcePool.setUpdateTime(System.currentTimeMillis());
validateTestResourcePool(testResourcePool);
testResourcePoolMapper.updateByPrimaryKeySelective(testResourcePool); testResourcePoolMapper.updateByPrimaryKeySelective(testResourcePool);
} }
@ -47,4 +62,55 @@ public class TestResourcePoolService {
} }
return testResourcePoolMapper.selectByExample(example); return testResourcePoolMapper.selectByExample(example);
} }
private void validateTestResourcePool(TestResourcePool testResourcePool) {
if (StringUtils.equalsIgnoreCase(testResourcePool.getType(), ResourcePoolTypeEnum.K8S.name())) {
validateK8s(testResourcePool);
return;
}
validateNodes(testResourcePool);
}
private void validateNodes(TestResourcePool testResourcePool) {
List<NodeDTO> nodes = JSON.parseArray(testResourcePool.getInfo(), NodeDTO.class);
if (CollectionUtils.isEmpty(nodes)) {
throw new RuntimeException("没有节点信息");
}
for (NodeDTO node : nodes) {
boolean isValidate = validateNode(node);
if (!isValidate) {
testResourcePool.setStatus("0");
}
node.setValidate(isValidate);
}
testResourcePool.setInfo(JSON.toJSONString(nodes));
}
private boolean validateNode(NodeDTO dto) {
RestTemplate restTemplate = new RestTemplate();
ResponseEntity<String> entity = restTemplate.getForEntity(String.format(nodeControllerUrl, dto.getIp(), dto.getPort()), String.class);
return entity.getStatusCode().value() == HttpStatus.SC_OK;
}
private void validateK8s(TestResourcePool testResourcePool) {
List<KubernetesDTO> dtos = JSON.parseArray(testResourcePool.getInfo(), KubernetesDTO.class);
if (CollectionUtils.isEmpty(dtos) || dtos.size() != 1) {
throw new RuntimeException("只能添加一个 K8s");
}
ClientCredential clientCredential = new ClientCredential();
BeanUtils.copyBean(clientCredential, dtos.get(0));
try {
KubernetesProvider provider = new KubernetesProvider(JSON.toJSONString(clientCredential));
provider.validateCredential();
dtos.get(0).setValidate(true);
} catch (Exception e) {
dtos.get(0).setValidate(false);
testResourcePool.setStatus("0");
}
testResourcePool.setInfo(JSON.toJSONString(dtos));
}
} }

View File

@ -69,7 +69,8 @@
</div> </div>
</el-card> </el-card>
<el-dialog title="创建资源池" :visible.sync="createVisible" width="70%" @closed="closeFunc" :destroy-on-close="true"> <el-dialog v-loading="testLoading" title="创建资源池" :visible.sync="createVisible" width="70%" @closed="closeFunc"
:destroy-on-close="true">
<el-form :model="form" label-position="right" label-width="100px" size="small" :rules="rule" <el-form :model="form" label-position="right" label-width="100px" size="small" :rules="rule"
ref="createTestResourcePoolForm"> ref="createTestResourcePoolForm">
<el-form-item label="名称" prop="name"> <el-form-item label="名称" prop="name">
@ -143,7 +144,8 @@
</span> </span>
</el-dialog> </el-dialog>
<el-dialog title="修改资源池" :visible.sync="updateVisible" width="70%" :destroy-on-close="true" @close="closeFunc"> <el-dialog v-loading="testLoading" title="修改资源池" :visible.sync="updateVisible" width="70%" :destroy-on-close="true"
@close="closeFunc">
<el-form :model="form" label-position="right" label-width="100px" size="small" :rules="rule" <el-form :model="form" label-position="right" label-width="100px" size="small" :rules="rule"
ref="updateTestResourcePoolForm"> ref="updateTestResourcePoolForm">
<el-form-item label="名称" prop="name"> <el-form-item label="名称" prop="name">
@ -225,6 +227,7 @@
data() { data() {
return { return {
loading: false, loading: false,
testLoading: false,
createVisible: false, createVisible: false,
infoList: [], infoList: [],
updateVisible: false, updateVisible: false,
@ -363,6 +366,7 @@
if (valide) { if (valide) {
let vri = this.validateResourceInfo(); let vri = this.validateResourceInfo();
if (vri.validate) { if (vri.validate) {
this.testLoading = true;
this.form.info = JSON.stringify(this.infoList); this.form.info = JSON.stringify(this.infoList);
this.$post("/testresourcepool/add", this.form) this.$post("/testresourcepool/add", this.form)
.then(() => { .then(() => {
@ -371,13 +375,15 @@
message: '添加成功!' message: '添加成功!'
}, },
this.createVisible = false, this.createVisible = false,
this.initTableData()) this.initTableData());
this.testLoading = false;
}); });
} else { } else {
this.$message({ this.$message({
type: 'warning', type: 'warning',
message: vri.msg message: vri.msg
}); });
this.testLoading = false;
return false; return false;
} }
@ -389,6 +395,7 @@
updateTestResourcePool(updateTestResourcePoolForm) { updateTestResourcePool(updateTestResourcePoolForm) {
this.$refs[updateTestResourcePoolForm].validate(valide => { this.$refs[updateTestResourcePoolForm].validate(valide => {
if (valide) { if (valide) {
this.testLoading = true;
let vri = this.validateResourceInfo(); let vri = this.validateResourceInfo();
if (vri.validate) { if (vri.validate) {
this.form.info = JSON.stringify(this.infoList); this.form.info = JSON.stringify(this.infoList);
@ -400,13 +407,15 @@
}, },
this.updateVisible = false, this.updateVisible = false,
this.initTableData(), this.initTableData(),
self.loading = false) self.loading = false);
this.testLoading = false;
}); });
} else { } else {
this.$message({ this.$message({
type: 'warning', type: 'warning',
message: vri.msg message: vri.msg
}); });
this.testLoading = false;
return false; return false;
} }
} else { } else {