Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(sdk): kraken-29 - add new endpoint for quick start guide #62

Merged
merged 2 commits into from
Nov 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package com.consoleconnect.kraken.operator.controller.api;

import com.consoleconnect.kraken.operator.controller.dto.start.StartGuideInfoDto;
import com.consoleconnect.kraken.operator.controller.service.start.StartGuideService;
import com.consoleconnect.kraken.operator.core.model.HttpResponse;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping(value = StartGuideController.URL, produces = MediaType.APPLICATION_JSON_VALUE)
@RequiredArgsConstructor
@Tag(name = "Start Guide APIs", description = "Portal APIs")
public class StartGuideController {

public static final String URL = "/start/guide";
private final StartGuideService service;

@Operation(summary = "Get start guide info")
@GetMapping("/{productId}")
public HttpResponse<StartGuideInfoDto> getStartGuideInfo(
@PathVariable("productId") String productId, @RequestParam(value = "kind") String kind) {
return HttpResponse.ok(service.getStartGuideInfo(productId, kind));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.consoleconnect.kraken.operator.controller.dto.start;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class ApiMappingInfoDto {

private Boolean atLeastOneMappingCompleted;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.consoleconnect.kraken.operator.controller.dto.start;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class DeploymentInfoDto {
private Boolean atLeastOneApiDeployedToStage;
private Boolean atLeastOneBuyerRegistered;
private Boolean atLeastOneApiDeployedToProduction;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.consoleconnect.kraken.operator.controller.dto.start;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class SellerApiServerRegistrationInfoDto {

private Boolean atLeastOneSellerApiRegistered;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.consoleconnect.kraken.operator.controller.dto.start;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class StartGuideInfoDto {
private SellerApiServerRegistrationInfoDto sellerApiServerRegistrationInfo;
private ApiMappingInfoDto apiMappingInfo;
private DeploymentInfoDto deploymentInfo;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
package com.consoleconnect.kraken.operator.controller.service.start;

import static com.consoleconnect.kraken.operator.core.enums.AssetKindEnum.PRODUCT_BUYER;
import static com.consoleconnect.kraken.operator.core.enums.MappingStatusEnum.COMPLETE;
import static com.consoleconnect.kraken.operator.core.service.UnifiedAssetService.getSearchPageRequest;

import com.consoleconnect.kraken.operator.controller.dto.start.ApiMappingInfoDto;
import com.consoleconnect.kraken.operator.controller.dto.start.DeploymentInfoDto;
import com.consoleconnect.kraken.operator.controller.dto.start.SellerApiServerRegistrationInfoDto;
import com.consoleconnect.kraken.operator.controller.dto.start.StartGuideInfoDto;
import com.consoleconnect.kraken.operator.controller.model.Environment;
import com.consoleconnect.kraken.operator.controller.service.ApiComponentService;
import com.consoleconnect.kraken.operator.controller.service.EnvironmentService;
import com.consoleconnect.kraken.operator.controller.service.ProductDeploymentService;
import com.consoleconnect.kraken.operator.core.enums.DeployStatusEnum;
import com.consoleconnect.kraken.operator.core.enums.EnvNameEnum;
import com.consoleconnect.kraken.operator.core.exception.KrakenException;
import com.consoleconnect.kraken.operator.core.repo.UnifiedAssetRepository;
import com.consoleconnect.kraken.operator.core.service.UnifiedAssetService;
import java.util.Optional;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

@RequiredArgsConstructor
@Service
public class StartGuideService {

public static final int DEFAULT_NUMBER_OF_COMPLETED_MAPPINGS = 2;
public static final String PRODUCT_ID_CAN_NOT_BE_EMPTY_ERROR = "Product id can not be empty.";
public static final String KIND_CAN_NOT_BE_EMPTY_ERROR = "Kind can not be empty.";

private final ApiComponentService apiComponentService;
private final UnifiedAssetRepository unifiedAssetRepository;
private final UnifiedAssetService unifiedAssetService;
private final EnvironmentService environmentService;
private final ProductDeploymentService productDeploymentService;

public StartGuideInfoDto getStartGuideInfo(String productId, String kind) {
validateParams(productId, kind);
var atLeastOneSellerApiRegistered = atLeastOneSellerApiRegistered(productId, kind);
var atLeastOneMappingCompleted = atLeastOneMappingCompleted();
var atLestOnBuyerRegistered = atLestOnBuyerRegistered(productId);
var atLeastOneApiDeployedOnStage = atLeastOneApiDeployedToEvn(productId, EnvNameEnum.STAGE);
var atLeastOneApiDeployedOnProduction =
atLeastOneApiDeployedToEvn(productId, EnvNameEnum.PRODUCTION);

return new StartGuideInfoDto(
new SellerApiServerRegistrationInfoDto(atLeastOneSellerApiRegistered),
new ApiMappingInfoDto(atLeastOneMappingCompleted),
new DeploymentInfoDto(
atLeastOneApiDeployedOnStage,
atLestOnBuyerRegistered,
atLeastOneApiDeployedOnProduction));
}

private void validateParams(String productId, String kind) {
if (StringUtils.isBlank(productId)) {
throw new KrakenException(400, PRODUCT_ID_CAN_NOT_BE_EMPTY_ERROR);
}
if (StringUtils.isBlank(kind)) {
throw new KrakenException(400, KIND_CAN_NOT_BE_EMPTY_ERROR);
}
}

private boolean atLeastOneSellerApiRegistered(String productId, String kind) {
var parentId = unifiedAssetService.findOne(productId).getId();
return unifiedAssetRepository.existsByParentIdAndKind(parentId, kind);
}

private boolean atLeastOneMappingCompleted() {
var completedMappings =
apiComponentService.listAllApiUseCase().stream()
.flatMap(component -> component.getDetails().stream())
.filter(mapping -> mapping.getMappingStatus().equalsIgnoreCase(COMPLETE.getDesc()))
.toList();
return completedMappings.size() > DEFAULT_NUMBER_OF_COMPLETED_MAPPINGS;
}

private boolean atLestOnBuyerRegistered(String productId) {
var parentId = unifiedAssetService.findOneByIdOrKey(productId).getId().toString();
return unifiedAssetRepository.existsByParentIdAndKind(parentId, PRODUCT_BUYER.getKind());
}

private boolean atLeastOneApiDeployedToEvn(String productId, EnvNameEnum envNameEnum) {
var environments =
environmentService
.search(productId, getSearchPageRequest(0, EnvNameEnum.values().length))
.getData();
Optional<Environment> environment =
environments.stream()
.filter(e -> envNameEnum.name().equalsIgnoreCase(e.getName()))
.findFirst();
return environment
.map(
env -> {
var deployments =
productDeploymentService.retrieveApiMapperDeployments(
environment.get().getId(),
null,
DeployStatusEnum.SUCCESS,
getSearchPageRequest(0, 1));
return !deployments.getData().isEmpty();
})
.orElse(false);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package com.consoleconnect.kraken.operator.controller.api;

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.when;

import com.consoleconnect.kraken.operator.config.TestApplication;
import com.consoleconnect.kraken.operator.controller.WebTestClientHelper;
import com.consoleconnect.kraken.operator.controller.dto.start.ApiMappingInfoDto;
import com.consoleconnect.kraken.operator.controller.dto.start.DeploymentInfoDto;
import com.consoleconnect.kraken.operator.controller.dto.start.SellerApiServerRegistrationInfoDto;
import com.consoleconnect.kraken.operator.controller.dto.start.StartGuideInfoDto;
import com.consoleconnect.kraken.operator.controller.service.start.StartGuideService;
import com.consoleconnect.kraken.operator.core.model.HttpResponse;
import com.consoleconnect.kraken.operator.test.AbstractIntegrationTest;
import com.consoleconnect.kraken.operator.test.MockIntegrationTest;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.SneakyThrows;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.web.reactive.server.WebTestClient;

@ActiveProfiles("test-auth-server-enabled")
@MockIntegrationTest
@ContextConfiguration(classes = TestApplication.class)
class StartGuideControllerTest extends AbstractIntegrationTest {

@Autowired protected ObjectMapper objectMapper;

@MockBean private StartGuideService service;

private final WebTestClientHelper testClientHelper;

@Autowired
StartGuideControllerTest(WebTestClient webTestClient) {
testClientHelper = new WebTestClientHelper(webTestClient);
}

@SneakyThrows
@Test
void givenStartingGuideInfo_whenGettingStartGuideInfo_thenReturnsOk() {
// given
var kind = "kind1";
var productId = "productId1";
var guideInfoDto =
new StartGuideInfoDto(
new SellerApiServerRegistrationInfoDto(true),
new ApiMappingInfoDto(true),
new DeploymentInfoDto(true, true, false));
when(service.getStartGuideInfo(productId, kind)).thenReturn(guideInfoDto);
// when
var path = StartGuideController.URL + "/" + productId;
testClientHelper.getAndVerify(
(uriBuilder -> uriBuilder.path(path).queryParam("kind", kind).build()),
bodyStr -> {
// then
var result = content(bodyStr, new TypeReference<HttpResponse<StartGuideInfoDto>>() {});
assertThat(result.getData()).isEqualTo(guideInfoDto);
});
}

@SneakyThrows
private <T> T content(String response, TypeReference<T> typeReference) {
return objectMapper.readValue(response, typeReference);
}
}
Loading
Loading