diff --git a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/controller/image/ImageController.java b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/controller/image/ImageController.java index 273068f2..f5bc75d0 100644 --- a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/controller/image/ImageController.java +++ b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/controller/image/ImageController.java @@ -122,8 +122,8 @@ public class ImageController { @ApiOperation("从本地上传构建镜像") public AjaxResult createImageFromLocal(@RequestParam("name") String imageName, @RequestParam("tag") String imageTag, - @RequestParam("description") String imageDescription){ - return AjaxResult.success(this.imageService.createImageFromLocal(imageName,imageTag,imageDescription)); + @RequestParam("path") String path) throws Exception { + return AjaxResult.success(this.imageService.createImageFromLocal(imageName,imageTag,path)); } diff --git a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/controller/tensorBoard/tensorBoard.java b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/controller/tensorBoard/tensorBoard.java index 04684ac7..5fd78fab 100644 --- a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/controller/tensorBoard/tensorBoard.java +++ b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/controller/tensorBoard/tensorBoard.java @@ -8,4 +8,8 @@ import org.springframework.web.bind.annotation.RestController; @RequestMapping("tensorBoard") @Api("流水线管理") public class tensorBoard { + + //状态查询接口 + + //启动tensorBoard接口 } diff --git a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/ImageService.java b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/ImageService.java index 78e67ec6..cb247643 100644 --- a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/ImageService.java +++ b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/ImageService.java @@ -74,7 +74,7 @@ public interface ImageService { * @param imageDescription * @return */ - String createImageFromLocal(String imageName, String imageTag, String imageDescription); + String createImageFromLocal(String imageName, String imageTag, String imageDescription) throws Exception; Map uploadImageFiles(MultipartFile file) throws Exception; 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 f2c5f97e..26f7da5c 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 @@ -8,9 +8,12 @@ import com.ruoyi.platform.service.ImageService; import com.ruoyi.platform.service.ImageVersionService; import com.ruoyi.platform.service.MinioService; 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.V1Pod; import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageImpl; @@ -43,11 +46,22 @@ public class ImageServiceImpl implements ImageService { @Resource private ImageVersionDao imageVersionDao; - @Resource private MinioService minioService; - + @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; + @Value("${harbor.deploymentName}") + private String deploymentName; + @Value("${harbor.serviceNS}") + private String serviceNS; /** * 通过ID查询单条数据 * @@ -178,15 +192,36 @@ public class ImageServiceImpl implements ImageService { } @Override - public String createImageFromLocal(String imageName, String imageTag, String fileName) { - // TODO 检查环境是否存在,如果不存在,请开启容器 - - // TODO 在容器的/data/admin 目录下执行命令 docker load -i fileName 得到返回的镜像名字name:tag - - // TODO 在容器里执行 docker tag name:tag nexus3.kube-system.svc:8083/imageName:imageTag - - - return null; + public String createImageFromLocal(String imageName, String imageTag, String path) throws Exception { + // 得到容器 + V1Pod pod = K8sClientUtil.getNSPodList(serviceNS, deploymentName); + if (pod == null) { + throw new Exception("镜像推送服务不存在"); + } + 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); + // 在这个容器的/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); + // 在容器里执行 docker tag name:tag nexus3.kube-system.svc:8083/imageName:imageTag + if (StringUtils.isNoneBlank(logs2)){ + String substring = logs2.substring(logs2.indexOf(harborUrl), logs2.length()); + String cleanedString = substring.replaceAll("(\\r|\\n)", ""); + String cmd1 = "docker tag " + cleanedString+ " " + harborUrl+"/"+repository+"/"+username+"/" + imageName + imageTag; + String imageUrl = harborUrl+"/"+repository+"/"+username+"/" + imageName + imageTag; + String cmd2 = "docker push " + imageUrl; + String s = K8sClientUtil.executeCommand(pod, cmd1); + if (StringUtils.isNotEmpty(K8sClientUtil.executeCommand(pod, cmd2))){ + return imageUrl; + }else { + throw new Exception("解析镜像压缩包失败,请检查镜像文件"); + } + }else { + throw new Exception("解析镜像压缩包失败,请检查镜像文件"); + } } @Override diff --git a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/utils/K8sClientUtil.java b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/utils/K8sClientUtil.java index 65f08456..fab2b2c3 100644 --- a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/utils/K8sClientUtil.java +++ b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/utils/K8sClientUtil.java @@ -1,5 +1,6 @@ package com.ruoyi.platform.utils; +import io.kubernetes.client.Exec; import io.kubernetes.client.custom.IntOrString; import io.kubernetes.client.custom.Quantity; import io.kubernetes.client.openapi.ApiClient; @@ -13,6 +14,9 @@ import org.apache.commons.lang.StringUtils; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.Map; @@ -48,7 +52,7 @@ public class K8sClientUtil { try { this.apiClient = new ClientBuilder(). setBasePath("https://172.20.32.181:6443").setVerifyingSsl(false). - setAuthentication(new AccessTokenAuthentication("eyJhbGciOiJSUzI1NiIsImtpZCI6IjRWcFBPWl9YSFFxQ2tVanRuNHdRT1dnUlJNTnB2bG5TQlVSRjNKdExWNDQifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlLXN5c3RlbSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJkZWZhdWx0LXRva2VuLXNteGxuIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQubmFtZSI6ImRlZmF1bHQiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC51aWQiOiIyZWY1ZjdkMC0zMTdkLTQxN2UtOWY4Ni1mYjA1OTFhYWVhZDQiLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6a3ViZS1zeXN0ZW06ZGVmYXVsdCJ9.GMpReYK7YJ0nNy-F6VrUJQzjWQiSauAOeq0-DT8ik2Lx8f2eznYEm_3cHX4kIn_nYgfxo857urcHt4Ft6IgVtWzxLzVTCQVaNP_H2J8bnJn8W2tUKXzF_3d_GwO75H7kN8P3aoShULrOLpiIf3o3Az28_gwHkwCnd42npcKrCXfAKj8A2U7-KUFQXXA-etrWSw81C5t8ziL-2xaiDgwD3ewH-TNYsOpyWjGopNTxJn1F7GyJ7xDlmMJOaZhSnOrDggB7lqDEsE68YmZtqB7lcSaZHnKzvNhEdbKri4R7_urpjttz_k6qcfIi-l6GwPtJLatsPDg3OL3FFnzjvArJ-A")).build(); + setAuthentication(new AccessTokenAuthentication("eyJhbGciOiJSUzI1NiIsImtpZCI6IjRWcFBPWl9YSFFxQ2tVanRuNHdRT1dnUlJNTnB2bG5TQlVSRjNKdExWNDQifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJkZWZhdWx0Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZWNyZXQubmFtZSI6ImFkbWluLXNlcnZpY2UtYWNjb3VudC10b2tlbi14ZDk5eiIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50Lm5hbWUiOiJhZG1pbi1zZXJ2aWNlLWFjY291bnQiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC51aWQiOiJmMGEzNmYyMS01MjQyLTQ4MTAtYWVmZS0xOTEwOTZlZjc5YmUiLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6ZGVmYXVsdDphZG1pbi1zZXJ2aWNlLWFjY291bnQifQ.fo-Wf0-5-IRC5fhRh65yfqCJqKfE9MrNFIXL2fd1CqVAHD7JBpWO2IsFiSmz9Bm7VfLmFAp2NB7DjW4ZLjC7ODiGhpSseBP8x4ceFuHL6pRGUsEBvHQBBBuQcGhNOcsxIDHnDqUdUzoLprj223lMZNTQowITuqYFU4GVbethyEuS6G5Wh9KHI3KYHFtG4_AeWBgI5Ppz8pDrhHzSFWTFbzxQ3RPGEwF0V-9wEtdrSYnfETi3rdRWif9W4a0RW8HwD9Gf7UCYcyFOs7e5_3-IvmctS85g87PYIfHXMhu_kOw-_Il4bkwPEK5uiBFDw0M1-s9YP-F9r5sXXvOJlsAr1g")).build(); } catch (Exception e) { log.error("构建K8s-Client异常", e); throw new RuntimeException("构建K8s-Client异常"); @@ -62,16 +66,16 @@ public class K8sClientUtil { * * @param kubeConfigPath kube连接配置文件 */ - public K8sClientUtil(String kubeConfigPath) { - try { - this.apiClient = new ClientBuilder(). - setBasePath("https://172.20.32.181:6443").setVerifyingSsl(false). - setAuthentication(new AccessTokenAuthentication("eyJhbGciOiJSUzI1NiIsImtpZCI6IjRWcFBPWl9YSFFxQ2tVanRuNHdRT1dnUlJNTnB2bG5TQlVSRjNKdExWNDQifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlLXN5c3RlbSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJkZWZhdWx0LXRva2VuLXNteGxuIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQubmFtZSI6ImRlZmF1bHQiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC51aWQiOiIyZWY1ZjdkMC0zMTdkLTQxN2UtOWY4Ni1mYjA1OTFhYWVhZDQiLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6a3ViZS1zeXN0ZW06ZGVmYXVsdCJ9.GMpReYK7YJ0nNy-F6VrUJQzjWQiSauAOeq0-DT8ik2Lx8f2eznYEm_3cHX4kIn_nYgfxo857urcHt4Ft6IgVtWzxLzVTCQVaNP_H2J8bnJn8W2tUKXzF_3d_GwO75H7kN8P3aoShULrOLpiIf3o3Az28_gwHkwCnd42npcKrCXfAKj8A2U7-KUFQXXA-etrWSw81C5t8ziL-2xaiDgwD3ewH-TNYsOpyWjGopNTxJn1F7GyJ7xDlmMJOaZhSnOrDggB7lqDEsE68YmZtqB7lcSaZHnKzvNhEdbKri4R7_urpjttz_k6qcfIi-l6GwPtJLatsPDg3OL3FFnzjvArJ-A")).build(); - } catch (Exception e) { - log.error("构建K8s-Client异常", e); - throw new RuntimeException("构建K8s-Client异常"); - } - } +// public K8sClientUtil(String kubeConfigPath) { +// try { +// this.apiClient = new ClientBuilder(). +// setBasePath("https://172.20.32.181:6443").setVerifyingSsl(false). +// setAuthentication(new AccessTokenAuthentication("eyJhbGciOiJSUzI1NiIsImtpZCI6IjRWcFBPWl9YSFFxQ2tVanRuNHdRT1dnUlJNTnB2bG5TQlVSRjNKdExWNDQifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlLXN5c3RlbSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJkZWZhdWx0LXRva2VuLXNteGxuIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQubmFtZSI6ImRlZmF1bHQiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC51aWQiOiIyZWY1ZjdkMC0zMTdkLTQxN2UtOWY4Ni1mYjA1OTFhYWVhZDQiLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6a3ViZS1zeXN0ZW06ZGVmYXVsdCJ9.GMpReYK7YJ0nNy-F6VrUJQzjWQiSauAOeq0-DT8ik2Lx8f2eznYEm_3cHX4kIn_nYgfxo857urcHt4Ft6IgVtWzxLzVTCQVaNP_H2J8bnJn8W2tUKXzF_3d_GwO75H7kN8P3aoShULrOLpiIf3o3Az28_gwHkwCnd42npcKrCXfAKj8A2U7-KUFQXXA-etrWSw81C5t8ziL-2xaiDgwD3ewH-TNYsOpyWjGopNTxJn1F7GyJ7xDlmMJOaZhSnOrDggB7lqDEsE68YmZtqB7lcSaZHnKzvNhEdbKri4R7_urpjttz_k6qcfIi-l6GwPtJLatsPDg3OL3FFnzjvArJ-A")).build(); +// } catch (Exception e) { +// log.error("构建K8s-Client异常", e); +// throw new RuntimeException("构建K8s-Client异常"); +// } +// } /** * 获取所有的Pod @@ -269,4 +273,52 @@ public class K8sClientUtil { V1Service service = createService(namespace, podName + "-svc", port, selector); return service.getSpec().getPorts().get(0).getNodePort(); } + + + /** + * 根据获取namespace,deploymentName的Pod Name + * + * @return podList + */ + public static V1Pod getNSPodList(String namespace,String deploymentName) throws Exception { + // new a CoreV1Api + CoreV1Api api = new CoreV1Api(apiClient); + V1PodList v1PodList = null; + try { + v1PodList = api.listNamespacedPod(namespace, null, null, null, null, null, null, null, null, null, null); + } catch (ApiException e) { + log.error("获取 POD 异常:", e); + } + // invokes the CoreV1Api client + + for (V1Pod item : v1PodList.getItems()) { + if (item.getMetadata().getGenerateName().startsWith(deploymentName)) { + // 找到匹配的Pod,获取其名称 + return item; + } + } + return null; + } + + public static String executeCommand(V1Pod item, String command) { + try { + // 创建API实例 + // 创建Exec实例 + Exec exec = new Exec(apiClient); + String[] cmd = { "/bin/sh", "-c", command}; + Process proc = exec.exec(item, cmd, false); + // 读取输出 + BufferedReader reader = new BufferedReader(new InputStreamReader(proc.getInputStream())); + StringBuilder builder = new StringBuilder(); + String line = null; + while ((line = reader.readLine()) != null) { + builder.append(line); + builder.append(System.getProperty("line.separator")); + } + return builder.toString(); + } catch (Exception e) { + log.error("执行命令异常", e); + throw new RuntimeException("执行命令异常"); + } + } } diff --git a/ruoyi-modules/management-platform/src/main/resources/k8sconfig/clusterrolebinding.yaml b/ruoyi-modules/management-platform/src/main/resources/k8sconfig/clusterrolebinding.yaml new file mode 100644 index 00000000..1e76e022 --- /dev/null +++ b/ruoyi-modules/management-platform/src/main/resources/k8sconfig/clusterrolebinding.yaml @@ -0,0 +1,13 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: admin-service-account-binding +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: cluster-admin +subjects: +- kind: ServiceAccount + name: admin-service-account + namespace: default +