Skip to content

Commit 654e70b

Browse files
authored
Endpoint for cases S3 migration (#63)
Signed-off-by: Etienne Homer <etiennehomer@gmail.com>
1 parent 0b02f85 commit 654e70b

File tree

7 files changed

+88
-11
lines changed

7 files changed

+88
-11
lines changed

src/main/java/com/powsybl/caseserver/CaseController.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -164,8 +164,9 @@ public ResponseEntity<Boolean> exists(@PathVariable("caseUuid") UUID caseUuid) {
164164
public ResponseEntity<UUID> importCase(@RequestParam("file") MultipartFile file,
165165
@RequestParam(value = "withExpiration", required = false, defaultValue = "false") boolean withExpiration,
166166
@RequestParam(value = "withIndexation", required = false, defaultValue = "false") boolean withIndexation) {
167-
LOGGER.debug("importCase request received with file = {}", file.getName());
168-
UUID caseUuid = caseService.importCase(file, withExpiration, withIndexation);
167+
LOGGER.debug("importCase request received with file = {}", file.getOriginalFilename());
168+
UUID caseUuid = UUID.randomUUID();
169+
caseService.importCase(file, withExpiration, withIndexation, caseUuid);
169170
return ResponseEntity.ok().body(caseUuid);
170171
}
171172

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/**
2+
* Copyright (c) 2025, RTE (http://www.rte-france.com)
3+
* This Source Code Form is subject to the terms of the Mozilla Public
4+
* License, v. 2.0. If a copy of the MPL was not distributed with this
5+
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
6+
*/
7+
package com.powsybl.caseserver.migration;
8+
9+
import com.powsybl.caseserver.CaseConstants;
10+
import com.powsybl.caseserver.service.CaseService;
11+
import io.swagger.v3.oas.annotations.Operation;
12+
import io.swagger.v3.oas.annotations.tags.Tag;
13+
import org.slf4j.Logger;
14+
import org.slf4j.LoggerFactory;
15+
import org.springframework.beans.factory.annotation.Autowired;
16+
import org.springframework.beans.factory.annotation.Qualifier;
17+
import org.springframework.http.HttpStatus;
18+
import org.springframework.http.MediaType;
19+
import org.springframework.http.ResponseEntity;
20+
import org.springframework.web.bind.annotation.*;
21+
import org.springframework.web.multipart.MultipartFile;
22+
import org.springframework.web.server.ResponseStatusException;
23+
24+
import java.util.*;
25+
26+
/**
27+
* @author Etienne Homer <etienne.homer at rte-france.com>
28+
*/
29+
@RestController
30+
@RequestMapping(value = "/" + CaseConstants.API_VERSION + "/migration")
31+
@Tag(name = "Case migration")
32+
public class MigrationController {
33+
34+
private static final Logger LOGGER = LoggerFactory.getLogger(MigrationController.class);
35+
36+
@Autowired
37+
@Qualifier("storageService")
38+
private CaseService caseService;
39+
40+
@PostMapping(value = "/cases", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
41+
@Operation(summary = "import a case with given uuid")
42+
@SuppressWarnings("javasecurity:S5145")
43+
public ResponseEntity<UUID> importCase(@RequestParam("file") MultipartFile file,
44+
@RequestParam(value = "withExpiration", defaultValue = "false") boolean withExpiration,
45+
@RequestParam(value = "withIndexation", defaultValue = "false") boolean withIndexation,
46+
@RequestParam(value = "caseUuid") UUID caseUuid) {
47+
LOGGER.debug("importCase request received with file = {}", file.getOriginalFilename());
48+
if (caseService.caseExists(caseUuid)) {
49+
throw new ResponseStatusException(HttpStatus.CONFLICT, "Case with UUID " + caseUuid + " already exists");
50+
}
51+
caseService.importCase(file, withExpiration, withIndexation, caseUuid);
52+
return ResponseEntity.ok().build();
53+
}
54+
}

src/main/java/com/powsybl/caseserver/service/CaseService.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ default List<CaseInfos> getCasesToReindex() {
168168

169169
Optional<byte[]> getCaseBytes(UUID caseUuid);
170170

171-
UUID importCase(MultipartFile file, boolean withExpiration, boolean withIndexation);
171+
UUID importCase(MultipartFile file, boolean withExpiration, boolean withIndexation, UUID caseUuid);
172172

173173
UUID duplicateCase(UUID sourceCaseUuid, boolean withExpiration);
174174

src/main/java/com/powsybl/caseserver/service/FsCaseService.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -184,10 +184,9 @@ public boolean caseExists(UUID caseName) {
184184
}
185185

186186
@Override
187-
public UUID importCase(MultipartFile mpf, boolean withExpiration, boolean withIndexation) {
187+
public UUID importCase(MultipartFile mpf, boolean withExpiration, boolean withIndexation, UUID caseUuid) {
188188
checkStorageInitialization();
189189

190-
UUID caseUuid = UUID.randomUUID();
191190
Path uuidDirectory = getStorageRootDir().resolve(caseUuid.toString());
192191

193192
String caseName = Objects.requireNonNull(mpf.getOriginalFilename()).trim();

src/main/java/com/powsybl/caseserver/service/S3CaseService.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -336,9 +336,7 @@ public Set<String> listName(UUID caseUuid, String regex) {
336336
}
337337

338338
@Override
339-
public UUID importCase(MultipartFile mpf, boolean withExpiration, boolean withIndexation) {
340-
UUID caseUuid = UUID.randomUUID();
341-
339+
public UUID importCase(MultipartFile mpf, boolean withExpiration, boolean withIndexation, UUID caseUuid) {
342340
String caseName = Objects.requireNonNull(mpf.getOriginalFilename());
343341
validateCaseName(caseName);
344342

src/test/java/com/powsybl/caseserver/datasource/AbstractCaseDataSourceControllerTest.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,11 +73,11 @@ public abstract class AbstractCaseDataSourceControllerTest {
7373
protected DataSource iidmDataSource;
7474

7575
protected static UUID importCase(String filename, String contentType) throws IOException {
76-
UUID caseUUID;
76+
UUID caseUuid = UUID.randomUUID();
7777
try (InputStream inputStream = S3CaseDataSourceControllerTest.class.getResourceAsStream("/" + filename)) {
78-
caseUUID = caseService.importCase(new MockMultipartFile(filename, filename, contentType, inputStream.readAllBytes()), false, false);
78+
caseService.importCase(new MockMultipartFile(filename, filename, contentType, inputStream.readAllBytes()), false, false, caseUuid);
7979
}
80-
return caseUUID;
80+
return caseUuid;
8181
}
8282

8383
@Test

src/test/java/com/powsybl/caseserver/service/AbstractCaseControllerTest.java

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ abstract class AbstractCaseControllerTest {
6666
private static final String GET_CASE_FORMAT_URL = "/v1/cases/{caseName}/format";
6767

6868
private static final UUID RANDOM_UUID = UUID.fromString("3e2b6777-fea5-4e76-9b6b-b68f151373ab");
69+
private static final UUID CASE_UUID_TO_IMPORT = UUID.fromString("88601ab1-530e-47d2-8881-0dedecd6e6ee");
6970

7071
@Autowired
7172
protected MockMvc mvc;
@@ -805,4 +806,28 @@ public void testTar() throws Exception {
805806
assertEquals(TEST_TAR_CASE, headersCase.get(CaseInfos.NAME_HEADER_KEY));
806807
assertEquals("XIIDM", headersCase.get(CaseInfos.FORMAT_HEADER_KEY));
807808
}
809+
810+
@Test
811+
void testImportCaseWithUuid() throws Exception {
812+
createStorageDir();
813+
814+
// import a case
815+
mvc.perform(multipart("/v1/migration/cases")
816+
.file(createMockMultipartFile(TEST_CASE))
817+
.param("caseUuid", CASE_UUID_TO_IMPORT.toString()))
818+
.andExpect(status().isOk());
819+
820+
// retrieve case format
821+
mvc.perform(get(GET_CASE_FORMAT_URL, CASE_UUID_TO_IMPORT))
822+
.andExpect(status().isOk())
823+
.andExpect(content().string(TEST_CASE_FORMAT));
824+
825+
// import a case with existing UUID
826+
mvc.perform(multipart("/v1/migration/cases")
827+
.file(createMockMultipartFile(TEST_CASE))
828+
.param("caseUuid", CASE_UUID_TO_IMPORT.toString()))
829+
.andExpect(status().isConflict());
830+
831+
assertNotNull(outputDestination.receive(1000, caseImportDestination));
832+
}
808833
}

0 commit comments

Comments
 (0)