Skip to content

Commit

Permalink
feat(service): create native api entity + add to mappers
Browse files Browse the repository at this point in the history
  • Loading branch information
jourdiw committed Nov 8, 2024
1 parent 93f2907 commit d967607
Show file tree
Hide file tree
Showing 15 changed files with 697 additions and 20 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
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.UpdateApiEntity;
import io.gravitee.rest.api.model.v4.nativeapi.NativeApiEntity;
import jakarta.ws.rs.core.UriInfo;
import java.util.ArrayList;
import java.util.List;
Expand Down Expand Up @@ -117,7 +118,11 @@ default Api map(GenericApiEntity apiEntity, UriInfo uriInfo, Boolean isSynchroni
return new io.gravitee.rest.api.management.v2.rest.model.Api(this.mapToFederated((FederatedApiEntity) apiEntity, uriInfo));
}
if (apiEntity.getDefinitionVersion() == io.gravitee.definition.model.DefinitionVersion.V4) {
return new io.gravitee.rest.api.management.v2.rest.model.Api(this.mapToV4((ApiEntity) apiEntity, uriInfo, state));
if (apiEntity instanceof ApiEntity asApiEntity) {
return new io.gravitee.rest.api.management.v2.rest.model.Api(this.mapToV4(asApiEntity, uriInfo, state));
} else if (apiEntity instanceof NativeApiEntity asNativeApiEntity) {
return new io.gravitee.rest.api.management.v2.rest.model.Api(this.mapToV4(asNativeApiEntity, uriInfo, state));
}
}
if (apiEntity.getDefinitionVersion() == io.gravitee.definition.model.DefinitionVersion.V2) {
return new io.gravitee.rest.api.management.v2.rest.model.Api(
Expand Down Expand Up @@ -155,6 +160,11 @@ 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 = "definitionContext", source = "apiEntity.originContext")
@Mapping(target = "listeners", qualifiedByName = "fromNativeListeners")
@Mapping(target = "links", expression = "java(computeApiLinks(apiEntity, uriInfo))")
ApiV4 mapToV4(NativeApiEntity apiEntity, UriInfo uriInfo, GenericApi.DeploymentStateEnum deploymentState);

default ApiV4 mapToV4(io.gravitee.apim.core.api.model.Api source, UriInfo uriInfo, GenericApi.DeploymentStateEnum deploymentState) {
if (ApiType.NATIVE.equals(source.getType())) {
return mapToNativeV4(source, uriInfo, deploymentState);
Expand Down Expand Up @@ -199,7 +209,11 @@ io.gravitee.rest.api.management.v2.rest.model.ApiV1 mapToV1(

@Mapping(target = "listeners", qualifiedByName = "fromHttpListeners")
@Mapping(target = "links", ignore = true)
ApiV4 map(ApiEntity apiEntity);
ApiV4 mapFromHttpApiEntity(ApiEntity apiEntity);

@Mapping(target = "listeners", qualifiedByName = "fromNativeListeners")
@Mapping(target = "links", ignore = true)
ApiV4 mapFromNativeApiEntity(NativeApiEntity apiEntity);

@Mapping(target = "listeners", qualifiedByName = "toHttpListeners")
ApiEntity map(ApiV4 api);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@
import io.gravitee.rest.api.model.v4.api.ExportApiEntity;
import io.gravitee.rest.api.model.v4.api.GenericApiEntity;
import io.gravitee.rest.api.model.v4.api.UpdateApiEntity;
import io.gravitee.rest.api.model.v4.nativeapi.NativeApiEntity;
import io.gravitee.rest.api.rest.annotation.Permission;
import io.gravitee.rest.api.rest.annotation.Permissions;
import io.gravitee.rest.api.security.utils.ImageUtils;
Expand Down Expand Up @@ -851,11 +852,17 @@ private void setPicturesUrl(final GenericApiEntity apiEntity) {
String backgroundUrl = uriBuilder.build().toString();

if (apiEntity.getDefinitionVersion() == DefinitionVersion.V4) {
ApiEntity apiEntityV4 = (ApiEntity) apiEntity;
apiEntityV4.setPictureUrl(pictureUrl);
apiEntityV4.setPicture(null);
apiEntityV4.setBackgroundUrl(backgroundUrl);
apiEntityV4.setBackground(null);
if (apiEntity instanceof ApiEntity apiEntityV4) {
apiEntityV4.setPictureUrl(pictureUrl);
apiEntityV4.setPicture(null);
apiEntityV4.setBackgroundUrl(backgroundUrl);
apiEntityV4.setBackground(null);
} else if (apiEntity instanceof NativeApiEntity nativeApiEntityV4) {
nativeApiEntityV4.setPictureUrl(pictureUrl);
nativeApiEntityV4.setPicture(null);
nativeApiEntityV4.setBackgroundUrl(backgroundUrl);
nativeApiEntityV4.setBackground(null);
}
}
if (apiEntity.getDefinitionVersion() == DefinitionVersion.V2) {
io.gravitee.rest.api.model.api.ApiEntity apiEntityV2 = (io.gravitee.rest.api.model.api.ApiEntity) apiEntity;
Expand All @@ -868,7 +875,11 @@ private void setPicturesUrl(final GenericApiEntity apiEntity) {

private void filterSensitiveData(GenericApiEntity apiEntity) {
if (apiEntity.getDefinitionVersion() == DefinitionVersion.V4) {
filterSensitiveData((ApiEntity) apiEntity);
if (apiEntity instanceof ApiEntity asApiEntity) {
filterSensitiveData(asApiEntity);
} else if (apiEntity instanceof NativeApiEntity asNativeApiEntity) {
filterSensitiveData(asNativeApiEntity);
}
}
if (apiEntity.getDefinitionVersion() == DefinitionVersion.V2) {
filterSensitiveData((io.gravitee.rest.api.model.api.ApiEntity) apiEntity);
Expand Down Expand Up @@ -897,6 +908,12 @@ private void filterSensitiveData(ApiEntity apiEntity) {
apiEntity.setResponseTemplates(null);
}

private void filterSensitiveData(NativeApiEntity apiEntity) {
apiEntity.setProperties(null);
apiEntity.setServices(null);
apiEntity.setResources(null);
}

private void filterSensitiveData(io.gravitee.rest.api.model.api.ApiEntity apiEntity) {
final Proxy filteredProxy = new Proxy();
final VirtualHost virtualHost = apiEntity.getProxy().getVirtualHosts().get(0);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
import io.gravitee.definition.model.services.dynamicproperty.DynamicPropertyService;
import io.gravitee.definition.model.services.dynamicproperty.http.HttpDynamicPropertyProviderConfiguration;
import io.gravitee.definition.model.services.healthcheck.HealthCheckService;
import io.gravitee.definition.model.v4.ApiType;
import io.gravitee.definition.model.v4.analytics.Analytics;
import io.gravitee.definition.model.v4.endpointgroup.Endpoint;
import io.gravitee.definition.model.v4.endpointgroup.EndpointGroup;
Expand All @@ -56,6 +57,12 @@
import io.gravitee.definition.model.v4.listener.http.Path;
import io.gravitee.definition.model.v4.listener.subscription.SubscriptionListener;
import io.gravitee.definition.model.v4.listener.tcp.TcpListener;
import io.gravitee.definition.model.v4.nativeapi.NativeApiServices;
import io.gravitee.definition.model.v4.nativeapi.NativeEndpoint;
import io.gravitee.definition.model.v4.nativeapi.NativeEndpointGroup;
import io.gravitee.definition.model.v4.nativeapi.NativeEntrypoint;
import io.gravitee.definition.model.v4.nativeapi.NativeFlow;
import io.gravitee.definition.model.v4.nativeapi.kafka.KafkaListener;
import io.gravitee.definition.model.v4.property.Property;
import io.gravitee.definition.model.v4.resource.Resource;
import io.gravitee.definition.model.v4.service.ApiServices;
Expand All @@ -68,6 +75,7 @@
import io.gravitee.rest.api.model.permissions.RolePermission;
import io.gravitee.rest.api.model.permissions.RolePermissionAction;
import io.gravitee.rest.api.model.v4.api.ApiEntity;
import io.gravitee.rest.api.model.v4.nativeapi.NativeApiEntity;
import io.gravitee.rest.api.service.common.GraviteeContext;
import io.gravitee.rest.api.service.exceptions.ApiNotFoundException;
import jakarta.ws.rs.core.Response;
Expand Down Expand Up @@ -266,6 +274,138 @@ public void should_get_filtered_api_V4() {
assertNull((responseApi.getListeners().get(0).getHttpListener()).getPaths().get(0).getHost());
}

@Test
public void should_get_native_api_V4() throws JsonProcessingException {
when(apiSearchServiceV4.findGenericById(GraviteeContext.getExecutionContext(), API)).thenReturn(this.fakeNativeApiEntityV4());

when(apiStateServiceV4.isSynchronized(eq(GraviteeContext.getExecutionContext()), any())).thenReturn(false);

final Response response = rootTarget(API).request().get();

assertEquals(OK_200, response.getStatus());

final ApiV4 responseApi = response.readEntity(ApiV4.class);

assertNotNull(responseApi);
assertEquals(API, responseApi.getName());
assertEquals(GenericApi.DeploymentStateEnum.NEED_REDEPLOY, responseApi.getDeploymentState());
assertNotNull(responseApi.getLinks());
assertNotNull(responseApi.getLinks().getPictureUrl());
assertTrue(responseApi.getLinks().getPictureUrl().contains("environments/my-env/apis/my-api/picture"));
assertNotNull(responseApi.getLinks().getBackgroundUrl());
assertTrue(responseApi.getLinks().getBackgroundUrl().contains("environments/my-env/apis/my-api/background"));
assertNotNull(responseApi.getProperties());
assertEquals(1, responseApi.getProperties().size());
assertNotNull(responseApi.getServices());
assertNotNull(responseApi.getResources());
assertEquals(1, responseApi.getResources().size());
assertEquals(0, responseApi.getResponseTemplates().size());

assertNotNull(responseApi.getListeners());
assertEquals(1, responseApi.getListeners().size());

var kafkaListener = responseApi.getListeners().get(0).getKafkaListener();
assertNotNull(kafkaListener);
assertNotNull(kafkaListener.getHost());
assertNotNull(kafkaListener.getPort());
var foundEntrypoint = kafkaListener.getEntrypoints().get(0);
assertNotNull(foundEntrypoint);
LinkedHashMap configuration = (LinkedHashMap) foundEntrypoint.getConfiguration();
assertEquals("configuration", configuration.get("nice"));
assertEquals("native-kafka", foundEntrypoint.getType());
assertEquals("KAFKA", kafkaListener.getType().toString());

assertNotNull(responseApi.getEndpointGroups());
assertEquals(1, responseApi.getEndpointGroups().size());
assertNotNull(responseApi.getEndpointGroups().get(0));
EndpointGroupV4 endpointGroup = responseApi.getEndpointGroups().get(0);
LinkedHashMap sharedConfig = (LinkedHashMap) endpointGroup.getSharedConfiguration();
assertNotNull(sharedConfig);
assertEquals("configuration", sharedConfig.get("shared"));
assertNotNull(responseApi.getEndpointGroups().get(0).getEndpoints());
assertEquals(1, responseApi.getEndpointGroups().get(0).getEndpoints().size());

var endpoint = responseApi.getEndpointGroups().get(0).getEndpoints().get(0);
assertNotNull(endpoint);
assertEquals("native-kafka", endpoint.getType());

JsonNode jsonNode = mapper.valueToTree((LinkedHashMap) endpoint.getConfiguration());
assertEquals("kafka:9092", jsonNode.get("bootstrapServers").asText());
assertEquals(List.of("demo"), mapper.readValue(jsonNode.get("topics").toString(), List.class));

assertNotNull(responseApi.getFlows());
assertEquals(1, responseApi.getFlows().size());

var flow = responseApi.getFlows().get(0);
assertNotNull(flow);
assertEquals("flowName", flow.getName());
assertEquals(Boolean.TRUE, flow.getEnabled());
assertNotNull(flow.getTags());
assertEquals(2, flow.getTags().size());
assertEquals(Set.of("tag1", "tag2"), flow.getTags());
assertNotNull(flow.getConnect());
assertNotNull(flow.getInteract());
assertNotNull(flow.getPublish());
assertNotNull(flow.getSubscribe());

assertNull(flow.getRequest());
assertNull(flow.getResponse());
assertNull(flow.getSelectors());

assertEquals(1, flow.getConnect().size());

var step = flow.getConnect().get(0);
assertNotNull(step);
assertEquals(Boolean.TRUE, step.getEnabled());
assertEquals("my-policy", step.getPolicy());
assertEquals("my-condition", step.getCondition());

var service = responseApi.getServices();
assertNotNull(service);
assertNotNull(service.getDynamicProperty());
assertNotNull(service.getDynamicProperty().getConfiguration());

ServiceV4 dynamicPropertyConfiguration = service.getDynamicProperty();
assertNotNull(dynamicPropertyConfiguration);
assertEquals(true, dynamicPropertyConfiguration.getEnabled());
assertEquals(true, dynamicPropertyConfiguration.getOverrideConfiguration());
assertNotNull(dynamicPropertyConfiguration.getConfiguration());
assertEquals("dynamic-property", dynamicPropertyConfiguration.getType());
}

@Test
public void should_get_filtered_native_api_V4() {
when(apiSearchServiceV4.findGenericById(GraviteeContext.getExecutionContext(), API)).thenReturn(this.fakeNativeApiEntityV4());
when(
permissionService.hasPermission(
GraviteeContext.getExecutionContext(),
RolePermission.API_DEFINITION,
API,
RolePermissionAction.READ
)
)
.thenReturn(false);

final Response response = rootTarget(API).request().get();

assertEquals(OK_200, response.getStatus());

final ApiV4 responseApi = response.readEntity(ApiV4.class);
assertNotNull(responseApi);
assertEquals(API, responseApi.getName());
assertNotNull(responseApi.getLinks());
assertNotNull(responseApi.getLinks().getPictureUrl());
assertNotNull(responseApi.getLinks().getBackgroundUrl());
assertNotNull(responseApi.getProperties());
assertTrue(responseApi.getProperties().isEmpty());
assertNull(responseApi.getServices());
assertNull(responseApi.getResources());
assertNotNull(responseApi.getResponseTemplates());
assertEquals(0, responseApi.getResponseTemplates().size());
assertNotNull(responseApi.getListeners());
assertNotNull(responseApi.getListeners().get(0));
}

@Test
public void should_get_api_V2() {
when(apiSearchServiceV4.findGenericById(GraviteeContext.getExecutionContext(), API)).thenReturn(this.fakeApiEntityV2());
Expand Down Expand Up @@ -465,6 +605,91 @@ private ApiEntity fakeApiEntityV4() {
return apiEntity;
}

private NativeApiEntity fakeNativeApiEntityV4() {
var apiEntity = new NativeApiEntity();
apiEntity.setDefinitionVersion(DefinitionVersion.V4);
apiEntity.setType(ApiType.NATIVE);
apiEntity.setId(API);
apiEntity.setName(API);
var kafkaListener = new KafkaListener();
kafkaListener.setHost("my.fake.host");
kafkaListener.setPort(1000);

var entrypoint = new NativeEntrypoint();
entrypoint.setType("native-kafka");
entrypoint.setConfiguration("{\"nice\": \"configuration\"}");
kafkaListener.setEntrypoints(List.of(entrypoint));
kafkaListener.setType(ListenerType.KAFKA);

apiEntity.setListeners(List.of(kafkaListener));
apiEntity.setProperties(List.of(new Property()));
apiEntity.setServices(new NativeApiServices());
apiEntity.setResources(List.of(new Resource()));
apiEntity.setUpdatedAt(new Date());

var endpointGroup = new NativeEndpointGroup();
endpointGroup.setType("native-kafka");
endpointGroup.setSharedConfiguration("{\"shared\": \"configuration\"}");
var endpoint = new NativeEndpoint();
endpoint.setType("native-kafka");
endpoint.setConfiguration(
"{\n" +
" \"bootstrapServers\": \"kafka:9092\",\n" +
" \"topics\": [\n" +
" \"demo\"\n" +
" ],\n" +
" \"producer\": {\n" +
" \"enabled\": false\n" +
" },\n" +
" \"consumer\": {\n" +
" \"encodeMessageId\": true,\n" +
" \"enabled\": true,\n" +
" \"autoOffsetReset\": \"earliest\"\n" +
" }\n" +
" }"
);
endpointGroup.setEndpoints(List.of(endpoint));
apiEntity.setEndpointGroups(List.of(endpointGroup));

var flow = new NativeFlow();
flow.setName("flowName");
flow.setEnabled(true);

Step step = new Step();
step.setEnabled(true);
step.setPolicy("my-policy");
step.setCondition("my-condition");
flow.setInteract(List.of(step));
flow.setConnect(List.of(step));
flow.setPublish(List.of(step));
flow.setSubscribe(List.of(step));
flow.setTags(Set.of("tag1", "tag2"));

apiEntity.setFlows(List.of(flow));

Service dynamicProperty = new Service();
dynamicProperty.setConfiguration(
"{\n" +
" \"enabled\": true,\n" +
" \"schedule\": \"*/10 * * * * *\",\n" +
" \"provider\": \"HTTP\",\n" +
" \"configuration\": {\n" +
" \"url\": \"https://api.gravitee.io/echo\",\n" +
" \"specification\": \"[{\\n \\\"operation\\\": \\\"shift\\\",\\n \\\"spec\\\": {\\n \\\"rating\\\": {\\n \\\"primary\\\": {\\n \\\"value\\\": \\\"Rating\\\",\\n \\\"max\\\": \\\"RatingRange\\\"\\n },\\n \\\"*\\\": {\\n \\\"max\\\": \\\"SecondaryRatings.&1.Range\\\",\\n \\\"value\\\": \\\"SecondaryRatings.&1.Value\\\",\\n \\\"$\\\": \\\"SecondaryRatings.&1.Id\\\"\\n }\\n }\\n }\\n },\\n {\\n \\\"operation\\\": \\\"default\\\",\\n \\\"spec\\\": {\\n \\\"Range\\\": 5,\\n \\\"SecondaryRatings\\\": {\\n \\\"*\\\": {\\n \\\"Range\\\": 5\\n }\\n }\\n }\\n }\\n]\",\n" +
" \"useSystemProxy\": false,\n" +
" \"method\": \"GET\",\n" +
" \"body\": \"{\\n \\\"rating\\\": {\\n \\\"primary\\\": {\\n \\\"value\\\": 3\\n },\\n \\\"quality\\\": {\\n \\\"value\\\": 3\\n }\\n }\\n }\"\n" +
" }\n" +
" }"
);
dynamicProperty.setType("dynamic-property");
dynamicProperty.setEnabled(true);
dynamicProperty.setOverrideConfiguration(true);
apiEntity.setServices(new NativeApiServices(dynamicProperty));

return apiEntity;
}

private io.gravitee.rest.api.model.api.ApiEntity fakeApiEntityV2() {
var apiEntity = new io.gravitee.rest.api.model.api.ApiEntity();
apiEntity.setGraviteeDefinitionVersion(DefinitionVersion.V2.getLabel());
Expand Down
Loading

0 comments on commit d967607

Please sign in to comment.