| @@ -1,5 +1,6 @@ | |||||
| package com.ruoyi.platform.controller.dataset; | package com.ruoyi.platform.controller.dataset; | ||||
| import com.ruoyi.common.core.utils.StringUtils; | |||||
| import com.ruoyi.common.core.web.domain.AjaxResult; | import com.ruoyi.common.core.web.domain.AjaxResult; | ||||
| import com.ruoyi.common.security.utils.SecurityUtils; | import com.ruoyi.common.security.utils.SecurityUtils; | ||||
| import com.ruoyi.platform.domain.Dataset; | import com.ruoyi.platform.domain.Dataset; | ||||
| @@ -54,11 +55,15 @@ public class DatasetController { | |||||
| public AjaxResult queryByPage(Dataset dataset, @RequestParam("page") int page, | public AjaxResult queryByPage(Dataset dataset, @RequestParam("page") int page, | ||||
| @RequestParam("size") int size, | @RequestParam("size") int size, | ||||
| @RequestParam(value = "available_range") int availableRange , | @RequestParam(value = "available_range") int availableRange , | ||||
| @RequestParam(value = "data_type", required = false) String dataType) { | |||||
| @RequestParam(value = "data_type", required = false) String dataType, | |||||
| @RequestParam(value = "data_tag", required = false) String dataTag) { | |||||
| if (dataType != null) { // 仅当dataType有值时设置 | if (dataType != null) { // 仅当dataType有值时设置 | ||||
| dataset.setDataType(dataType); | dataset.setDataType(dataType); | ||||
| } | } | ||||
| if (dataTag != null) { | |||||
| dataset.setDataTag(dataTag); | |||||
| } | |||||
| dataset.setAvailableRange(availableRange); | dataset.setAvailableRange(availableRange); | ||||
| PageRequest pageRequest = PageRequest.of(page, size); | PageRequest pageRequest = PageRequest.of(page, size); | ||||
| return AjaxResult.success(this.datasetService.queryByPage(dataset, pageRequest)); | return AjaxResult.success(this.datasetService.queryByPage(dataset, pageRequest)); | ||||
| @@ -79,6 +84,9 @@ public class DatasetController { | |||||
| if (dataType != null) { // 仅当dataType有值时设置 | if (dataType != null) { // 仅当dataType有值时设置 | ||||
| dataset.setDataType(dataType); | dataset.setDataType(dataType); | ||||
| } | } | ||||
| if (dataTag != null) { | |||||
| dataset.setDataTag(dataTag); | |||||
| } | |||||
| PageRequest pageRequest = PageRequest.of(page, size); | PageRequest pageRequest = PageRequest.of(page, size); | ||||
| return AjaxResult.success(this.datasetService.queryByPage(dataset, pageRequest)); | return AjaxResult.success(this.datasetService.queryByPage(dataset, pageRequest)); | ||||
| } | } | ||||
| @@ -122,7 +122,7 @@ public class ImageController extends BaseController { | |||||
| @PostMapping("/net") | @PostMapping("/net") | ||||
| @ApiOperation("从网络上传构建镜像") | @ApiOperation("从网络上传构建镜像") | ||||
| public GenericsAjaxResult<String> createImageFromNet(@RequestParam("name") String imageName, | |||||
| public GenericsAjaxResult<Map<String, String>> createImageFromNet(@RequestParam("name") String imageName, | |||||
| @RequestParam("tag") String imageTag, | @RequestParam("tag") String imageTag, | ||||
| @RequestParam("path") String path) throws Exception { | @RequestParam("path") String path) throws Exception { | ||||
| return genericsSuccess(this.imageService.createImageFromNet(imageName,imageTag,path)); | return genericsSuccess(this.imageService.createImageFromNet(imageName,imageTag,path)); | ||||
| @@ -130,7 +130,7 @@ public class ImageController extends BaseController { | |||||
| @PostMapping("/local") | @PostMapping("/local") | ||||
| @ApiOperation("从本地上传构建镜像") | @ApiOperation("从本地上传构建镜像") | ||||
| public GenericsAjaxResult<String> createImageFromLocal(@RequestParam("name") String imageName, | |||||
| public GenericsAjaxResult<Map<String, String>> createImageFromLocal(@RequestParam("name") String imageName, | |||||
| @RequestParam("tag") String imageTag, | @RequestParam("tag") String imageTag, | ||||
| @RequestParam("path") String path) throws Exception { | @RequestParam("path") String path) throws Exception { | ||||
| return genericsSuccess(this.imageService.createImageFromLocal(imageName,imageTag,path)); | return genericsSuccess(this.imageService.createImageFromLocal(imageName,imageTag,path)); | ||||
| @@ -8,8 +8,10 @@ import io.swagger.annotations.ApiOperation; | |||||
| import org.springframework.data.domain.Page; | import org.springframework.data.domain.Page; | ||||
| import org.springframework.data.domain.PageRequest; | import org.springframework.data.domain.PageRequest; | ||||
| import org.springframework.web.bind.annotation.*; | import org.springframework.web.bind.annotation.*; | ||||
| import org.springframework.web.multipart.MultipartFile; | |||||
| import javax.annotation.Resource; | import javax.annotation.Resource; | ||||
| import java.util.Map; | |||||
| /** | /** | ||||
| * (ImageVersion)表控制层 | * (ImageVersion)表控制层 | ||||
| @@ -36,11 +38,17 @@ public class ImageVersionController extends BaseController { | |||||
| */ | */ | ||||
| @GetMapping | @GetMapping | ||||
| @ApiOperation("分页查询") | @ApiOperation("分页查询") | ||||
| public GenericsAjaxResult<Page<ImageVersion>> queryByPage(ImageVersion imageVersion, int page, int size) { | |||||
| public GenericsAjaxResult<Page<ImageVersion>> queryByPage(ImageVersion imageVersion, @RequestParam("page") int page, | |||||
| @RequestParam("size") int size, | |||||
| @RequestParam(value = "image_id") int imageId) { | |||||
| imageVersion.setImageId(imageId); | |||||
| PageRequest pageRequest = PageRequest.of(page,size); | PageRequest pageRequest = PageRequest.of(page,size); | ||||
| return genericsSuccess(this.imageVersionService.queryByPage(imageVersion, pageRequest)); | return genericsSuccess(this.imageVersionService.queryByPage(imageVersion, pageRequest)); | ||||
| } | } | ||||
| /** | /** | ||||
| * 通过主键查询单条数据 | * 通过主键查询单条数据 | ||||
| * | * | ||||
| @@ -1,13 +1,11 @@ | |||||
| package com.ruoyi.platform.service; | package com.ruoyi.platform.service; | ||||
| import com.ruoyi.platform.domain.Image; | import com.ruoyi.platform.domain.Image; | ||||
| import com.ruoyi.platform.domain.Workflow; | |||||
| import com.ruoyi.platform.vo.ImageVo; | import com.ruoyi.platform.vo.ImageVo; | ||||
| import org.springframework.data.domain.Page; | import org.springframework.data.domain.Page; | ||||
| import org.springframework.data.domain.PageRequest; | import org.springframework.data.domain.PageRequest; | ||||
| import org.springframework.web.multipart.MultipartFile; | import org.springframework.web.multipart.MultipartFile; | ||||
| import java.util.Collection; | |||||
| import java.util.Map; | import java.util.Map; | ||||
| /** | /** | ||||
| @@ -69,13 +67,14 @@ public interface ImageService { | |||||
| /** | /** | ||||
| * 本地上传构建镜像 | * 本地上传构建镜像 | ||||
| * | |||||
| * @param imageName | * @param imageName | ||||
| * @param imageTag | * @param imageTag | ||||
| * @param path | * @param path | ||||
| * @return | * @return | ||||
| */ | */ | ||||
| String createImageFromLocal(String imageName, String imageTag, String path) throws Exception; | |||||
| String createImageFromNet(String imageName, String imageTag, String NetPath) throws Exception; | |||||
| Map<String, String> createImageFromLocal(String imageName, String imageTag, String path) throws Exception; | |||||
| Map<String, String> createImageFromNet(String imageName, String imageTag, String NetPath) throws Exception; | |||||
| Map<String, String> uploadImageFiles(MultipartFile file) throws Exception; | Map<String, String> uploadImageFiles(MultipartFile file) throws Exception; | ||||
| } | } | ||||
| @@ -8,6 +8,7 @@ import com.ruoyi.platform.mapper.ImageVersionDao; | |||||
| import com.ruoyi.platform.service.ImageService; | import com.ruoyi.platform.service.ImageService; | ||||
| import com.ruoyi.platform.service.ImageVersionService; | import com.ruoyi.platform.service.ImageVersionService; | ||||
| import com.ruoyi.platform.service.MinioService; | import com.ruoyi.platform.service.MinioService; | ||||
| import com.ruoyi.platform.utils.FileUtil; | |||||
| import com.ruoyi.platform.utils.K8sClientUtil; | import com.ruoyi.platform.utils.K8sClientUtil; | ||||
| import com.ruoyi.platform.vo.ImageVo; | import com.ruoyi.platform.vo.ImageVo; | ||||
| import com.ruoyi.system.api.model.LoginUser; | import com.ruoyi.system.api.model.LoginUser; | ||||
| @@ -23,7 +24,9 @@ import org.springframework.web.multipart.MultipartFile; | |||||
| import javax.annotation.Resource; | import javax.annotation.Resource; | ||||
| import java.util.Date; | import java.util.Date; | ||||
| import java.util.HashMap; | |||||
| import java.util.Map; | import java.util.Map; | ||||
| import java.util.concurrent.CompletableFuture; | |||||
| /** | /** | ||||
| * (Image)表服务实现类 | * (Image)表服务实现类 | ||||
| @@ -171,7 +174,6 @@ public class ImageServiceImpl implements ImageService { | |||||
| image.setName(imageVo.getName()); | image.setName(imageVo.getName()); | ||||
| image.setDescription(imageVo.getDescription()); | image.setDescription(imageVo.getDescription()); | ||||
| image.setImageType(imageVo.getImageType()); | image.setImageType(imageVo.getImageType()); | ||||
| Image imageInsert = this.insert(image); | Image imageInsert = this.insert(image); | ||||
| if (imageInsert == null){ | if (imageInsert == null){ | ||||
| throw new Exception("新增镜像失败"); | throw new Exception("新增镜像失败"); | ||||
| @@ -181,17 +183,50 @@ public class ImageServiceImpl implements ImageService { | |||||
| imageVersion.setVersion(imageVo.getVersion()); | imageVersion.setVersion(imageVo.getVersion()); | ||||
| imageVersion.setUrl(imageVo.getUrl()); | imageVersion.setUrl(imageVo.getUrl()); | ||||
| imageVersion.setTagName(imageVo.getTagName()); | imageVersion.setTagName(imageVo.getTagName()); | ||||
| //imageVersion.setFileSize(datasetVo.getFileSize()); | |||||
| imageVersion.setFileSize(imageVo.getFileSize()); | |||||
| imageVersion.setStatus("building"); | |||||
| ImageVersion imageVersionInsert = this.imageVersionService.insert(imageVersion); | ImageVersion imageVersionInsert = this.imageVersionService.insert(imageVersion); | ||||
| if (imageVersionInsert == null) { | if (imageVersionInsert == null) { | ||||
| throw new Exception("新增镜像失败"); | throw new Exception("新增镜像失败"); | ||||
| } | } | ||||
| return "新增镜像成功"; | |||||
| // 使用CompletableFuture异步执行不同的镜像构建逻辑 | |||||
| CompletableFuture.supplyAsync(() -> { | |||||
| Map<String, String> resultMap = new HashMap<>(); | |||||
| try { | |||||
| if(imageVo.getUploadType()==0){ | |||||
| resultMap = createImageFromNet(imageVo.getName(), imageVo.getTagName(), imageVo.getPath()); | |||||
| }else{ | |||||
| resultMap = createImageFromLocal(imageVo.getName(), imageVo.getTagName(), imageVo.getPath()); | |||||
| } | |||||
| } catch (Exception e) { | |||||
| imageVersion.setStatus("failed"); | |||||
| imageVersionService.update(imageVersion); | |||||
| throw new RuntimeException("镜像构建失败: " + e.getMessage(), e); | |||||
| } | |||||
| return resultMap; | |||||
| }).thenAccept(resultMap ->{ | |||||
| try { | |||||
| String imageUrl = resultMap.get("url"); | |||||
| String fileSize = resultMap.get("filesize"); | |||||
| imageVersion.setUrl(imageUrl); | |||||
| imageVersion.setFileSize(fileSize); | |||||
| imageVersion.setStatus("available"); | |||||
| imageVersionService.update(imageVersion); | |||||
| } catch (Exception e) { | |||||
| System.err.println("更新数据库失败: " + e.getMessage()); | |||||
| } | |||||
| }).exceptionally(ex -> { | |||||
| System.err.println("异步操作发生错误: " + ex.getMessage()); | |||||
| return null; | |||||
| }); | |||||
| return "新增镜像成功,镜像构建中..."; | |||||
| } | } | ||||
| @Override | @Override | ||||
| public String createImageFromNet(String imageName, String imageTag, String netPath) throws Exception { | |||||
| public Map<String, String> createImageFromNet(String imageName, String imageTag, String netPath) throws Exception { | |||||
| Map<String, String> resultMap = new HashMap<>(); | |||||
| // 得到容器 | // 得到容器 | ||||
| V1Pod pod = k8sClientUtil.getNSPodList(serviceNS, deploymentName); | V1Pod pod = k8sClientUtil.getNSPodList(serviceNS, deploymentName); | ||||
| if (pod == null) { | if (pod == null) { | ||||
| @@ -203,7 +238,7 @@ public class ImageServiceImpl implements ImageService { | |||||
| // 在这个容器的/data/admin 目录下执行命令 docker load -i fileName 得到返回的镜像名字name:tag | // 在这个容器的/data/admin 目录下执行命令 docker load -i fileName 得到返回的镜像名字name:tag | ||||
| String username = SecurityUtils.getLoginUser().getUsername(); | String username = SecurityUtils.getLoginUser().getUsername(); | ||||
| // | // | ||||
| String logs2 = k8sClientUtil.executeCommand(pod,"docker pull "+netPath); | |||||
| String logs2 = k8sClientUtil.executeCommand(pod,"docker pull "+ netPath); | |||||
| // 在容器里执行 docker tag name:tag nexus3.kube-system.svc:8083/imageName:imageTag | // 在容器里执行 docker tag name:tag nexus3.kube-system.svc:8083/imageName:imageTag | ||||
| if (StringUtils.isNoneBlank(logs2)){ | if (StringUtils.isNoneBlank(logs2)){ | ||||
| String substring = logs2.substring(logs2.indexOf(harborUrl), logs2.length()); | String substring = logs2.substring(logs2.indexOf(harborUrl), logs2.length()); | ||||
| @@ -211,19 +246,28 @@ public class ImageServiceImpl implements ImageService { | |||||
| String cmd1 = "docker tag " + cleanedString+ " " + harborUrl+"/"+repository+"/"+username+"/" + imageName + imageTag; | String cmd1 = "docker tag " + cleanedString+ " " + harborUrl+"/"+repository+"/"+username+"/" + imageName + imageTag; | ||||
| String imageUrl = harborUrl+"/"+repository+"/"+username+"/" + imageName + imageTag; | String imageUrl = harborUrl+"/"+repository+"/"+username+"/" + imageName + imageTag; | ||||
| String cmd2 = "docker push " + imageUrl; | String cmd2 = "docker push " + imageUrl; | ||||
| String cmd3 = "docker inspect --format='{{.Size}}' " + imageUrl; | |||||
| String s = k8sClientUtil.executeCommand(pod, cmd1); | String s = k8sClientUtil.executeCommand(pod, cmd1); | ||||
| if (StringUtils.isNotEmpty(k8sClientUtil.executeCommand(pod, cmd2))){ | if (StringUtils.isNotEmpty(k8sClientUtil.executeCommand(pod, cmd2))){ | ||||
| return imageUrl; | |||||
| resultMap.put("url", imageUrl); | |||||
| //得到镜像文件大小 | |||||
| long sizeInBytes = Long.parseLong(k8sClientUtil.executeCommand(pod, cmd3)); | |||||
| String formattedImageSize = FileUtil.formatFileSize(sizeInBytes); // 格式化镜像文件大小 | |||||
| resultMap.put("fileSize", formattedImageSize); | |||||
| return resultMap; | |||||
| }else { | }else { | ||||
| throw new Exception("拉取公网镜像失败,请检查网络或者镜像地址"); | |||||
| throw new Exception("拉取公网镜像失败,请检查网络或者镜像地址"); | |||||
| } | } | ||||
| }else { | }else { | ||||
| throw new Exception("拉取公网镜像失败,请检查网络或者镜像地址"); | |||||
| throw new Exception("拉取公网镜像失败,请检查网络或者镜像地址"); | |||||
| } | } | ||||
| } | } | ||||
| @Override | @Override | ||||
| public String createImageFromLocal(String imageName, String imageTag, String path) throws Exception { | |||||
| public Map<String, String> createImageFromLocal(String imageName, String imageTag, String path) throws Exception { | |||||
| Map<String, String> resultMap = new HashMap<>(); | |||||
| // 得到容器 | // 得到容器 | ||||
| V1Pod pod = k8sClientUtil.getNSPodList(serviceNS, deploymentName); | V1Pod pod = k8sClientUtil.getNSPodList(serviceNS, deploymentName); | ||||
| if (pod == null) { | if (pod == null) { | ||||
| @@ -244,11 +288,17 @@ public class ImageServiceImpl implements ImageService { | |||||
| String cmd1 = "docker tag " + cleanedString+ " " + harborUrl+"/"+repository+"/"+username+"/" + imageName + imageTag; | String cmd1 = "docker tag " + cleanedString+ " " + harborUrl+"/"+repository+"/"+username+"/" + imageName + imageTag; | ||||
| String imageUrl = harborUrl+"/"+repository+"/"+username+"/" + imageName + imageTag; | String imageUrl = harborUrl+"/"+repository+"/"+username+"/" + imageName + imageTag; | ||||
| String cmd2 = "docker push " + imageUrl; | String cmd2 = "docker push " + imageUrl; | ||||
| String cmd3 = "docker inspect --format='{{.Size}}' " + imageUrl; | |||||
| String s = k8sClientUtil.executeCommand(pod, cmd1); | String s = k8sClientUtil.executeCommand(pod, cmd1); | ||||
| if (StringUtils.isNotEmpty(k8sClientUtil.executeCommand(pod, cmd2))){ | if (StringUtils.isNotEmpty(k8sClientUtil.executeCommand(pod, cmd2))){ | ||||
| return imageUrl; | |||||
| resultMap.put("url", imageUrl); | |||||
| //得到镜像文件大小 | |||||
| long sizeInBytes = Long.parseLong(k8sClientUtil.executeCommand(pod, cmd3)); | |||||
| String formattedImageSize = FileUtil.formatFileSize(sizeInBytes); // 格式化镜像文件大小 | |||||
| resultMap.put("fileSize", formattedImageSize); | |||||
| return resultMap; | |||||
| }else { | }else { | ||||
| throw new Exception("解析镜像压缩包失败,请检查镜像文件"); | |||||
| throw new Exception("解析镜像压缩包失败,请检查镜像文件"); | |||||
| } | } | ||||
| }else { | }else { | ||||
| throw new Exception("解析镜像压缩包失败,请检查镜像文件"); | throw new Exception("解析镜像压缩包失败,请检查镜像文件"); | ||||
| @@ -259,7 +309,6 @@ public class ImageServiceImpl implements ImageService { | |||||
| public Map<String, String> uploadImageFiles(MultipartFile file) throws Exception { | public Map<String, String> uploadImageFiles(MultipartFile file) throws Exception { | ||||
| LoginUser loginUser = SecurityUtils.getLoginUser(); | LoginUser loginUser = SecurityUtils.getLoginUser(); | ||||
| String path = loginUser.getUsername()+"/"+file.getOriginalFilename(); | String path = loginUser.getUsername()+"/"+file.getOriginalFilename(); | ||||
| Map<String, String> stringMap = minioService.uploadFile(bucketName, path, file); | |||||
| return stringMap; | |||||
| return minioService.uploadFile(bucketName, path, file); | |||||
| } | } | ||||
| } | } | ||||
| @@ -382,9 +382,10 @@ public class K8sClientUtil { | |||||
| // invokes the CoreV1Api client | // invokes the CoreV1Api client | ||||
| for (V1Pod item : v1PodList.getItems()) { | for (V1Pod item : v1PodList.getItems()) { | ||||
| if (item.getMetadata().getGenerateName().startsWith(deploymentName)) { | |||||
| String generateName = item.getMetadata().getGenerateName(); | |||||
| if (StringUtils.isNotEmpty(generateName) && generateName.startsWith(deploymentName)) { | |||||
| // 找到匹配的Pod,获取其名称 | // 找到匹配的Pod,获取其名称 | ||||
| return item; | |||||
| return item; | |||||
| } | } | ||||
| } | } | ||||
| return null; | return null; | ||||
| @@ -9,10 +9,7 @@ import java.io.Serializable; | |||||
| @JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class) | @JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class) | ||||
| public class ImageVo implements Serializable { | public class ImageVo implements Serializable { | ||||
| /** | |||||
| * 主键 | |||||
| */ | |||||
| private Integer id; | |||||
| /** | /** | ||||
| * 镜像名称 | * 镜像名称 | ||||
| */ | */ | ||||
| @@ -58,13 +55,20 @@ public class ImageVo implements Serializable { | |||||
| @ApiModelProperty(name = "status") | @ApiModelProperty(name = "status") | ||||
| private String status; | private String status; | ||||
| public Integer getId() { | |||||
| return id; | |||||
| } | |||||
| @ApiModelProperty(value = "上传方式, 基于公网上传0,基于本地上传1") | |||||
| private Integer uploadType; | |||||
| public void setId(Integer id) { | |||||
| this.id = id; | |||||
| } | |||||
| @ApiModelProperty(value = "镜像上传路径") | |||||
| private String path; | |||||
| // public Integer getId() { | |||||
| // return id; | |||||
| // } | |||||
| // | |||||
| // public void setId(Integer id) { | |||||
| // this.id = id; | |||||
| // } | |||||
| public String getName() { | public String getName() { | ||||
| return name; | return name; | ||||
| @@ -129,4 +133,19 @@ public class ImageVo implements Serializable { | |||||
| public void setStatus(String status) { | public void setStatus(String status) { | ||||
| this.status = status; | this.status = status; | ||||
| } | } | ||||
| public Integer getUploadType() { | |||||
| return uploadType; | |||||
| } | |||||
| public void setUploadType(Integer uploadType) { | |||||
| this.uploadType = uploadType; | |||||
| } | |||||
| public String getPath() { | |||||
| return path; | |||||
| } | |||||
| public void setPath(String path) { | |||||
| this.path = path; | |||||
| } | |||||
| } | } | ||||
| @@ -19,7 +19,7 @@ | |||||
| select | select | ||||
| id,name,description,image_type,create_by,create_time,update_by,update_time,state | id,name,description,image_type,create_by,create_time,update_by,update_time,state | ||||
| from image | from image | ||||
| where id = #{id} | |||||
| where id = #{id} and state = 1 | |||||
| </select> | </select> | ||||
| <!--查询指定行数据--> | <!--查询指定行数据--> | ||||