Skip to content

Commit

Permalink
refactor: introduction of CreateV4ApiUseCase (#6827)
Browse files Browse the repository at this point in the history
Follow the work initiated in #6659

It introduces a new use case used by mAPI v2 when creating a new V4 API.
The ImportCRDUseCase and the Cockpit handler creating V4 API have also been
updated to use the new Domain Service introduced earlier.

All of this work allows us to remove the create method we have in ApiService 🎉

https://gravitee.atlassian.net/browse/APIM-3959
  • Loading branch information
jgiovaresco authored and jourdiw committed Mar 11, 2024
1 parent a57f30f commit e3ac624
Show file tree
Hide file tree
Showing 33 changed files with 1,892 additions and 1,315 deletions.
Expand Up @@ -18,6 +18,8 @@
import com.fasterxml.jackson.annotation.JsonProperty;
import java.io.Serializable;
import java.util.Map;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.NoArgsConstructor;
Expand All @@ -28,6 +30,8 @@
* @author David BRASSELY (david.brassely at graviteesource.com)
* @author GraviteeSource Team
*/
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Getter
@Setter
Expand Down
Expand Up @@ -99,6 +99,7 @@ public class Api implements Serializable {
@NotNull
private Map<@NotEmpty String, @NotNull Plan> plans;

@Builder.Default
private FlowExecution flowExecution = new FlowExecution();

private List<Flow> flows;
Expand Down
Expand Up @@ -17,6 +17,7 @@

import static java.util.stream.Collectors.toMap;

import io.gravitee.apim.core.api.model.NewApi;
import io.gravitee.apim.core.api.model.crd.ApiCRD;
import io.gravitee.rest.api.management.v2.rest.model.Api;
import io.gravitee.rest.api.management.v2.rest.model.ApiLinks;
Expand All @@ -34,7 +35,6 @@
import io.gravitee.rest.api.model.ReviewEntity;
import io.gravitee.rest.api.model.v4.api.ApiEntity;
import io.gravitee.rest.api.model.v4.api.GenericApiEntity;
import io.gravitee.rest.api.model.v4.api.NewApiEntity;
import io.gravitee.rest.api.model.v4.api.UpdateApiEntity;
import jakarta.ws.rs.core.UriInfo;
import java.util.ArrayList;
Expand Down Expand Up @@ -72,6 +72,19 @@ public interface ApiMapper {
ApiMapper INSTANCE = Mappers.getMapper(ApiMapper.class);

// Api
default Api map(io.gravitee.apim.core.api.model.Api api, UriInfo uriInfo, Boolean isSynchronized) {
GenericApi.DeploymentStateEnum state = null;

if (isSynchronized != null) {
state = isSynchronized ? GenericApi.DeploymentStateEnum.DEPLOYED : GenericApi.DeploymentStateEnum.NEED_REDEPLOY;
}

if (api != null && api.getDefinitionVersion() == io.gravitee.definition.model.DefinitionVersion.V4) {
return new io.gravitee.rest.api.management.v2.rest.model.Api(this.mapToV4(api, uriInfo, state));
}
return null;
}

default Api map(GenericApiEntity apiEntity, UriInfo uriInfo, Boolean isSynchronized) {
GenericApi.DeploymentStateEnum state = null;

Expand Down Expand Up @@ -116,6 +129,18 @@ default List<Api> map(List<GenericApiEntity> apiEntities, UriInfo uriInfo, Funct
@Mapping(target = "links", expression = "java(computeApiLinks(apiEntity, uriInfo))")
ApiV4 mapToV4(ApiEntity apiEntity, UriInfo uriInfo, GenericApi.DeploymentStateEnum deploymentState);

@Mapping(target = "apiVersion", source = "source.version")
@Mapping(target = "analytics", source = "source.apiDefinitionV4.analytics")
@Mapping(target = "deploymentState", source = "deploymentState")
@Mapping(target = "endpointGroups", source = "source.apiDefinitionV4.endpointGroups")
@Mapping(target = "flowExecution", source = "source.apiDefinitionV4.flowExecution")
@Mapping(target = "flows", source = "source.apiDefinitionV4.flows")
@Mapping(target = "lifecycleState", source = "source.apiLifecycleState")
@Mapping(target = "links", expression = "java(computeCoreApiLinks(source, uriInfo))")
@Mapping(target = "listeners", source = "source.apiDefinitionV4.listeners", qualifiedByName = "fromListeners")
@Mapping(target = "state", source = "source.lifecycleState")
ApiV4 mapToV4(io.gravitee.apim.core.api.model.Api source, UriInfo uriInfo, GenericApi.DeploymentStateEnum deploymentState);

@Mapping(target = "links", expression = "java(computeApiLinks(apiEntity, uriInfo))")
ApiV2 mapToV2(io.gravitee.rest.api.model.api.ApiEntity apiEntity, UriInfo uriInfo, GenericApi.DeploymentStateEnum deploymentState);

Expand All @@ -134,7 +159,7 @@ io.gravitee.rest.api.management.v2.rest.model.ApiV1 mapToV1(
ApiEntity map(ApiV4 api);

@Mapping(target = "listeners", qualifiedByName = "toListeners")
NewApiEntity map(CreateApiV4 api);
NewApi map(CreateApiV4 api);

@Mapping(target = "listeners", qualifiedByName = "toListeners")
@Mapping(target = "plans", qualifiedByName = "mapPlanCRD")
Expand Down Expand Up @@ -167,6 +192,13 @@ default ApiLinks computeApiLinks(GenericApiEntity api, UriInfo uriInfo) {
.backgroundUrl(ManagementApiLinkHelper.apiBackgroundURL(uriInfo.getBaseUriBuilder(), api));
}

@Named("computeCoreApiLinks")
default ApiLinks computeCoreApiLinks(io.gravitee.apim.core.api.model.Api api, UriInfo uriInfo) {
return new ApiLinks()
.pictureUrl(ManagementApiLinkHelper.apiPictureURL(uriInfo.getBaseUriBuilder(), api))
.backgroundUrl(ManagementApiLinkHelper.apiBackgroundURL(uriInfo.getBaseUriBuilder(), api));
}

@Named("mapPlanCRD")
default Map<String, io.gravitee.apim.core.api.model.crd.PlanCRD> mapPlanCRD(Map<String, PlanCRD> plans) {
return plans
Expand Down
Expand Up @@ -19,7 +19,9 @@
import static io.gravitee.rest.api.service.impl.search.lucene.transformer.ApiDocumentTransformer.FIELD_TYPE_VALUE;

import com.google.common.base.Strings;
import io.gravitee.apim.core.api.domain_service.ApiStateDomainService;
import io.gravitee.apim.core.api.exception.InvalidPathsException;
import io.gravitee.apim.core.api.use_case.CreateV4ApiUseCase;
import io.gravitee.apim.core.api.use_case.ImportCRDUseCase;
import io.gravitee.apim.core.api.use_case.VerifyApiHostsUseCase;
import io.gravitee.apim.core.api.use_case.VerifyApiPathsUseCase;
Expand Down Expand Up @@ -110,6 +112,12 @@ public ApiResource getApiResource() {
return resourceContext.getResource(ApiResource.class);
}

@Inject
private ApiStateDomainService apiStateDomainService;

@Inject
private CreateV4ApiUseCase createV4ApiUseCase;

@Inject
private ImportCRDUseCase importCRDUseCase;

Expand All @@ -119,13 +127,28 @@ public ApiResource getApiResource() {
@Permissions({ @Permission(value = RolePermission.ENVIRONMENT_API, acls = { RolePermissionAction.CREATE }) })
public Response createApi(@Valid @NotNull final CreateApiV4 api) {
// NOTE: Only for V4 API. V2 API is planned to be supported in the future.
NewApiEntity newApiEntity = ApiMapper.INSTANCE.map(api);
ApiEntity newApi = apiServiceV4.create(GraviteeContext.getExecutionContext(), newApiEntity, getAuthenticatedUser());
var executionContext = GraviteeContext.getExecutionContext();
var userDetails = getAuthenticatedUserDetails();

AuditInfo audit = AuditInfo
.builder()
.organizationId(executionContext.getOrganizationId())
.environmentId(executionContext.getEnvironmentId())
.actor(
AuditActor
.builder()
.userId(userDetails.getUsername())
.userSource(userDetails.getSource())
.userSourceId(userDetails.getSourceId())
.build()
)
.build();
var output = createV4ApiUseCase.execute(new CreateV4ApiUseCase.Input(ApiMapper.INSTANCE.map(api), audit));

boolean isSynchronized = apiStateService.isSynchronized(GraviteeContext.getExecutionContext(), newApi);
boolean isSynchronized = apiStateDomainService.isSynchronized(output.api(), audit);
return Response
.created(this.getLocationHeader(newApi.getId()))
.entity(ApiMapper.INSTANCE.map(newApi, uriInfo, isSynchronized))
.created(this.getLocationHeader(output.api().getId()))
.entity(ApiMapper.INSTANCE.map(output.api(), uriInfo, isSynchronized))
.build();
}

Expand Down
Expand Up @@ -15,6 +15,7 @@
*/
package io.gravitee.rest.api.management.v2.rest.utils;

import io.gravitee.apim.core.api.model.Api;
import io.gravitee.rest.api.model.v4.api.GenericApiEntity;
import io.gravitee.rest.api.service.common.GraviteeContext;
import jakarta.ws.rs.core.UriBuilder;
Expand Down Expand Up @@ -45,6 +46,28 @@ public static String apiBackgroundURL(UriBuilder baseUriBuilder, GenericApiEntit
);
}

public static String apiPictureURL(UriBuilder baseUriBuilder, Api api) {
return resourcesURL(
baseUriBuilder,
api.getId(),
"apis",
null,
"picture",
null != api.getUpdatedAt() ? api.getUpdatedAt().toInstant().toEpochMilli() : null
);
}

public static String apiBackgroundURL(UriBuilder baseUriBuilder, Api api) {
return resourcesURL(
baseUriBuilder,
api.getId(),
"apis",
null,
"background",
null != api.getUpdatedAt() ? api.getUpdatedAt().toInstant().toEpochMilli() : null
);
}

private static String resourcesURL(
UriBuilder baseUriBuilder,
String resourceId,
Expand Down

0 comments on commit e3ac624

Please sign in to comment.