Skip to content

Commit

Permalink
Merge pull request #68 from Team-Goraebab/develop
Browse files Browse the repository at this point in the history
Merge develop into main branch
whitem4rk authored Nov 6, 2024

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
2 parents b600101 + 463c2ed commit 627320d
Showing 16 changed files with 326 additions and 137 deletions.
Original file line number Diff line number Diff line change
@@ -3,6 +3,7 @@
import api.goraebab.domain.blueprint.dto.BlueprintReqDto;
import api.goraebab.domain.blueprint.dto.BlueprintResDto;
import api.goraebab.domain.blueprint.dto.BlueprintsResDto;
import api.goraebab.domain.blueprint.dto.SyncResultDto;
import api.goraebab.domain.blueprint.service.BlueprintServiceImpl;
import api.goraebab.global.exception.ErrorResponse;
import io.swagger.v3.oas.annotations.Operation;
@@ -171,11 +172,11 @@ public ResponseEntity<BlueprintResDto> getBlueprint(@RequestParam(required = fal
"{\"status\": \"CONTAINER_CREATION_FAILED\", \"code\": 500, \"message\": \"Failed to create the specified Docker container.\", \"errors\": []}"))
)
})
public ResponseEntity<Void> saveBlueprint(@RequestParam(required = false) @Schema(description = "The unique identifier of the storage. If null, the blueprint is considered to be in the local storage.") Long storageId,
public ResponseEntity<SyncResultDto> saveBlueprint(@RequestParam(required = false) @Schema(description = "The unique identifier of the storage. If null, the blueprint is considered to be in the local storage.") Long storageId,
@RequestBody @Valid BlueprintReqDto blueprintReqDto) {
blueprintService.saveBlueprint(storageId, blueprintReqDto);
SyncResultDto syncResultDto = blueprintService.saveBlueprint(storageId, blueprintReqDto);

return ResponseEntity.ok().build();
return ResponseEntity.ok(syncResultDto);
}

@Operation(summary = "Modify the blueprint",
@@ -214,12 +215,13 @@ public ResponseEntity<Void> saveBlueprint(@RequestParam(required = false) @Schem
"{\"status\": \"MODIFY_FAILED\", \"code\": 500, \"message\": \"Failed to modify blueprint.\", \"errors\": []}"))
)
})
public ResponseEntity<Void> modifyBlueprint(@RequestParam(required = false) @Schema(description = "The unique identifier of the storage. If null, the blueprint is considered to be in the local storage.") Long storageId,
public ResponseEntity<SyncResultDto> modifyBlueprint(@RequestParam(required = false) @Schema(description = "The unique identifier of the storage. If null, the blueprint is considered to be in the local storage.") Long storageId,
@PathVariable @Schema(description = "The unique identifier of the blueprint.") Long blueprintId,
@RequestBody @Valid BlueprintReqDto blueprintReqDto) {
blueprintService.modifyBlueprint(storageId, blueprintId, blueprintReqDto);
SyncResultDto syncResultDto = blueprintService.modifyBlueprint(storageId, blueprintId,
blueprintReqDto);

return ResponseEntity.ok().build();
return ResponseEntity.ok(syncResultDto);
}

@Operation(summary = "Delete the blueprint",
Original file line number Diff line number Diff line change
@@ -10,6 +10,8 @@
@NoArgsConstructor
public class CustomContainer {

private String containerId;

private String containerName;

@JsonProperty("image")
@@ -32,9 +34,10 @@ public class CustomContainer {


@Builder
public CustomContainer(String containerName, CustomImage customImage,
public CustomContainer(String containerId, String containerName, CustomImage customImage,
CustomNetworkSettings customNetworkSettings, List<CustomPort> customPorts,
List<CustomMount> customMounts, List<String> customEnv, List<String> customCmd) {
this.containerId = containerId;
this.containerName = containerName;
this.customImage = customImage;
this.customNetworkSettings = customNetworkSettings;
Original file line number Diff line number Diff line change
@@ -10,21 +10,25 @@
@NoArgsConstructor
public class CustomHost {

private String id;

@JsonProperty("network")
private List<CustomNetwork> customNetwork;

@JsonProperty("volume")
private List<CustomVolume> customVolume;

private Boolean isLocal;
private Boolean isRemote;

private String ip;

@Builder
public CustomHost(List<CustomNetwork> customNetwork, List<CustomVolume> customVolume, Boolean isLocal, String ip) {
public CustomHost(String id, List<CustomNetwork> customNetwork, List<CustomVolume> customVolume,
Boolean isRemote, String ip) {
this.id = id;
this.customNetwork = customNetwork;
this.customVolume = customVolume;
this.isLocal = isLocal;
this.isRemote = isRemote;
this.ip = ip;
}

Original file line number Diff line number Diff line change
@@ -10,6 +10,8 @@
@NoArgsConstructor
public class CustomNetwork {

private String id;

private String name;

private String driver;
@@ -22,7 +24,9 @@ public class CustomNetwork {


@Builder
public CustomNetwork(String name, String driver, CustomIpam customIpam, List<CustomContainer> customContainers) {
public CustomNetwork(String id, String name, String driver, CustomIpam customIpam,
List<CustomContainer> customContainers) {
this.id = id;
this.name = name;
this.driver = driver;
this.customIpam = customIpam;
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package api.goraebab.domain.blueprint.dto;

import api.goraebab.domain.blueprint.dockerObject.ProcessedData;
import api.goraebab.domain.remote.database.dto.StorageResDto;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
@@ -15,7 +15,7 @@ public class BlueprintResDto extends BlueprintsResDto {

private StorageResDto storageInfo;

public BlueprintResDto(Long blueprintId, String name, String data, Boolean isRemote, LocalDateTime dateCreated, LocalDateTime dateUpdated, StorageResDto storageInfo) {
public BlueprintResDto(Long blueprintId, String name, ProcessedData data, Boolean isRemote, LocalDateTime dateCreated, LocalDateTime dateUpdated, StorageResDto storageInfo) {
super(blueprintId, name, data, isRemote, dateCreated, dateUpdated);
this.storageInfo = storageInfo;
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package api.goraebab.domain.blueprint.dto;

import api.goraebab.domain.blueprint.dockerObject.CustomHost;
import api.goraebab.domain.blueprint.dockerObject.ProcessedData;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Getter;
@@ -21,7 +23,7 @@ public class BlueprintsResDto {
private String name;

@Schema(description = "The raw data associated with the blueprint.")
private String data;
private ProcessedData data;

@Schema(description = "The flag indicating whether the blueprint is stored remotely.", example = "true")
private Boolean isRemote;
24 changes: 24 additions & 0 deletions src/main/java/api/goraebab/domain/blueprint/dto/SyncResultDto.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package api.goraebab.domain.blueprint.dto;

import java.util.List;
import java.util.Map;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
@NoArgsConstructor
public class SyncResultDto {

private List<Map<String, Object>> failedContainers;

private List<Map<String, Object>> succeededContainers;


@Builder
public SyncResultDto(List<Map<String, Object>> failedContainers,
List<Map<String, Object>> succeededContainers) {
this.failedContainers = failedContainers;
this.succeededContainers = succeededContainers;
}
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
package api.goraebab.domain.blueprint.mapper;

import api.goraebab.domain.blueprint.dockerObject.ProcessedData;
import api.goraebab.domain.blueprint.dto.BlueprintResDto;
import api.goraebab.domain.blueprint.dto.BlueprintsResDto;
import api.goraebab.domain.blueprint.entity.Blueprint;
import api.goraebab.domain.remote.database.mapper.StorageMapper;
import api.goraebab.global.exception.CustomException;
import api.goraebab.global.exception.ErrorCode;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.IOException;
import java.util.List;
import org.mapstruct.IterableMapping;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.Named;
import org.mapstruct.factory.Mappers;

@Mapper(uses = {StorageMapper.class})
@@ -17,12 +23,24 @@ public interface BlueprintMapper {

@Mapping(source = "id", target = "blueprintId")
@Mapping(source = "storage", target = "storageInfo")
@Mapping(source = "data", target = "data", qualifiedByName = "stringToHost")
BlueprintResDto toBlueprintResDto(Blueprint blueprint);

@Mapping(source = "id", target = "blueprintId")
@Mapping(source = "data", target = "data", qualifiedByName = "stringToHost")
BlueprintsResDto toBlueprintsResDto(Blueprint blueprint);

@IterableMapping(elementTargetType = BlueprintsResDto.class)
List<BlueprintsResDto> toBlueprintsResDtoList(List<Blueprint> blueprints);

@Named("stringToHost")
default ProcessedData stringToHost(String data) {
try {
ObjectMapper objectMapper = new ObjectMapper();
return objectMapper.readValue(data, ProcessedData.class);
} catch (IOException e) {
throw new CustomException(ErrorCode.CONVERSION_FAILED);
}
}

}
Original file line number Diff line number Diff line change
@@ -4,6 +4,7 @@
import api.goraebab.domain.blueprint.dto.BlueprintResDto;
import api.goraebab.domain.blueprint.dto.BlueprintsResDto;

import api.goraebab.domain.blueprint.dto.SyncResultDto;
import java.util.List;

public interface BlueprintService {
@@ -12,9 +13,9 @@ public interface BlueprintService {

BlueprintResDto getBlueprintById(Long storageId, Long blueprintId);

void saveBlueprint(Long storageId, BlueprintReqDto blueprintReqDto);
SyncResultDto saveBlueprint(Long storageId, BlueprintReqDto blueprintReqDto);

void modifyBlueprint(Long storageId, Long blueprintId, BlueprintReqDto blueprintReqDto);
SyncResultDto modifyBlueprint(Long storageId, Long blueprintId, BlueprintReqDto blueprintReqDto);

void deleteBlueprint(Long storageId, Long blueprintId);

Original file line number Diff line number Diff line change
@@ -4,14 +4,18 @@
import api.goraebab.domain.blueprint.dto.BlueprintReqDto;
import api.goraebab.domain.blueprint.dto.BlueprintResDto;
import api.goraebab.domain.blueprint.dto.BlueprintsResDto;
import api.goraebab.domain.blueprint.dto.SyncResultDto;
import api.goraebab.domain.blueprint.entity.Blueprint;
import api.goraebab.domain.blueprint.mapper.BlueprintMapper;
import api.goraebab.domain.blueprint.repository.BlueprintRepository;
import api.goraebab.domain.remote.database.entity.Storage;
import api.goraebab.domain.remote.database.repository.StorageRepository;
import api.goraebab.global.exception.CustomException;
import api.goraebab.global.exception.ErrorCode;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.RequiredArgsConstructor;
@@ -26,6 +30,12 @@ public class BlueprintServiceImpl implements BlueprintService {
private final StorageRepository storageRepository;
private final DockerSyncServiceImpl dockerSyncService;
private final ObjectMapper objectMapper;
private static final String CONTAINER_SUCCESS = "success";
private static final String CONTAINER_FAILED = "failed";
private static final String FAIL_TO_CREATE_MESSAGE = "Failed to create some containers";
private static final String FAIL_TO_UPDATE_MESSAGE = "Failed to update some containers";
private static final String STATUS_KEY = "status";


@Override
@Transactional(readOnly = true)
@@ -64,53 +74,86 @@ public BlueprintResDto getBlueprintById(Long storageId, Long blueprintId) {

@Override
@Transactional
public void saveBlueprint(Long storageId, BlueprintReqDto blueprintReqDto) {
try {
Storage storage = null;
public SyncResultDto saveBlueprint(Long storageId, BlueprintReqDto blueprintReqDto) {
Storage storage = null;

if (storageId != null) {
storage = storageRepository.findById(storageId)
.orElseThrow(() -> new CustomException(ErrorCode.NOT_FOUND_VALUE));
}
if (storageId != null) {
storage = storageRepository.findById(storageId)
.orElseThrow(() -> new CustomException(ErrorCode.NOT_FOUND_VALUE));
}

String processedData = convertProcessedDataToJson(blueprintReqDto.getProcessedData());
String processedData = convertProcessedDataToJson(blueprintReqDto.getProcessedData());

Blueprint blueprint = Blueprint.builder()
.name(blueprintReqDto.getBlueprintName())
.data(processedData)
.isRemote(false)
.storage(storage)
.build();

blueprintRepository.save(blueprint);

List<Map<String, Object>> syncResults = dockerSyncService.syncDockerWithBlueprintData(blueprintReqDto.getProcessedData());

List<Map<String, Object>> failedContainers = syncResults.stream()
.filter(result -> CONTAINER_FAILED.equals(result.get(STATUS_KEY)))
.collect(Collectors.toList());

List<Map<String, Object>> succeededContainers = syncResults.stream()
.filter(result -> CONTAINER_SUCCESS.equals(result.get(STATUS_KEY)))
.collect(Collectors.toList());

if (!failedContainers.isEmpty()) {
throw new CustomException(ErrorCode.SAVE_FAILED, FAIL_TO_CREATE_MESSAGE,
failedContainers, succeededContainers);
} else {
return SyncResultDto.builder()
.failedContainers(failedContainers)
.succeededContainers(succeededContainers)
.build();
}

Blueprint blueprint = Blueprint.builder()
.name(blueprintReqDto.getBlueprintName())
.data(processedData)
.isRemote(false)
.storage(storage)
.build();

blueprintRepository.save(blueprint);
dockerSyncService.syncDockerWithBlueprintData(blueprintReqDto.getProcessedData());
} catch (Exception e) {
throw new CustomException(ErrorCode.SAVE_FAILED);
}
}

@Override
@Transactional
public void modifyBlueprint(Long storageId, Long blueprintId, BlueprintReqDto blueprintReqDto) {
try {
Blueprint blueprint;
public SyncResultDto modifyBlueprint(Long storageId, Long blueprintId, BlueprintReqDto blueprintReqDto) {
Blueprint blueprint;

if (storageId == null) {
blueprint = blueprintRepository.findById(blueprintId)
.orElseThrow(() -> new CustomException(ErrorCode.NOT_FOUND_VALUE));
} else {
blueprint = findBlueprintByStorageAndId(storageId, blueprintId);
}

String processedData = convertProcessedDataToJson(blueprintReqDto.getProcessedData());
blueprint.modify(blueprintReqDto.getBlueprintName(), processedData);

List<Map<String, Object>> syncResults = dockerSyncService.syncDockerWithBlueprintData(blueprintReqDto.getProcessedData());

List<Map<String, Object>> failedContainers = syncResults.stream()
.filter(result -> CONTAINER_FAILED.equals(result.get(STATUS_KEY)))
.collect(Collectors.toList());

List<Map<String, Object>> succeededContainers = syncResults.stream()
.filter(result -> CONTAINER_SUCCESS.equals(result.get(STATUS_KEY)))
.collect(Collectors.toList());

if (!failedContainers.isEmpty()) {
throw new CustomException(ErrorCode.MODIFY_FAILED,
FAIL_TO_UPDATE_MESSAGE, failedContainers, succeededContainers);
} else {
return SyncResultDto.builder()
.failedContainers(failedContainers)
.succeededContainers(succeededContainers)
.build();
}

if (storageId == null) {
blueprint = blueprintRepository.findById(blueprintId)
.orElseThrow(() -> new CustomException(ErrorCode.NOT_FOUND_VALUE));
} else {
blueprint = findBlueprintByStorageAndId(storageId, blueprintId);
}

String processedData = convertProcessedDataToJson(blueprintReqDto.getProcessedData());
blueprint.modify(blueprintReqDto.getBlueprintName(), processedData);

dockerSyncService.syncDockerWithBlueprintData(blueprintReqDto.getProcessedData());
} catch (Exception e) {
throw new CustomException(ErrorCode.MODIFY_FAILED);
}
}


@Override
@Transactional
public void deleteBlueprint(Long storageId, Long blueprintId) {
Loading

0 comments on commit 627320d

Please sign in to comment.