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.
96 lines
4.2 KiB
96 lines
4.2 KiB
|
9 months ago
|
package kr.re.etri.autoflow.controllers;
|
||
|
|
|
||
|
|
import io.swagger.v3.oas.annotations.Operation;
|
||
|
|
import io.swagger.v3.oas.annotations.Parameter;
|
||
|
|
import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
||
|
|
import io.swagger.v3.oas.annotations.responses.ApiResponses;
|
||
|
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||
|
|
import jakarta.transaction.Transactional;
|
||
|
|
import kr.re.etri.autoflow.entity.ExperimentsEntity;
|
||
|
|
import kr.re.etri.autoflow.payload.request.ProjectBaseSearchRequest;
|
||
|
|
import kr.re.etri.autoflow.service.ExperimentsService;
|
||
|
|
import lombok.RequiredArgsConstructor;
|
||
|
|
import lombok.extern.slf4j.Slf4j;
|
||
|
|
import org.springdoc.core.annotations.ParameterObject;
|
||
|
|
import org.springframework.beans.factory.annotation.Value;
|
||
|
|
import org.springframework.data.domain.Page;
|
||
|
|
import org.springframework.http.MediaType;
|
||
|
|
import org.springframework.http.ResponseEntity;
|
||
|
|
import org.springframework.web.bind.annotation.*;
|
||
|
|
import org.springframework.web.reactive.function.client.WebClient;
|
||
|
|
import reactor.core.publisher.Mono;
|
||
|
|
|
||
|
|
import java.net.URLEncoder;
|
||
|
|
import java.nio.charset.StandardCharsets;
|
||
|
|
import java.time.Instant;
|
||
|
|
import java.time.OffsetDateTime;
|
||
|
|
import java.time.ZoneId;
|
||
|
|
import java.time.ZoneOffset;
|
||
|
|
import java.time.format.DateTimeFormatter;
|
||
|
|
import java.util.HashMap;
|
||
|
|
import java.util.List;
|
||
|
|
import java.util.Map;
|
||
|
|
|
||
|
|
@Tag(name = "Experiments", description = "Kubeflow 및 MLflow Experiment API")
|
||
|
|
@RestController
|
||
|
|
@RequestMapping("/api/experiments")
|
||
|
|
@RequiredArgsConstructor
|
||
|
|
@Slf4j
|
||
|
|
public class KubeflowRunsController {
|
||
|
|
private final WebClient.Builder webClientBuilder;
|
||
|
|
@Value("${kubeflow.url}")
|
||
|
|
private String kubeflowBaseUrl; // 예: http://192.168.10.135:32473/
|
||
|
|
|
||
|
|
@Operation(summary = "Kubeflow Run 목록 조회", description = "Kubeflow API를 호출하여 Run 목록을 조회합니다.")
|
||
|
|
@ApiResponses({
|
||
|
|
@ApiResponse(responseCode = "200", description = "Run 목록 조회 성공"),
|
||
|
|
@ApiResponse(responseCode = "400", description = "잘못된 요청"),
|
||
|
|
@ApiResponse(responseCode = "500", description = "서버 내부 오류")
|
||
|
|
})
|
||
|
|
@GetMapping("/runs")
|
||
|
|
public Mono<ResponseEntity<Map>> listRuns(
|
||
|
|
@Parameter(description = "페이지 토큰 (다음 페이지 조회 시 사용)", example = "")
|
||
|
|
@RequestParam(value = "page_token", defaultValue = "") String pageToken,
|
||
|
|
|
||
|
|
@Parameter(description = "페이지 크기", example = "10")
|
||
|
|
@RequestParam(value = "page_size", defaultValue = "10") int pageSize,
|
||
|
|
|
||
|
|
@Parameter(description = "정렬 기준 (sort_by)", example = "created_at desc")
|
||
|
|
@RequestParam(value = "sort_by", defaultValue = "created_at desc") String sortBy,
|
||
|
|
|
||
|
|
@Parameter(description = "필터 JSON 문자열 (URL 인코딩 필요)", example = "{\"predicates\":[{\"key\":\"storage_state\",\"operation\":\"NOT_EQUALS\",\"string_value\":\"ARCHIVED\"}]}")
|
||
|
|
@RequestParam(value = "filter", required = false) String filter
|
||
|
|
) {
|
||
|
|
try {
|
||
|
|
// filter가 없으면 기본값 적용
|
||
|
|
if (filter == null || filter.isBlank()) {
|
||
|
|
filter = "{\"predicates\":[{\"key\":\"storage_state\",\"operation\":\"NOT_EQUALS\",\"string_value\":\"ARCHIVED\"}]}";
|
||
|
|
}
|
||
|
|
|
||
|
|
String encodedFilter = URLEncoder.encode(filter, StandardCharsets.UTF_8);
|
||
|
|
|
||
|
|
String uri = String.format(
|
||
|
|
"%s/apis/v2beta1/runs?page_token=%s&page_size=%d&sort_by=%s&filter=%s",
|
||
|
|
kubeflowBaseUrl, pageToken, pageSize, URLEncoder.encode(sortBy, StandardCharsets.UTF_8), encodedFilter
|
||
|
|
);
|
||
|
|
|
||
|
|
return webClientBuilder.build()
|
||
|
|
.get()
|
||
|
|
.uri(uri)
|
||
|
|
.accept(MediaType.APPLICATION_JSON)
|
||
|
|
.retrieve()
|
||
|
|
.bodyToMono(Map.class)
|
||
|
|
.map(ResponseEntity::ok)
|
||
|
|
.doOnError(e -> log.error("Kubeflow Runs 조회 실패", e));
|
||
|
|
|
||
|
|
} catch (Exception e) {
|
||
|
|
log.error("URI 생성 실패", e);
|
||
|
|
return Mono.just(ResponseEntity.status(500).body(Map.of(
|
||
|
|
"status", 500,
|
||
|
|
"error", "Internal Server Error",
|
||
|
|
"message", e.getMessage()
|
||
|
|
)));
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|