| @@ -4,6 +4,7 @@ import com.ruoyi.common.core.web.controller.BaseController; | |||
| import com.ruoyi.common.core.web.domain.GenericsAjaxResult; | |||
| import com.ruoyi.platform.domain.DatasetVersion; | |||
| import com.ruoyi.platform.service.DatasetVersionService; | |||
| import com.ruoyi.platform.vo.LabelDatasetVersion; | |||
| import io.swagger.annotations.ApiOperation; | |||
| import org.springframework.data.domain.Page; | |||
| import org.springframework.data.domain.PageRequest; | |||
| @@ -135,5 +136,10 @@ public class DatasetVersionController extends BaseController { | |||
| 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.DatasetVersion; | |||
| import com.ruoyi.platform.vo.LabelDatasetVersion; | |||
| import org.springframework.data.domain.Page; | |||
| import org.springframework.data.domain.PageRequest; | |||
| @@ -73,4 +74,6 @@ public interface DatasetVersionService { | |||
| void checkDeclaredVersion(DatasetVersion insert) 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.mapper.DatasetVersionDao; | |||
| 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 org.apache.commons.lang3.StringUtils; | |||
| import org.springframework.data.domain.Page; | |||
| @@ -16,6 +18,7 @@ import org.springframework.data.domain.PageRequest; | |||
| import org.springframework.stereotype.Service; | |||
| import javax.annotation.Resource; | |||
| import java.io.InputStream; | |||
| import java.lang.reflect.Field; | |||
| import java.util.Date; | |||
| import java.util.HashMap; | |||
| @@ -32,7 +35,6 @@ import java.util.Map; | |||
| public class DatasetVersionServiceImpl implements DatasetVersionService { | |||
| @Resource | |||
| private DatasetVersionDao datasetVersionDao; | |||
| // 固定存储桶名 | |||
| private final String bucketName = "platform-data"; | |||
| @@ -193,8 +195,15 @@ public class DatasetVersionServiceImpl implements DatasetVersionService { | |||
| 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 { | |||
| @@ -1,5 +1,6 @@ | |||
| package com.ruoyi.platform.service.impl; | |||
| import com.alibaba.fastjson2.util.DateUtils; | |||
| import com.ruoyi.common.security.utils.SecurityUtils; | |||
| import com.ruoyi.platform.domain.Image; | |||
| 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.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.factory.annotation.Value; | |||
| @@ -64,6 +66,15 @@ public class ImageServiceImpl implements ImageService { | |||
| private String deploymentName; | |||
| @Value("${harbor.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查询单条数据 | |||
| * | |||
| @@ -251,7 +262,8 @@ public class ImageServiceImpl implements ImageService { | |||
| // 得到容器 | |||
| V1Pod pod = k8sClientUtil.getNSPodList(serviceNS, deploymentName); | |||
| 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; | |||
| // 执行命令 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); | |||
| 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; | |||
| // 执行命令 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(); | |||
| 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; | |||
| } | |||
| /** | |||
| * 发送 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 { | |||
| @Override | |||
| public void checkClientTrusted(X509Certificate[] chain, String authType) { | |||
| @@ -382,7 +382,7 @@ public class K8sClientUtil { | |||
| // invokes the CoreV1Api client | |||
| for (V1Pod item : v1PodList.getItems()) { | |||
| String generateName = item.getMetadata().getGenerateName(); | |||
| String generateName = item.getMetadata().getName(); | |||
| if (StringUtils.isNotEmpty(generateName) && generateName.startsWith(deploymentName)) { | |||
| // 找到匹配的Pod,获取其名称 | |||
| 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; | |||
| } | |||
| } | |||