| @@ -4,6 +4,7 @@ import com.ruoyi.common.core.web.controller.BaseController; | |||||
| import com.ruoyi.common.core.web.domain.GenericsAjaxResult; | import com.ruoyi.common.core.web.domain.GenericsAjaxResult; | ||||
| import com.ruoyi.platform.domain.DatasetVersion; | import com.ruoyi.platform.domain.DatasetVersion; | ||||
| import com.ruoyi.platform.service.DatasetVersionService; | import com.ruoyi.platform.service.DatasetVersionService; | ||||
| import com.ruoyi.platform.vo.LabelDatasetVersion; | |||||
| import io.swagger.annotations.ApiOperation; | 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; | ||||
| @@ -135,5 +136,10 @@ public class DatasetVersionController extends BaseController { | |||||
| return genericsSuccess(this.datasetVersionService.deleteDatasetVersion(datasetId, version)); | return genericsSuccess(this.datasetVersionService.deleteDatasetVersion(datasetId, version)); | ||||
| } | } | ||||
| @PostMapping("/addDatasetVersionsFromLabel") | |||||
| @ApiOperation("从数据标注添加数据集版本") | |||||
| public GenericsAjaxResult<Boolean> addDatasetVersionsFromLabel(@RequestBody LabelDatasetVersion labelDatasetVersion) throws Exception { | |||||
| return genericsSuccess(true); | |||||
| } | |||||
| } | } | ||||
| @@ -5,6 +5,7 @@ package com.ruoyi.platform.service; | |||||
| import com.ruoyi.platform.domain.Dataset; | import com.ruoyi.platform.domain.Dataset; | ||||
| import com.ruoyi.platform.domain.DatasetVersion; | import com.ruoyi.platform.domain.DatasetVersion; | ||||
| import com.ruoyi.platform.vo.LabelDatasetVersion; | |||||
| import org.springframework.data.domain.Page; | import org.springframework.data.domain.Page; | ||||
| import org.springframework.data.domain.PageRequest; | import org.springframework.data.domain.PageRequest; | ||||
| @@ -73,4 +74,6 @@ public interface DatasetVersionService { | |||||
| void checkDeclaredVersion(DatasetVersion insert) throws Exception; | void checkDeclaredVersion(DatasetVersion insert) throws Exception; | ||||
| String addDatasetVersions(List<DatasetVersion> datasetVersions) throws Exception; | String addDatasetVersions(List<DatasetVersion> datasetVersions) throws Exception; | ||||
| void addDatasetVersionsFromLabel(LabelDatasetVersion labelDatasetVersion) throws Exception; | |||||
| } | } | ||||
| @@ -8,6 +8,8 @@ import com.ruoyi.platform.domain.ModelsVersion; | |||||
| import com.ruoyi.platform.domain.Workflow; | import com.ruoyi.platform.domain.Workflow; | ||||
| import com.ruoyi.platform.mapper.DatasetVersionDao; | import com.ruoyi.platform.mapper.DatasetVersionDao; | ||||
| import com.ruoyi.platform.service.DatasetVersionService; | import com.ruoyi.platform.service.DatasetVersionService; | ||||
| import com.ruoyi.platform.utils.HttpUtils; | |||||
| import com.ruoyi.platform.vo.LabelDatasetVersion; | |||||
| import com.ruoyi.system.api.model.LoginUser; | import com.ruoyi.system.api.model.LoginUser; | ||||
| import org.apache.commons.lang3.StringUtils; | import org.apache.commons.lang3.StringUtils; | ||||
| import org.springframework.data.domain.Page; | import org.springframework.data.domain.Page; | ||||
| @@ -16,6 +18,7 @@ import org.springframework.data.domain.PageRequest; | |||||
| import org.springframework.stereotype.Service; | import org.springframework.stereotype.Service; | ||||
| import javax.annotation.Resource; | import javax.annotation.Resource; | ||||
| import java.io.InputStream; | |||||
| import java.lang.reflect.Field; | import java.lang.reflect.Field; | ||||
| import java.util.Date; | import java.util.Date; | ||||
| import java.util.HashMap; | import java.util.HashMap; | ||||
| @@ -32,7 +35,6 @@ import java.util.Map; | |||||
| public class DatasetVersionServiceImpl implements DatasetVersionService { | public class DatasetVersionServiceImpl implements DatasetVersionService { | ||||
| @Resource | @Resource | ||||
| private DatasetVersionDao datasetVersionDao; | private DatasetVersionDao datasetVersionDao; | ||||
| // 固定存储桶名 | // 固定存储桶名 | ||||
| private final String bucketName = "platform-data"; | private final String bucketName = "platform-data"; | ||||
| @@ -193,8 +195,15 @@ public class DatasetVersionServiceImpl implements DatasetVersionService { | |||||
| throw new Exception("新增数据集版本失败: " + e.getMessage()); | throw new Exception("新增数据集版本失败: " + e.getMessage()); | ||||
| } | } | ||||
| } | |||||
| @Override | |||||
| public void addDatasetVersionsFromLabel(LabelDatasetVersion labelDatasetVersion) throws Exception{ | |||||
| // 获取label-studio数据流 | |||||
| InputStream inputStream = HttpUtils.getInputStream("http://127.0.0.1:8080/api/projects/"+labelDatasetVersion.getProject_id()+"/export?exportType="+labelDatasetVersion.getExportType(), labelDatasetVersion.getToken()); | |||||
| // 上传镜像至minio | |||||
| //保存DatasetVersion | |||||
| } | } | ||||
| private void insertPrepare(DatasetVersion datasetVersion) throws Exception { | private void insertPrepare(DatasetVersion datasetVersion) throws Exception { | ||||
| @@ -1,5 +1,6 @@ | |||||
| package com.ruoyi.platform.service.impl; | package com.ruoyi.platform.service.impl; | ||||
| import com.alibaba.fastjson2.util.DateUtils; | |||||
| import com.ruoyi.common.security.utils.SecurityUtils; | import com.ruoyi.common.security.utils.SecurityUtils; | ||||
| import com.ruoyi.platform.domain.Image; | import com.ruoyi.platform.domain.Image; | ||||
| import com.ruoyi.platform.domain.ImageVersion; | import com.ruoyi.platform.domain.ImageVersion; | ||||
| @@ -12,6 +13,7 @@ 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; | ||||
| import io.kubernetes.client.openapi.models.V1PersistentVolumeClaim; | |||||
| import io.kubernetes.client.openapi.models.V1Pod; | import io.kubernetes.client.openapi.models.V1Pod; | ||||
| import org.apache.commons.lang3.StringUtils; | import org.apache.commons.lang3.StringUtils; | ||||
| import org.springframework.beans.factory.annotation.Value; | import org.springframework.beans.factory.annotation.Value; | ||||
| @@ -64,6 +66,15 @@ public class ImageServiceImpl implements ImageService { | |||||
| private String deploymentName; | private String deploymentName; | ||||
| @Value("${harbor.serviceNS}") | @Value("${harbor.serviceNS}") | ||||
| private String serviceNS; | private String serviceNS; | ||||
| @Value("${dockerpush.image}") | |||||
| private String image; | |||||
| @Value("${dockerpush.mountPath}") | |||||
| private String mountPath; | |||||
| @Value("${dockerpush.proxyUrl}") | |||||
| private String proxyUrl; | |||||
| @Value("${minio.pvcName}") | |||||
| private String pvcName; | |||||
| /** | /** | ||||
| * 通过ID查询单条数据 | * 通过ID查询单条数据 | ||||
| * | * | ||||
| @@ -251,7 +262,8 @@ public class ImageServiceImpl implements ImageService { | |||||
| // 得到容器 | // 得到容器 | ||||
| V1Pod pod = k8sClientUtil.getNSPodList(serviceNS, deploymentName); | V1Pod pod = k8sClientUtil.getNSPodList(serviceNS, deploymentName); | ||||
| if (pod == null) { | if (pod == null) { | ||||
| throw new Exception("镜像推送服务不存在"); | |||||
| String podName = deploymentName+"-"+ DateUtils.formatYMD10(new Date()); | |||||
| pod = createPod(serviceNS, podName); | |||||
| } | } | ||||
| 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 | // 执行命令 docker login -u admin -p Harbor12345 172.20.32.187 | ||||
| @@ -292,7 +304,8 @@ public class ImageServiceImpl implements ImageService { | |||||
| // 得到容器 | // 得到容器 | ||||
| V1Pod pod = k8sClientUtil.getNSPodList(serviceNS, deploymentName); | V1Pod pod = k8sClientUtil.getNSPodList(serviceNS, deploymentName); | ||||
| if (pod == null) { | if (pod == null) { | ||||
| throw new Exception("镜像推送服务不存在"); | |||||
| String podName = deploymentName+"-"+ DateUtils.formatYMD10(new Date()); | |||||
| pod = createPod(serviceNS, podName); | |||||
| } | } | ||||
| 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 | // 执行命令 docker login -u admin -p Harbor12345 172.20.32.187 | ||||
| @@ -333,4 +346,8 @@ public class ImageServiceImpl implements ImageService { | |||||
| String path = loginUser.getUsername()+"/"+file.getOriginalFilename(); | String path = loginUser.getUsername()+"/"+file.getOriginalFilename(); | ||||
| return minioService.uploadFile(bucketName, path, file); | return minioService.uploadFile(bucketName, path, file); | ||||
| } | } | ||||
| private V1Pod createPod(String namespace, String podName){ | |||||
| return k8sClientUtil.createPodWithEnv(podName,namespace,proxyUrl,mountPath,pvcName,image); | |||||
| } | |||||
| } | } | ||||
| @@ -374,6 +374,29 @@ public class HttpUtils { | |||||
| return httpClient; | return httpClient; | ||||
| } | } | ||||
| /** | |||||
| * 发送 HTTP 请求并返回二进制数据流(InputStream)。 | |||||
| * | |||||
| * @param url 请求的 URL 地址。 | |||||
| * @param token 要携带的 Token。 | |||||
| * @return 服务器响应的二进制数据流(InputStream)。 | |||||
| * @throws IOException 如果请求失败或发生其他 I/O 错误。 | |||||
| */ | |||||
| public static InputStream getInputStream(String url, String token) throws IOException { | |||||
| URL requestUrl = new URL(url); | |||||
| HttpURLConnection connection = (HttpURLConnection) requestUrl.openConnection(); | |||||
| connection.setRequestMethod("GET"); | |||||
| connection.setRequestProperty("Authorization", "Bearer " + token); // 添加 Authorization 头部,携带 Token | |||||
| int responseCode = connection.getResponseCode(); | |||||
| if (responseCode == HttpURLConnection.HTTP_OK) { | |||||
| return connection.getInputStream(); // 获取响应的输入流 | |||||
| } else { | |||||
| throw new IOException("HTTP 请求失败,状态码:" + responseCode); | |||||
| } | |||||
| } | |||||
| private static class TrustAnyTrustManager implements X509TrustManager { | private static class TrustAnyTrustManager implements X509TrustManager { | ||||
| @Override | @Override | ||||
| public void checkClientTrusted(X509Certificate[] chain, String authType) { | public void checkClientTrusted(X509Certificate[] chain, String authType) { | ||||
| @@ -382,7 +382,7 @@ public class K8sClientUtil { | |||||
| // invokes the CoreV1Api client | // invokes the CoreV1Api client | ||||
| for (V1Pod item : v1PodList.getItems()) { | for (V1Pod item : v1PodList.getItems()) { | ||||
| String generateName = item.getMetadata().getGenerateName(); | |||||
| String generateName = item.getMetadata().getName(); | |||||
| if (StringUtils.isNotEmpty(generateName) && generateName.startsWith(deploymentName)) { | if (StringUtils.isNotEmpty(generateName) && generateName.startsWith(deploymentName)) { | ||||
| // 找到匹配的Pod,获取其名称 | // 找到匹配的Pod,获取其名称 | ||||
| return item; | return item; | ||||
| @@ -440,4 +440,46 @@ public class K8sClientUtil { | |||||
| } | } | ||||
| } | } | ||||
| public V1Pod createPodWithEnv(String podName,String namespace,String proxyUrl ,String mountPath,String pvcName, String image){ | |||||
| CoreV1Api api = new CoreV1Api(apiClient); | |||||
| V1PodList v1PodList = null; | |||||
| V1Pod pod = new V1PodBuilder() | |||||
| .withNewMetadata() | |||||
| .withName(podName) | |||||
| .endMetadata() | |||||
| .withNewSpec() | |||||
| .addNewContainer() | |||||
| .withName(podName) | |||||
| .withImage(image) // 替换为您实际要使用的镜像名称 | |||||
| .withVolumeMounts(new V1VolumeMount().name("workspace").mountPath(mountPath)) | |||||
| .withNewSecurityContext().withNewPrivileged(true).endSecurityContext() | |||||
| .addNewEnv() | |||||
| .withName("HTTP_PROXY") | |||||
| .withValue(proxyUrl) | |||||
| .endEnv() | |||||
| .addNewEnv() | |||||
| .withName("HTTPS_PROXY") | |||||
| .withValue(proxyUrl) | |||||
| .endEnv() | |||||
| .addNewEnv() | |||||
| .withName("NO_PROXY") | |||||
| .withValue("localhost,kubernetes.default.svc") | |||||
| .endEnv() | |||||
| .endContainer() | |||||
| .addNewVolume() | |||||
| .withName("workspace").withPersistentVolumeClaim(new V1PersistentVolumeClaimVolumeSource().claimName(pvcName)) | |||||
| .endVolume() | |||||
| .endSpec() | |||||
| .build(); | |||||
| try { | |||||
| pod = api.createNamespacedPod(namespace, pod, null, null, null); | |||||
| } catch (ApiException e) { | |||||
| log.error("创建pod异常:" + e.getResponseBody(), e); | |||||
| } catch (Exception e) { | |||||
| log.error("创建pod系统异常:", e); | |||||
| } | |||||
| return pod; | |||||
| } | |||||
| } | } | ||||
| @@ -0,0 +1,63 @@ | |||||
| package com.ruoyi.platform.vo; | |||||
| import com.fasterxml.jackson.databind.PropertyNamingStrategy; | |||||
| import com.fasterxml.jackson.databind.annotation.JsonNaming; | |||||
| import java.io.Serializable; | |||||
| @JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class) | |||||
| public class LabelDatasetVersion implements Serializable { | |||||
| private String token; | |||||
| private String project_id; | |||||
| private String dataset_id; | |||||
| private String version; | |||||
| private String desc; | |||||
| private String exportType; | |||||
| public String getToken() { | |||||
| return token; | |||||
| } | |||||
| public void setToken(String token) { | |||||
| this.token = token; | |||||
| } | |||||
| public String getProject_id() { | |||||
| return project_id; | |||||
| } | |||||
| public void setProject_id(String project_id) { | |||||
| this.project_id = project_id; | |||||
| } | |||||
| public String getDataset_id() { | |||||
| return dataset_id; | |||||
| } | |||||
| public void setDataset_id(String dataset_id) { | |||||
| this.dataset_id = dataset_id; | |||||
| } | |||||
| public String getVersion() { | |||||
| return version; | |||||
| } | |||||
| public void setVersion(String version) { | |||||
| this.version = version; | |||||
| } | |||||
| public String getDesc() { | |||||
| return desc; | |||||
| } | |||||
| public void setDesc(String desc) { | |||||
| this.desc = desc; | |||||
| } | |||||
| public String getExportType() { | |||||
| return exportType; | |||||
| } | |||||
| public void setExportType(String exportType) { | |||||
| this.exportType = exportType; | |||||
| } | |||||
| } | |||||