From d447a6f0f3d1ebc4dfc37c9c83f8768cbdfdb7c2 Mon Sep 17 00:00:00 2001 From: chenzhihang <709011834@qq.com> Date: Mon, 2 Sep 2024 15:23:14 +0800 Subject: [PATCH] =?UTF-8?q?1=E3=80=81=E4=BC=98=E5=8C=96=E4=BF=9D=E5=AD=98?= =?UTF-8?q?=E9=95=9C=E5=83=8F=E6=96=B9=E6=B3=95=202=E3=80=81=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E5=88=A0=E9=99=A4=E9=95=9C=E5=83=8F=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/impl/ImageServiceImpl.java | 106 ++++++++++-------- .../platform/utils/DockerClientUtil.java | 5 + 2 files changed, 65 insertions(+), 46 deletions(-) diff --git a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/impl/ImageServiceImpl.java b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/impl/ImageServiceImpl.java index b13c414..591628a 100644 --- a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/impl/ImageServiceImpl.java +++ b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/impl/ImageServiceImpl.java @@ -32,6 +32,7 @@ import org.springframework.web.multipart.MultipartFile; import javax.annotation.Resource; import java.util.Date; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.concurrent.CompletableFuture; @@ -85,6 +86,7 @@ public class ImageServiceImpl implements ImageService { private String pvcName; @Value("${jupyter.namespace}") private String namespace; + /** * 通过ID查询单条数据 * @@ -99,8 +101,8 @@ public class ImageServiceImpl implements ImageService { /** * 分页查询 * - * @param image 筛选条件 - * @param pageRequest 分页对象 + * @param image 筛选条件 + * @param pageRequest 分页对象 * @return 查询结果 */ @Override @@ -110,7 +112,6 @@ public class ImageServiceImpl implements ImageService { } - /** * 新增数据 * @@ -138,7 +139,7 @@ public class ImageServiceImpl implements ImageService { @Override public Image update(Image image) { int currentState = image.getState(); - if(currentState == 0){ + if (currentState == 0) { throw new RuntimeException("镜像已被删除,无法更新。"); } LoginUser loginUser = SecurityUtils.getLoginUser(); @@ -163,7 +164,7 @@ public class ImageServiceImpl implements ImageService { @Override public String removeById(Integer id) throws Exception { Image image = this.imageDao.queryById(id); - if (image == null){ + if (image == null) { throw new Exception("镜像不存在"); } @@ -173,14 +174,20 @@ public class ImageServiceImpl implements ImageService { String createdBy = image.getCreateBy(); - if (!(StringUtils.equals(username,"admin") || !StringUtils.equals(username,createdBy))){ + if (!(StringUtils.equals(username, "admin") || !StringUtils.equals(username, createdBy))) { throw new Exception("无权限删除该镜像"); } - if (!imageVersionService.queryByImageId(id).isEmpty()){ - throw new Exception("请先删除该镜像下的版本文件"); +// if (!imageVersionService.queryByImageId(id).isEmpty()){ +// throw new Exception("请先删除该镜像下的版本文件"); +// } + List imageVersions = imageVersionService.queryByImageId(id); + + for (ImageVersion imageVersion : imageVersions) { + dockerClientUtil.removeImage(imageVersion.getUrl(), imageVersion.getHostIp()); } + image.setState(0); - return this.imageDao.update(image)>0?"删除成功":"删除失败"; + return this.imageDao.update(image) > 0 ? "删除成功" : "删除失败"; } @@ -207,7 +214,7 @@ public class ImageServiceImpl implements ImageService { public String insertImageAndVersion(ImageVo imageVo) throws Exception { Image existingImage = getByName(imageVo.getName()); Image imageToUse; - if(existingImage == null) { + if (existingImage == null) { // 如果不存在相同名称的镜像,则创建新的镜像记录 Image newImage = new Image(); newImage.setName(imageVo.getName()); @@ -217,7 +224,7 @@ public class ImageServiceImpl implements ImageService { if (imageToUse == null) { throw new Exception("新增镜像失败"); } - }else{ + } else { // 如果已存在相同名称的镜像,使用已存在的镜像 imageToUse = existingImage; } @@ -235,9 +242,9 @@ public class ImageServiceImpl implements ImageService { CompletableFuture.supplyAsync(() -> { Map resultMap = new HashMap<>(); try { - if(imageVo.getUploadType()==0){ - resultMap = createImageFromNet(imageVo.getName(), imageVo.getTagName(), imageVo.getPath()); - }else{ + if (imageVo.getUploadType() == 0) { + resultMap = createImageFromNet(imageVo.getName(), imageVo.getTagName(), imageVo.getPath()); + } else { resultMap = createImageFromLocal(imageVo.getName(), imageVo.getTagName(), imageVo.getPath()); } } catch (Exception e) { @@ -246,7 +253,7 @@ public class ImageServiceImpl implements ImageService { throw new RuntimeException("镜像构建失败: " + e.getMessage(), e); } return resultMap; - }).thenAccept(resultMap ->{ + }).thenAccept(resultMap -> { try { String imageUrl = resultMap.get("url"); String fileSize = resultMap.get("fileSize"); @@ -272,27 +279,27 @@ public class ImageServiceImpl implements ImageService { // 得到容器 V1Pod pod = k8sClientUtil.getNSPodList(serviceNS, deploymentName); if (pod == null) { - String podName = deploymentName+"-"+ DateUtils.formatYMD10(new Date()); - pod = k8sClientUtil.createPodWithEnv(podName,serviceNS,proxyUrl,mountPath,pvcName,image); + String podName = deploymentName + "-" + DateUtils.formatYMD10(new Date()); + pod = k8sClientUtil.createPodWithEnv(podName, serviceNS, proxyUrl, mountPath, pvcName, image); } - String loginCmd = "docker login -u " + harborUser +" -p "+harborpassword+" "+harborUrl; + String loginCmd = "docker login -u " + harborUser + " -p " + harborpassword + " " + harborUrl; // 执行命令 docker login -u admin -p Harbor12345 172.20.32.187 - String loginlog = k8sClientUtil.executeCommand(pod,loginCmd); + String loginlog = k8sClientUtil.executeCommand(pod, loginCmd); // 在这个容器的/data/admin 目录下执行命令 docker load -i fileName 得到返回的镜像名字name:tag 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 - if (StringUtils.isNoneBlank(logs2)){ + if (StringUtils.isNoneBlank(logs2)) { String[] lines = logs2.split("\n"); String lastLine = lines[lines.length - 1].trim(); String tagCmd = "docker tag " + lastLine + " " + harborUrl + "/" + repository + "/" + username + "/" + imageName + ":" + imageTag; String imageUrl = harborUrl + "/" + repository + "/" + username + "/" + imageName + ":" + imageTag; - String pushCmd = "docker push " + imageUrl; + String pushCmd = "docker push " + imageUrl; String sizeCmd = "docker inspect --format='{{.Size}}' " + imageUrl; String s = k8sClientUtil.executeCommand(pod, tagCmd); - if (StringUtils.isNotEmpty(k8sClientUtil.executeCommand(pod, pushCmd))){ + if (StringUtils.isNotEmpty(k8sClientUtil.executeCommand(pod, pushCmd))) { resultMap.put("url", imageUrl); //得到镜像文件大小 String imageSizeStr = k8sClientUtil.executeCommand(pod, sizeCmd); @@ -301,10 +308,10 @@ public class ImageServiceImpl implements ImageService { resultMap.put("fileSize", formattedImageSize); return resultMap; - }else { + } else { throw new Exception("拉取公网镜像失败,请检查网络或者镜像地址"); } - }else { + } else { throw new Exception("拉取公网镜像失败,请检查网络或者镜像地址"); } } @@ -315,27 +322,27 @@ public class ImageServiceImpl implements ImageService { // 得到容器 V1Pod pod = k8sClientUtil.getNSPodList(serviceNS, deploymentName); if (pod == null) { - String podName = deploymentName+"-"+ DateUtils.formatYMD10(new Date()); - pod = k8sClientUtil.createPodWithEnv(podName,serviceNS,proxyUrl,mountPath,pvcName,image); + String podName = deploymentName + "-" + DateUtils.formatYMD10(new Date()); + pod = k8sClientUtil.createPodWithEnv(podName, serviceNS, proxyUrl, mountPath, pvcName, image); } - String loginCmd = "docker login -u " + harborUser +" -p "+harborpassword+" "+harborUrl; + String loginCmd = "docker login -u " + harborUser + " -p " + harborpassword + " " + harborUrl; // 执行命令 docker login -u admin -p Harbor12345 172.20.32.187 - String loginlog = k8sClientUtil.executeCommand(pod,loginCmd); + String loginlog = k8sClientUtil.executeCommand(pod, loginCmd); // 在这个容器的/data/admin 目录下执行命令 docker load -i fileName 得到返回的镜像名字name:tag String username = SecurityUtils.getLoginUser().getUsername(); // - String filePath = "/data/argo-workflow/" + bucketName + "/" +path; - String logs2 = k8sClientUtil.executeCommand(pod,"docker load -i "+filePath); + String filePath = "/data/argo-workflow/" + bucketName + "/" + path; + String logs2 = k8sClientUtil.executeCommand(pod, "docker load -i " + filePath); // 在容器里执行 docker tag name:tag nexus3.kube-system.svc:8083/imageName:imageTag - if (StringUtils.isNoneBlank(logs2)){ - String substring = logs2.substring(logs2.indexOf(":")+1).trim(); + if (StringUtils.isNoneBlank(logs2)) { + String substring = logs2.substring(logs2.indexOf(":") + 1).trim(); String tagCmd = "docker tag " + substring + " " + harborUrl + "/" + repository + "/" + username + "/" + imageName + ":" + imageTag; String imageUrl = harborUrl + "/" + repository + "/" + username + "/" + imageName + ":" + imageTag; - String pushCmd = "docker push " + imageUrl; + String pushCmd = "docker push " + imageUrl; String sizeCmd = "docker inspect --format='{{.Size}}' " + imageUrl; String s = k8sClientUtil.executeCommand(pod, tagCmd); - if (StringUtils.isNotEmpty(k8sClientUtil.executeCommand(pod, pushCmd))){ + if (StringUtils.isNotEmpty(k8sClientUtil.executeCommand(pod, pushCmd))) { resultMap.put("url", imageUrl); //得到镜像文件大小 String imageSizeStr = k8sClientUtil.executeCommand(pod, sizeCmd); @@ -343,43 +350,49 @@ public class ImageServiceImpl implements ImageService { String formattedImageSize = FileUtil.formatFileSize(sizeInBytes); // 格式化镜像文件大小 resultMap.put("fileSize", formattedImageSize); return resultMap; - }else { + } else { throw new Exception("解析镜像压缩包失败,请检查镜像文件"); } - }else { + } else { throw new Exception("解析镜像压缩包失败,请检查镜像文件"); } } - - @Override public Map uploadImageFiles(MultipartFile file) throws Exception { LoginUser loginUser = SecurityUtils.getLoginUser(); - String path = loginUser.getUsername()+"/"+file.getOriginalFilename(); + String path = loginUser.getUsername() + "/" + file.getOriginalFilename(); return minioService.uploadFile(bucketName, path, file); } @Override @Transactional + @Async public String saveImage(ImageVo imageVo) { - if(imageDao.getByName(imageVo.getName()) != null){ - throw new IllegalStateException("镜像名称已存在"); + Image oldImage = imageDao.getByName(imageVo.getName()); + if (oldImage != null) { + List oldImageVersions = imageVersionDao.queryByImageId(oldImage.getId()); + for (ImageVersion oldImageVersion : oldImageVersions) { + if(oldImageVersion.getTagName().equals(imageVo.getTagName())){ + throw new IllegalStateException("镜像tag不能重复"); + } + } } + LoginUser loginUser = SecurityUtils.getLoginUser(); String username = loginUser.getUsername().toLowerCase(); - String podName = username +"-editor-pod" + "-" + imageVo.getDevEnvironmentId().toString(); + 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); + dockerClientUtil.commitImage(imageVo, containerId, hostIp, username); HashMap resultMap = dockerClientUtil.pushImageToHorbor(imageVo, hostIp); Image image = new Image(); - BeanUtils.copyProperties(imageVo,image); + BeanUtils.copyProperties(imageVo, image); image.setImageType(Constant.Image_Type_Pri); image.setCreateBy(username); image.setUpdateBy(username); @@ -396,6 +409,7 @@ public class ImageServiceImpl implements ImageService { imageVersion.setFileSize(resultMap.get("size")); imageVersion.setCreateBy(username); imageVersion.setUpdateBy(username); + imageVersion.setHostIp(hostIp); imageVersion.setUpdateTime(new Date()); imageVersion.setCreateTime(new Date()); imageVersion.setState(1); @@ -410,7 +424,7 @@ public class ImageServiceImpl implements ImageService { return "保存镜像成功"; } catch (Exception e) { - throw new RuntimeException("保存镜像失败:" +e); + throw new RuntimeException("保存镜像失败:" + e); } } } diff --git a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/utils/DockerClientUtil.java b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/utils/DockerClientUtil.java index b20fa07..552b025 100644 --- a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/utils/DockerClientUtil.java +++ b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/utils/DockerClientUtil.java @@ -106,4 +106,9 @@ public class DockerClientUtil { } } + + public void removeImage(String imageName, String hostIp){ + DockerClient dockerClient = getDockerClient(hostIp); + dockerClient.removeImageCmd(imageName).withForce(true).exec(); + } } \ No newline at end of file