You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
autoflow-server-mgmt/src/main/java/kr/re/etri/autoflow/controllers/PipelineUploadController.java

149 lines
5.8 KiB

package kr.re.etri.autoflow.controllers;
import io.minio.MinioClient;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import kr.re.etri.autoflow.entity.StorageAttachmentEntity;
import kr.re.etri.autoflow.entity.WorkflowEntity;
import kr.re.etri.autoflow.payload.request.CreateRunRequest;
import kr.re.etri.autoflow.service.StorageAttachmentService;
import kr.re.etri.autoflow.service.PipelineUploadService;
import kr.re.etri.autoflow.service.WorkFlowService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
@Slf4j
@RestController
@RequestMapping("/pipelines")
@RequiredArgsConstructor
@CrossOrigin(origins = "*")
@io.swagger.v3.oas.annotations.tags.Tag(name = "Kubeflow Pipeline", description = "Kubeflow 파이프라인 API")
public class PipelineUploadController {
private final PipelineUploadService pipelineUploadService;
private final WorkFlowService workFlowService;
private final StorageAttachmentService minioAttachmentService;
@PostMapping(value = "/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public ResponseEntity<Map<String, Object>> uploadPipeline(
@RequestParam("uploadfile") MultipartFile file,
@RequestParam("name") String name,
@RequestParam("display_name") String displayName,
@RequestParam(value = "description", required = false) String description,
@RequestParam(value = "namespace", required = false) String namespace,
@RequestParam("regUserId") String regUserId,
@RequestParam("projectId") Long projectId
) {
try {
// description 한글 디코딩
String decodedDescription = description != null
? URLDecoder.decode(description, StandardCharsets.UTF_8)
: null;
// 1. Kubeflow 업로드
Map<String, Object> result = pipelineUploadService.uploadPipeline(
file, name, displayName, decodedDescription, namespace);
WorkflowEntity workflow = WorkflowEntity.builder()
.pipelineId((String) result.get("pipeline_id"))
.displayName((String) result.get("display_name"))
.name((String) result.get("name"))
.description(decodedDescription) // 여기 디코딩 적용
.namespace((String) result.get("namespace"))
.regUserId(regUserId)
.projectId(projectId)
.kubeflowStatus("Created")
.version(1)
.build();
workFlowService.save(workflow);
// 2. MinIO 업로드
StorageAttachmentEntity attachment = minioAttachmentService.uploadFile(
file,
"workflows/" + projectId,
workflow.getId(),
"workflows",
displayName,
decodedDescription, // 디코딩 적용
1,
regUserId,
projectId
);
String minioUrl = minioAttachmentService.getFileUrl(attachment.getStoragePath());
// 3. 최종 응답
Map<String, Object> response = new HashMap<>();
response.put("pipeline", result);
response.put("workflow", workflow);
response.put("attachment", attachment);
response.put("minioUrl", minioUrl);
return ResponseEntity.ok(response);
} catch (Exception e) {
log.error("Pipeline + MinIO upload failed", e);
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(Map.of(
"status", 500,
"error", "Internal Server Error",
"message", e.getMessage()
));
}
}
@PostMapping("/runs")
@Operation(
summary = "Kubeflow Run 생성",
description = "Kubeflow에 Run을 생성합니다."
)
@ApiResponses({
@ApiResponse(responseCode = "200", description = "Run 생성 성공"),
@ApiResponse(responseCode = "400", description = "display_name 필수"),
@ApiResponse(responseCode = "500", description = "서버 오류")
})
public ResponseEntity<Map<String, Object>> createRun(
@RequestBody CreateRunRequest runRequest
) {
try {
Map<String, Object> result = pipelineUploadService.createRun(runRequest);
return ResponseEntity.ok(result);
} catch (IllegalArgumentException e) {
log.error("Invalid run request", e);
return ResponseEntity.status(HttpStatus.BAD_REQUEST)
.body(Map.of(
"status", 400,
"error", "Bad Request",
"message", e.getMessage()
));
} catch (Exception e) {
log.error("Run creation failed", e);
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(Map.of(
"status", 500,
"error", "Internal Server Error",
"message", e.getMessage()
));
}
}
}