Merge branch 'dev-czh' into dev
This commit is contained in:
commit
f6db5d28eb
|
@ -140,7 +140,12 @@
|
|||
<dependency>
|
||||
<groupId>com.github.docker-java</groupId>
|
||||
<artifactId>docker-java</artifactId>
|
||||
<version>3.1.1</version>
|
||||
<version>3.2.13</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.github.docker-java</groupId>
|
||||
<artifactId>docker-java-transport-httpclient5</artifactId>
|
||||
<version>3.2.13</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.baomidou</groupId>
|
||||
|
@ -216,6 +221,12 @@
|
|||
<version>3.0.8</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-lang</groupId>
|
||||
<artifactId>commons-lang</artifactId>
|
||||
<version>2.6</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
|
||||
|
||||
</dependencies>
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
package com.ruoyi.platform.constant;
|
||||
|
||||
public class Constant {
|
||||
|
||||
public final static int Image_Type_Pub = 1; // 公共镜像
|
||||
public final static int Image_Type_Pri = 0; // 私有镜像
|
||||
|
||||
public final static int State_valid = 1; // 有效
|
||||
public final static int State_invalid = 0; // 无效
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
package com.ruoyi.platform.controller.codeConfig;
|
||||
|
||||
import com.ruoyi.common.core.web.controller.BaseController;
|
||||
import com.ruoyi.common.core.web.domain.GenericsAjaxResult;
|
||||
import com.ruoyi.platform.domain.CodeConfig;
|
||||
import com.ruoyi.platform.service.CodeConfigService;
|
||||
import io.swagger.annotations.Api;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("codeConfig")
|
||||
@Api("代码配置")
|
||||
public class CodeConfigController extends BaseController {
|
||||
|
||||
@Resource
|
||||
private CodeConfigService codeConfigService;
|
||||
|
||||
/**
|
||||
* 分页查询
|
||||
* @param codeConfig 筛选条件
|
||||
* @param page 页数
|
||||
* @param size 每页大小
|
||||
* @return 查询结果
|
||||
*/
|
||||
@GetMapping
|
||||
public GenericsAjaxResult<Page<CodeConfig>> queryByPage(CodeConfig codeConfig, int page, int size) {
|
||||
PageRequest pageRequest = PageRequest.of(page,size);
|
||||
return genericsSuccess(this.codeConfigService.queryByPage(codeConfig, pageRequest));
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过主键查询单条数据
|
||||
* @param id
|
||||
* @return 单条数据
|
||||
*/
|
||||
@GetMapping("{id}")
|
||||
public ResponseEntity<CodeConfig> queryById(@PathVariable("id") Long id) {
|
||||
return ResponseEntity.ok(this.codeConfigService.queryById(id));
|
||||
}
|
||||
|
||||
|
||||
@PostMapping
|
||||
public GenericsAjaxResult<CodeConfig> add(@RequestBody CodeConfig codeConfig){
|
||||
return genericsSuccess(this.codeConfigService.insert(codeConfig));
|
||||
}
|
||||
|
||||
@PutMapping
|
||||
public GenericsAjaxResult<CodeConfig> update(@RequestBody CodeConfig codeConfig){
|
||||
return genericsSuccess(this.codeConfigService.update(codeConfig));
|
||||
}
|
||||
|
||||
@DeleteMapping("{id}")
|
||||
public GenericsAjaxResult<String> delete(@PathVariable("id") Long id){
|
||||
return genericsSuccess(this.codeConfigService.removeById(id));
|
||||
}
|
||||
}
|
|
@ -78,16 +78,15 @@ public class ImageController extends BaseController {
|
|||
* @param image 实体
|
||||
* @return 新增结果
|
||||
*/
|
||||
@PostMapping
|
||||
@ApiOperation("新增镜像,不包含镜像版本")
|
||||
public GenericsAjaxResult<Image> add(@RequestBody Image image) {
|
||||
return genericsSuccess(this.imageService.insert(image));
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增镜像和版本
|
||||
*
|
||||
* @param imageVo 实体
|
||||
* 新增镜像和版本 @PostMapping
|
||||
* @return 新增结果
|
||||
*/
|
||||
@PostMapping("/addImageAndVersion")
|
||||
|
@ -149,5 +148,11 @@ public class ImageController extends BaseController {
|
|||
return genericsSuccess(this.imageService.uploadImageFiles(file));
|
||||
}
|
||||
|
||||
|
||||
@PostMapping("/saveImage")
|
||||
@ApiOperation(value = "保存环境为镜像", notes = "docker commit方式保存,并推送到horbor")
|
||||
public GenericsAjaxResult<String> saveImage(@RequestBody ImageVo imageVo){
|
||||
return genericsSuccess(this.imageService.saveImage(imageVo));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
package com.ruoyi.platform.domain;
|
||||
|
||||
import com.fasterxml.jackson.databind.PropertyNamingStrategy;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonNaming;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
@Data
|
||||
@JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class)
|
||||
public class CodeConfig implements Serializable {
|
||||
|
||||
|
||||
private Long id;
|
||||
|
||||
@ApiModelProperty(value = "代码仓库名称")
|
||||
private String codeRepoName;
|
||||
|
||||
@ApiModelProperty(value = "代码仓库可见性(1-公开,0-私有)")
|
||||
private Integer codeRepoVis;
|
||||
|
||||
@ApiModelProperty(value = "Git地址")
|
||||
private String gitUrl;
|
||||
|
||||
@ApiModelProperty(value = "代码分支/Tag")
|
||||
private String gitBranch;
|
||||
|
||||
@ApiModelProperty(value = "验证方式(0-用户名密码,1-SSH-Key)")
|
||||
private Integer verifyMode;
|
||||
|
||||
@ApiModelProperty(value = "Git用户名")
|
||||
private String gitUserName;
|
||||
|
||||
@ApiModelProperty(value = "Git密码")
|
||||
private String gitPassword;
|
||||
|
||||
private String createBy;
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
private Date createTime;
|
||||
/**
|
||||
* 更新者
|
||||
*/
|
||||
private String updateBy;
|
||||
/**
|
||||
* 更新时间
|
||||
*/
|
||||
private Date updateTime;
|
||||
/**
|
||||
* 状态,0失效1生效
|
||||
*/
|
||||
private Integer state;
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
package com.ruoyi.platform.mapper;
|
||||
|
||||
import com.ruoyi.platform.domain.CodeConfig;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface CodeConfigDao {
|
||||
|
||||
long count(@Param("codeConfig") CodeConfig codeConfig);
|
||||
|
||||
List<CodeConfig> queryAllByLimit(@Param("codeConfig") CodeConfig codeConfig, @Param("pageable") Pageable pageable);
|
||||
|
||||
CodeConfig queryById(Long id);
|
||||
|
||||
int insert(@Param("codeConfig") CodeConfig codeConfig);
|
||||
|
||||
int update(@Param("codeConfig") CodeConfig codeConfig);
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
package com.ruoyi.platform.service;
|
||||
|
||||
import com.ruoyi.platform.domain.CodeConfig;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
|
||||
public interface CodeConfigService {
|
||||
|
||||
Page<CodeConfig> queryByPage(CodeConfig codeConfig, PageRequest pageRequest);
|
||||
|
||||
CodeConfig queryById(Long id);
|
||||
|
||||
CodeConfig insert(CodeConfig codeConfig);
|
||||
|
||||
CodeConfig update(CodeConfig codeConfig);
|
||||
|
||||
String removeById(Long id);
|
||||
|
||||
}
|
|
@ -93,6 +93,5 @@ public interface ImageService {
|
|||
Map<String, String> createImageFromNet(String imageName, String imageTag, String NetPath) throws Exception;
|
||||
Map<String, String> uploadImageFiles(MultipartFile file) throws Exception;
|
||||
|
||||
|
||||
|
||||
String saveImage(ImageVo imageVo);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,74 @@
|
|||
package com.ruoyi.platform.service.impl;
|
||||
|
||||
import com.ruoyi.common.security.utils.SecurityUtils;
|
||||
import com.ruoyi.platform.constant.Constant;
|
||||
import com.ruoyi.platform.domain.CodeConfig;
|
||||
import com.ruoyi.platform.mapper.CodeConfigDao;
|
||||
import com.ruoyi.platform.service.CodeConfigService;
|
||||
import com.ruoyi.system.api.model.LoginUser;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageImpl;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
@Service("codeConfigService")
|
||||
public class CodeConfigServiceImpl implements CodeConfigService {
|
||||
|
||||
@Resource
|
||||
private CodeConfigDao codeConfigDao;
|
||||
|
||||
|
||||
@Override
|
||||
public Page<CodeConfig> queryByPage(CodeConfig codeConfig, PageRequest pageRequest) {
|
||||
long total = this.codeConfigDao.count(codeConfig);
|
||||
List<CodeConfig> codeConfigList = this.codeConfigDao.queryAllByLimit(codeConfig, pageRequest);
|
||||
|
||||
return new PageImpl<>(codeConfigList, pageRequest, total);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CodeConfig queryById(Long id) {
|
||||
return this.codeConfigDao.queryById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CodeConfig insert(CodeConfig codeConfig) {
|
||||
LoginUser loginUser = SecurityUtils.getLoginUser();
|
||||
codeConfig.setCreateBy(loginUser.getUsername());
|
||||
codeConfig.setUpdateBy(loginUser.getUsername());
|
||||
codeConfig.setCreateTime(new Date());
|
||||
codeConfig.setUpdateTime(new Date());
|
||||
this.codeConfigDao.insert(codeConfig);
|
||||
return codeConfig;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CodeConfig update(CodeConfig codeConfig) {
|
||||
LoginUser loginUser = SecurityUtils.getLoginUser();
|
||||
codeConfig.setUpdateBy(loginUser.getUsername());
|
||||
codeConfig.setUpdateTime(new Date());
|
||||
this.codeConfigDao.update(codeConfig);
|
||||
return this.codeConfigDao.queryById(codeConfig.getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String removeById(Long id) {
|
||||
CodeConfig codeConfig = this.codeConfigDao.queryById(id);
|
||||
if (codeConfig == null) {
|
||||
return "代码配置不存在";
|
||||
}
|
||||
LoginUser loginUser = SecurityUtils.getLoginUser();
|
||||
String username = loginUser.getUsername();
|
||||
String createBy = codeConfig.getCreateBy();
|
||||
if (!(StringUtils.equals(username, "admin") || StringUtils.equals(username, createBy))) {
|
||||
return "无权限删除该代码配置";
|
||||
}
|
||||
codeConfig.setState(Constant.State_invalid);
|
||||
return this.codeConfigDao.update(codeConfig) > 0 ? "删除成功" : "删除失败";
|
||||
}
|
||||
}
|
|
@ -2,24 +2,29 @@ package com.ruoyi.platform.service.impl;
|
|||
|
||||
import com.alibaba.fastjson2.util.DateUtils;
|
||||
import com.ruoyi.common.security.utils.SecurityUtils;
|
||||
import com.ruoyi.platform.constant.Constant;
|
||||
import com.ruoyi.platform.domain.DevEnvironment;
|
||||
import com.ruoyi.platform.domain.Image;
|
||||
import com.ruoyi.platform.domain.ImageVersion;
|
||||
import com.ruoyi.platform.mapper.DevEnvironmentDao;
|
||||
import com.ruoyi.platform.mapper.ImageDao;
|
||||
import com.ruoyi.platform.mapper.ImageVersionDao;
|
||||
import com.ruoyi.platform.service.ImageService;
|
||||
import com.ruoyi.platform.service.ImageVersionService;
|
||||
import com.ruoyi.platform.service.MinioService;
|
||||
import com.ruoyi.platform.utils.DockerClientUtil;
|
||||
import com.ruoyi.platform.utils.FileUtil;
|
||||
import com.ruoyi.platform.utils.K8sClientUtil;
|
||||
import com.ruoyi.platform.vo.ImageVo;
|
||||
import com.ruoyi.system.api.model.LoginUser;
|
||||
import io.kubernetes.client.openapi.models.V1PersistentVolumeClaim;
|
||||
import io.kubernetes.client.openapi.models.V1Pod;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageImpl;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
@ -40,16 +45,19 @@ import java.util.concurrent.CompletableFuture;
|
|||
public class ImageServiceImpl implements ImageService {
|
||||
@Resource
|
||||
private ImageDao imageDao;
|
||||
|
||||
@Resource
|
||||
private ImageVersionDao imageVersionDao;
|
||||
@Resource
|
||||
private DevEnvironmentDao devEnvironmentDao;
|
||||
|
||||
@Resource
|
||||
private ImageVersionService imageVersionService;
|
||||
|
||||
|
||||
@Resource
|
||||
private ImageVersionDao imageVersionDao;
|
||||
@Resource
|
||||
private K8sClientUtil k8sClientUtil;
|
||||
@Resource
|
||||
private DockerClientUtil dockerClientUtil;
|
||||
|
||||
@Resource
|
||||
private MinioService minioService;
|
||||
@Value("${harbor.bucketName}")
|
||||
|
@ -75,6 +83,8 @@ public class ImageServiceImpl implements ImageService {
|
|||
private String proxyUrl;
|
||||
@Value("${minio.pvcName}")
|
||||
private String pvcName;
|
||||
@Value("${jupyter.namespace}")
|
||||
private String namespace;
|
||||
/**
|
||||
* 通过ID查询单条数据
|
||||
*
|
||||
|
@ -350,4 +360,57 @@ public class ImageServiceImpl implements ImageService {
|
|||
String path = loginUser.getUsername()+"/"+file.getOriginalFilename();
|
||||
return minioService.uploadFile(bucketName, path, file);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public String saveImage(ImageVo imageVo) {
|
||||
if(imageDao.getByName(imageVo.getName()) != null){
|
||||
throw new IllegalStateException("镜像名称已存在");
|
||||
}
|
||||
LoginUser loginUser = SecurityUtils.getLoginUser();
|
||||
String username = loginUser.getUsername().toLowerCase();
|
||||
String podName = username +"-editor-pod" + "-" + imageVo.getDevEnvironmentId().toString();
|
||||
|
||||
try {
|
||||
String containerId = k8sClientUtil.getPodContainerId(podName, namespace);
|
||||
String hostIp = k8sClientUtil.getHostIp(podName, namespace);
|
||||
|
||||
dockerClientUtil.commitImage(imageVo,containerId,hostIp,username);
|
||||
HashMap<String, String> resultMap = dockerClientUtil.pushImageToHorbor(imageVo, hostIp);
|
||||
|
||||
Image image = new Image();
|
||||
BeanUtils.copyProperties(imageVo,image);
|
||||
image.setImageType(Constant.Image_Type_Pri);
|
||||
image.setCreateBy(username);
|
||||
image.setUpdateBy(username);
|
||||
image.setUpdateTime(new Date());
|
||||
image.setCreateTime(new Date());
|
||||
image.setState(1);
|
||||
imageDao.insert(image);
|
||||
|
||||
ImageVersion imageVersion = new ImageVersion();
|
||||
imageVersion.setImageId(image.getId());
|
||||
imageVersion.setVersion(imageVo.getVersion());
|
||||
imageVersion.setUrl(resultMap.get("imageName"));
|
||||
imageVersion.setTagName(imageVo.getTagName());
|
||||
imageVersion.setFileSize(resultMap.get("size"));
|
||||
imageVersion.setCreateBy(username);
|
||||
imageVersion.setUpdateBy(username);
|
||||
imageVersion.setUpdateTime(new Date());
|
||||
imageVersion.setCreateTime(new Date());
|
||||
imageVersion.setState(1);
|
||||
imageVersion.setStatus("available");
|
||||
imageVersionDao.insert(imageVersion);
|
||||
|
||||
//更新dev环境的镜像信息
|
||||
DevEnvironment devEnvironment = new DevEnvironment();
|
||||
devEnvironment.setId(imageVo.getDevEnvironmentId());
|
||||
devEnvironment.setImage(resultMap.get("imageName"));
|
||||
devEnvironmentDao.update(devEnvironment);
|
||||
|
||||
return "保存镜像成功";
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("保存镜像失败:" +e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,109 @@
|
|||
package com.ruoyi.platform.utils;
|
||||
|
||||
import com.github.dockerjava.api.DockerClient;
|
||||
import com.github.dockerjava.api.command.CommitCmd;
|
||||
import com.github.dockerjava.api.command.InspectImageResponse;
|
||||
import com.github.dockerjava.api.model.AuthConfig;
|
||||
import com.github.dockerjava.core.DefaultDockerClientConfig;
|
||||
import com.github.dockerjava.core.DockerClientConfig;
|
||||
import com.github.dockerjava.core.DockerClientImpl;
|
||||
import com.github.dockerjava.httpclient5.ApacheDockerHttpClient;
|
||||
import com.github.dockerjava.transport.DockerHttpClient;
|
||||
import com.ruoyi.platform.vo.ImageVo;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.HashMap;
|
||||
|
||||
@Slf4j
|
||||
@Component
|
||||
public class DockerClientUtil {
|
||||
|
||||
@Value("${harbor.bucketName}")
|
||||
private String bucketName;
|
||||
@Value("${harbor.repository}")
|
||||
private String repository;
|
||||
@Value("${harbor.harborUrl}")
|
||||
private String harborUrl;
|
||||
@Value("${harbor.harborUser}")
|
||||
private String harborUser;
|
||||
@Value("${harbor.harborpassword}")
|
||||
private String harborpassword;
|
||||
|
||||
public DockerClient getDockerClient(String dockerServerUrl) {
|
||||
|
||||
//创建DefaultDockerClientConfig(指定docker服务器的配置)
|
||||
DockerClientConfig config = DefaultDockerClientConfig
|
||||
.createDefaultConfigBuilder()
|
||||
.withDockerHost("tcp://" + dockerServerUrl + ":2375")
|
||||
.withDockerTlsVerify(false)
|
||||
.withApiVersion("1.40")
|
||||
// .withDockerCertPath(dcokerCertPath)
|
||||
// .withRegistryUsername(registryUser)
|
||||
// .withRegistryPassword(registryPass)
|
||||
// .withRegistryEmail(registryMail)
|
||||
// .withRegistryUrl(registryUrl)
|
||||
.build();
|
||||
|
||||
//创建DockerHttpClient
|
||||
DockerHttpClient httpClient = new ApacheDockerHttpClient.Builder()
|
||||
.dockerHost(config.getDockerHost())
|
||||
.sslConfig(config.getSSLConfig())
|
||||
.maxConnections(1000)
|
||||
.connectionTimeout(Duration.ofSeconds(300))
|
||||
.responseTimeout(Duration.ofSeconds(450))
|
||||
.build();
|
||||
|
||||
//创建DockerClient
|
||||
return DockerClientImpl.getInstance(config, httpClient);
|
||||
|
||||
}
|
||||
|
||||
public String commitImage(ImageVo imageVo, String containerId, String hostIp, String userName) {
|
||||
DockerClient dockerClient = getDockerClient(hostIp);
|
||||
|
||||
// 提交容器为镜像,这里的"new_image"和"new_tag"是新镜像的名字和标签
|
||||
CommitCmd commitCmd = dockerClient.commitCmd(containerId)
|
||||
.withRepository(imageVo.getName())
|
||||
.withTag(imageVo.getTagName())
|
||||
.withAuthor(userName)
|
||||
.withMessage(imageVo.getDescription());
|
||||
return commitCmd.exec();
|
||||
}
|
||||
|
||||
public HashMap<String, String> pushImageToHorbor(ImageVo imageVo, String hostIp) {
|
||||
|
||||
DockerClient dockerClient = getDockerClient(hostIp);
|
||||
//Harbor登录信息
|
||||
AuthConfig autoConfig = new AuthConfig().withRegistryAddress(harborUrl).withUsername(harborUser).withPassword(harborpassword);
|
||||
|
||||
|
||||
String localImageName = imageVo.getName() + ":" + imageVo.getTagName();
|
||||
String imageName = harborUrl + "/" + bucketName + "/" + imageVo.getName();
|
||||
|
||||
//给镜像打上tag
|
||||
dockerClient.tagImageCmd(localImageName, imageName, imageVo.getTagName()).exec();
|
||||
//推送镜像至镜像仓库
|
||||
try {
|
||||
dockerClient.pushImageCmd(imageName).withAuthConfig(autoConfig).start().awaitCompletion();
|
||||
//push成功后,删除本地加载的镜像
|
||||
dockerClient.removeImageCmd(localImageName).exec();
|
||||
|
||||
String totalImageName = imageName + ":" + imageVo.getTagName();
|
||||
InspectImageResponse exec = dockerClient.inspectImageCmd(totalImageName).exec();
|
||||
|
||||
String size = String.format("%.1f GB", (float) exec.getSize() / 1073741824.0);
|
||||
|
||||
HashMap<String, String> resultMap = new HashMap<>();
|
||||
resultMap.put("imageName",totalImageName);
|
||||
resultMap.put("size",size);
|
||||
|
||||
return resultMap;
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException("推送镜像失败:" + e);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -136,7 +136,7 @@ public class K8sClientUtil {
|
|||
if (v1ServiceList!=null) {
|
||||
for (V1Service svc : v1ServiceList.getItems()) {
|
||||
if (StringUtils.equals(svc.getMetadata().getName(), serviceName)) {
|
||||
// PVC 已存在
|
||||
// SVC 已存在
|
||||
return svc;
|
||||
}
|
||||
}
|
||||
|
@ -377,9 +377,48 @@ public class K8sClientUtil {
|
|||
|
||||
// 创建配置好的Pod
|
||||
public Integer createConfiguredPod(String podName, String namespace, Integer port, String mountPath, V1PersistentVolumeClaim pvc, String image, String dataPvcName, String datasetPath, String modelPath) {
|
||||
Map<String, String> selector = new LinkedHashMap<>();
|
||||
selector.put("k8s-jupyter", podName);
|
||||
|
||||
//设置选择节点,pod反亲和性
|
||||
Map<String, String> selector = new LinkedHashMap<>();
|
||||
selector.put("k8s-jupyter", "CPU-GPU");
|
||||
Map<String, String> nodeSelector = new LinkedHashMap<>();
|
||||
nodeSelector.put("resource-type", "CPU-GPU");
|
||||
|
||||
V1LabelSelectorRequirement labelSelectorRequirement = new V1LabelSelectorRequirement()
|
||||
.key("k8s-jupyter").operator("NotIn").values(Collections.singletonList("CPU-GPU"));
|
||||
|
||||
V1LabelSelector labelSelector = new V1LabelSelector()
|
||||
.matchExpressions(Collections.singletonList(labelSelectorRequirement));
|
||||
|
||||
V1PodAffinityTerm podAffinityTerm = new V1PodAffinityTerm()
|
||||
.labelSelector(labelSelector)
|
||||
.namespaces(Collections.singletonList(namespace))
|
||||
.topologyKey("kubernetes.io/hostname");
|
||||
|
||||
V1PodAffinity podAffinity = new V1PodAffinity()
|
||||
.requiredDuringSchedulingIgnoredDuringExecution(Collections.singletonList(podAffinityTerm));
|
||||
|
||||
V1LabelSelectorRequirement antiLabelSelectorRequirement = new V1LabelSelectorRequirement()
|
||||
.key("k8s-jupyter").operator("In").values(Collections.singletonList("CPU-GPU"));
|
||||
|
||||
V1LabelSelector antiLabelSelector = new V1LabelSelector()
|
||||
.matchExpressions(Collections.singletonList(antiLabelSelectorRequirement));
|
||||
|
||||
V1PodAffinityTerm antiPodAffinityTerm = new V1PodAffinityTerm()
|
||||
.labelSelector(antiLabelSelector)
|
||||
.namespaces(Collections.singletonList(namespace))
|
||||
.topologyKey("kubernetes.io/hostname");
|
||||
|
||||
// V1WeightedPodAffinityTerm weightedPodAffinityTerm = new V1WeightedPodAffinityTerm().weight(100).podAffinityTerm(podAffinityTerm);
|
||||
|
||||
V1PodAntiAffinity podAntiAffinity = new V1PodAntiAffinity()
|
||||
.requiredDuringSchedulingIgnoredDuringExecution(Collections.singletonList(antiPodAffinityTerm));
|
||||
|
||||
V1Affinity v1Affinity = new V1Affinity()
|
||||
.podAffinity(podAffinity)
|
||||
.podAntiAffinity(podAntiAffinity);
|
||||
|
||||
// 创建Pod
|
||||
CoreV1Api api = new CoreV1Api(apiClient);
|
||||
V1PodList v1PodList = null;
|
||||
try {
|
||||
|
@ -402,8 +441,8 @@ public class K8sClientUtil {
|
|||
// 配置卷和卷挂载
|
||||
List<V1VolumeMount> volumeMounts = new ArrayList<>();
|
||||
volumeMounts.add(new V1VolumeMount().name("workspace").mountPath(mountPath));
|
||||
volumeMounts.add(new V1VolumeMount().name("minio-pvc").mountPath("/datasets").subPath(datasetPath).readOnly(true));
|
||||
volumeMounts.add(new V1VolumeMount().name("minio-pvc").mountPath("/model").subPath(modelPath).readOnly(true));
|
||||
volumeMounts.add(new V1VolumeMount().name("minio-pvc").mountPath("/opt/data").subPath(datasetPath).readOnly(true));
|
||||
volumeMounts.add(new V1VolumeMount().name("minio-pvc").mountPath("/opt/model").subPath(modelPath).readOnly(true));
|
||||
|
||||
List<V1Volume> volumes = new ArrayList<>();
|
||||
volumes.add(new V1Volume().name("workspace").persistentVolumeClaim(new V1PersistentVolumeClaimVolumeSource().claimName(pvc.getMetadata().getName())));
|
||||
|
@ -423,6 +462,8 @@ public class K8sClientUtil {
|
|||
.withVolumeMounts(volumeMounts)
|
||||
.endContainer()
|
||||
.withVolumes(volumes)
|
||||
.withNodeSelector(nodeSelector)
|
||||
.withAffinity(v1Affinity)
|
||||
.endSpec()
|
||||
.build();
|
||||
|
||||
|
@ -506,6 +547,28 @@ public class K8sClientUtil {
|
|||
return pod.getStatus().getPhase();
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据Pod的名称和Namespace查询Pod的容器信息
|
||||
* @param podName Pod的名称
|
||||
* @param namespace Pod所在的Namespace
|
||||
*/
|
||||
public String getPodContainerId(String podName, String namespace) throws Exception {
|
||||
CoreV1Api api = new CoreV1Api(apiClient);
|
||||
V1Pod pod = api.readNamespacedPod(podName, namespace, null, null, null);
|
||||
|
||||
if(pod.getStatus().getContainerStatuses().size() !=1){
|
||||
throw new RuntimeException("容器错误");
|
||||
}
|
||||
String containerId = pod.getStatus().getContainerStatuses().get(0).getContainerID().split("//")[1];
|
||||
return containerId;
|
||||
}
|
||||
|
||||
public String getHostIp(String podName, String namespace) throws Exception {
|
||||
CoreV1Api api = new CoreV1Api(apiClient);
|
||||
V1Pod pod = api.readNamespacedPod(podName, namespace, null, null, null);
|
||||
return pod.getStatus().getHostIP();
|
||||
}
|
||||
|
||||
public String getPodLogs(String podName,String namespace,String container,int line) {
|
||||
CoreV1Api api = new CoreV1Api(apiClient);
|
||||
try {
|
||||
|
|
|
@ -57,13 +57,16 @@ public class ImageVo implements Serializable {
|
|||
@ApiModelProperty(name = "status")
|
||||
private String status;
|
||||
|
||||
@ApiModelProperty(value = "上传方式, 基于公网上传0,基于本地上传1")
|
||||
@ApiModelProperty(name = "upload_type", value = "上传方式, 基于公网上传0,基于本地上传1")
|
||||
private Integer uploadType;
|
||||
|
||||
@ApiModelProperty(value = "镜像上传路径")
|
||||
private String path;
|
||||
|
||||
|
||||
@ApiModelProperty(name = "dev_environment_id", value = "环境id")
|
||||
private Integer devEnvironmentId;
|
||||
|
||||
// public Integer getId() {
|
||||
// return id;
|
||||
// }
|
||||
|
@ -147,7 +150,17 @@ public class ImageVo implements Serializable {
|
|||
public String getPath() {
|
||||
return path;
|
||||
}
|
||||
|
||||
public void setPath(String path) {
|
||||
this.path = path;
|
||||
}
|
||||
|
||||
public Integer getDevEnvironmentId() {
|
||||
return devEnvironmentId;
|
||||
}
|
||||
|
||||
public void setDevEnvironmentId(Integer devEnvironmentId) {
|
||||
this.devEnvironmentId = devEnvironmentId;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,108 @@
|
|||
<?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.ruoyi.platform.mapper.CodeConfigDao">
|
||||
|
||||
<insert id="insert">
|
||||
insert into code_config(code_repo_name, code_repo_vis, git_url, git_branch, verify_mode, git_user_name, git_password, create_by, create_time, update_by, update_time)
|
||||
values(#{codeConfig.codeRepoName}, #{codeConfig.codeRepoVis}, #{codeConfig.gitUrl}, #{codeConfig.gitBranch}, #{codeConfig.verifyMode}, #{codeConfig.gitUserName}, #{codeConfig.gitPassword}, #{codeConfig.createBy}, #{codeConfig.createTime}, #{codeConfig.updateBy}, #{codeConfig.updateTime})
|
||||
</insert>
|
||||
|
||||
<update id="update">
|
||||
update code_config
|
||||
<set>
|
||||
<if test="codeConfig.codeRepoName != null and codeConfig.codeRepoName != ''">
|
||||
code_repo_name = #{codeConfig.codeRepoName},
|
||||
</if>
|
||||
<if test="codeConfig.codeRepoVis != null">
|
||||
code_repo_vis = #{codeConfig.codeRepoVis},
|
||||
</if>
|
||||
<if test="codeConfig.gitUrl != null">
|
||||
git_url = #{codeConfig.gitUrl},
|
||||
</if>
|
||||
<if test="codeConfig.gitBranch != null and codeConfig.gitBranch != ''">
|
||||
git_branch = #{codeConfig.gitBranch},
|
||||
</if>
|
||||
<if test="codeConfig.verifyMode != null">
|
||||
verify_mode = #{codeConfig.verifyMode},
|
||||
</if>
|
||||
<if test="codeConfig.gitUserName != null and codeConfig.gitUserName != ''">
|
||||
git_user_name = #{codeConfig.gitUserName},
|
||||
</if>
|
||||
<if test="codeConfig.createBy != null and codeConfig.createBy != ''">
|
||||
create_by = #{codeConfig.createBy},
|
||||
</if>
|
||||
<if test="codeConfig.createTime != null">
|
||||
create_time = #{codeConfig.createTime},
|
||||
</if>
|
||||
<if test="codeConfig.updateBy != null and codeConfig.updateBy != ''">
|
||||
update_by = #{codeConfig.updateBy},
|
||||
</if>
|
||||
<if test="codeConfig.updateTime != null">
|
||||
update_time = #{codeConfig.updateTime},
|
||||
</if>
|
||||
<if test="codeConfig.state != null">
|
||||
state = #{codeConfig.state},
|
||||
</if>
|
||||
</set>
|
||||
where id = #{codeConfig.id}
|
||||
</update>
|
||||
|
||||
|
||||
<select id="count" resultType="java.lang.Long">
|
||||
select count(1)
|
||||
from code_config
|
||||
<include refid="common_condition"></include>
|
||||
</select>
|
||||
|
||||
<select id="queryAllByLimit" resultType="com.ruoyi.platform.domain.CodeConfig">
|
||||
select * from code_config
|
||||
<include refid="common_condition"></include>
|
||||
limit #{pageable.offset}, #{pageable.pageSize}
|
||||
</select>
|
||||
|
||||
<select id="queryById" resultType="com.ruoyi.platform.domain.CodeConfig">
|
||||
select *
|
||||
from code_config
|
||||
where id = #{id}
|
||||
and state = 1
|
||||
</select>
|
||||
|
||||
<sql id="common_condition">
|
||||
<where>
|
||||
state = 1
|
||||
<if test="codeConfig.id != null">
|
||||
and id = #{codeConfig.id}
|
||||
</if>
|
||||
<if test="codeConfig.codeRepoName != null and codeConfig.codeRepoName != ''">
|
||||
and code_repo_name = #{codeConfig.codeRepoName}
|
||||
</if>
|
||||
<if test="codeConfig.codeRepoVis != null">
|
||||
and code_repo_vis = #{codeConfig.codeRepoVis}
|
||||
</if>
|
||||
<if test="codeConfig.gitUrl != null">
|
||||
and git_url = #{codeConfig.gitUrl}
|
||||
</if>
|
||||
<if test="codeConfig.gitBranch != null and codeConfig.gitBranch != ''">
|
||||
and git_branch = #{codeConfig.gitBranch}
|
||||
</if>
|
||||
<if test="codeConfig.verifyMode != null">
|
||||
and verify_mode = #{codeConfig.verifyMode}
|
||||
</if>
|
||||
<if test="codeConfig.gitUserName != null and codeConfig.gitUserName != ''">
|
||||
and git_user_name = #{codeConfig.gitUserName}
|
||||
</if>
|
||||
<if test="codeConfig.createBy != null and codeConfig.createBy != ''">
|
||||
and create_by = #{codeConfig.createBy}
|
||||
</if>
|
||||
<if test="codeConfig.createTime != null">
|
||||
and create_time = #{codeConfig.createTime}
|
||||
</if>
|
||||
<if test="codeConfig.updateBy != null and codeConfig.updateBy != ''">
|
||||
and update_by = #{codeConfig.updateBy}
|
||||
</if>
|
||||
<if test="codeConfig.updateTime != null">
|
||||
and update_time = #{codeConfig.updateTime}
|
||||
</if>
|
||||
</where>
|
||||
</sql>
|
||||
</mapper>
|
|
@ -65,7 +65,7 @@
|
|||
<groupId>com.mysql</groupId>
|
||||
<artifactId>mysql-connector-j</artifactId>
|
||||
</dependency>
|
||||
|
||||
|
||||
<!-- RuoYi Common Log -->
|
||||
<dependency>
|
||||
<groupId>com.ruoyi</groupId>
|
||||
|
@ -77,7 +77,13 @@
|
|||
<groupId>com.ruoyi</groupId>
|
||||
<artifactId>ruoyi-common-swagger</artifactId>
|
||||
</dependency>
|
||||
|
||||
|
||||
<!-- RuoYi Common DataSource -->
|
||||
<dependency>
|
||||
<groupId>com.ruoyi</groupId>
|
||||
<artifactId>ruoyi-common-datasource</artifactId>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
|
Loading…
Reference in New Issue