aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorandre.schmid <andre.schmid@est.tech>2021-06-21 22:25:28 +0100
committerChristophe Closset <christophe.closset@intl.att.com>2021-07-05 09:21:57 +0000
commitb835031b83230c36649c6e77787867a465e0ac47 (patch)
treec988e23a137da1f2a757693f56ab1a457394444f
parent70975c212b58b793d3893e131a3d23d8144f5df9 (diff)
Create REST endpoint to retrieve models
Change-Id: Ifca0095d84d5da4ab4b055942d893e9c6a259eb7 Issue-ID: SDC-3622 Signed-off-by: André Schmid <andre.schmid@est.tech>
-rw-r--r--catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ModelBusinessLogic.java10
-rw-r--r--catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ModelServlet.java28
-rw-r--r--catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ModelBusinessLogicTest.java17
-rw-r--r--catalog-be/src/test/java/org/openecomp/sdc/be/servlets/ModelServletTest.java71
-rw-r--r--catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/operations/exception/ModelOperationExceptionSupplier.java6
-rw-r--r--catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/ModelOperation.java55
-rw-r--r--catalog-model/src/test/java/org/openecomp/sdc/be/model/operations/impl/ModelOperationTest.java36
7 files changed, 193 insertions, 30 deletions
diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ModelBusinessLogic.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ModelBusinessLogic.java
index 7f68a00a8b..a048af4ac8 100644
--- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ModelBusinessLogic.java
+++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ModelBusinessLogic.java
@@ -21,6 +21,7 @@ package org.openecomp.sdc.be.components.impl;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
+import java.util.List;
import java.util.Map;
import java.util.Optional;
import org.apache.commons.lang3.StringUtils;
@@ -56,6 +57,15 @@ public class ModelBusinessLogic {
return modelOperation.findModelByName(modelName);
}
+ /**
+ * Loads the list of models.
+ *
+ * @return the list of models
+ */
+ public List<Model> listModels() {
+ return modelOperation.findAllModels();
+ }
+
public void createModelImports(final String modelName, final InputStream modelImportsZip) {
if (StringUtils.isEmpty(modelName)) {
throw ModelOperationExceptionSupplier.invalidModel(modelName).get();
diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ModelServlet.java b/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ModelServlet.java
index 0c5e4aebd6..337c641b33 100644
--- a/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ModelServlet.java
+++ b/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ModelServlet.java
@@ -30,10 +30,12 @@ import io.swagger.v3.oas.annotations.servers.Server;
import io.swagger.v3.oas.annotations.tags.Tag;
import java.io.InputStream;
import java.util.Arrays;
+import java.util.List;
import javax.inject.Inject;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
import javax.ws.rs.HeaderParam;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
@@ -121,6 +123,32 @@ public class ModelServlet extends AbstractValidationsServlet {
}
}
+ @GET
+ @Path("/model")
+ @Produces(MediaType.APPLICATION_JSON)
+ @PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE)
+ @Operation(method = "GET", summary = "List TOSCA models", description = "List all the existing TOSCA models",
+ responses = {
+ @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Model.class)))),
+ @ApiResponse(responseCode = "200", description = "Listing successful"),
+ @ApiResponse(responseCode = "403", description = "Restricted operation")
+ }
+ )
+ public Response listModels(@HeaderParam(value = Constants.USER_ID_HEADER) final String userId) {
+ validateUser(ValidationUtils.sanitizeInputString(userId));
+ try {
+ final List<Model> modelList = modelBusinessLogic.listModels();
+ return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), RepresentationUtils.toRepresentation(modelList));
+ } catch (final BusinessException e) {
+ throw e;
+ } catch (final Exception e) {
+ var errorMsg = "Unexpected error while listing the models";
+ BeEcompErrorManager.getInstance().logBeRestApiGeneralError(errorMsg);
+ log.error(errorMsg, e);
+ return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));
+ }
+ }
+
@PUT
@Path("/model/imports")
@Consumes(MediaType.MULTIPART_FORM_DATA)
diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ModelBusinessLogicTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ModelBusinessLogicTest.java
index b88bdfb01c..ef334f5510 100644
--- a/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ModelBusinessLogicTest.java
+++ b/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ModelBusinessLogicTest.java
@@ -33,6 +33,8 @@ import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
+import java.util.Collections;
+import java.util.List;
import java.util.Map;
import java.util.Optional;
import org.junit.jupiter.api.BeforeEach;
@@ -190,4 +192,19 @@ class ModelBusinessLogicTest {
actualModel = modelBusinessLogic.findModel(null);
assertTrue(actualModel.isEmpty());
}
+
+ @Test
+ void listModelsSuccessTest() {
+ final List<Model> expectedModelList = List.of(new Model());
+ when(modelOperation.findAllModels()).thenReturn(expectedModelList);
+ final List<Model> actualModelList = modelBusinessLogic.listModels();
+ assertEquals(expectedModelList, actualModelList, "The model list should be as expected");
+ }
+
+ @Test
+ void listModelsTest_emptyList() {
+ when(modelOperation.findAllModels()).thenReturn(Collections.emptyList());
+ final List<Model> actualModelList = modelBusinessLogic.listModels();
+ assertTrue(actualModelList.isEmpty(), "The model list should be empty");
+ }
} \ No newline at end of file
diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/servlets/ModelServletTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/servlets/ModelServletTest.java
index 5992be4e9d..12f803fd19 100644
--- a/catalog-be/src/test/java/org/openecomp/sdc/be/servlets/ModelServletTest.java
+++ b/catalog-be/src/test/java/org/openecomp/sdc/be/servlets/ModelServletTest.java
@@ -26,12 +26,15 @@ import static org.mockito.Mockito.when;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
+import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Path;
+import java.util.List;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import javax.ws.rs.client.Entity;
+import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response.Status;
import org.apache.commons.lang3.StringUtils;
@@ -44,11 +47,8 @@ import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.test.JerseyTest;
import org.glassfish.jersey.test.TestProperties;
import org.junit.jupiter.api.AfterEach;
-import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.TestInstance;
-import org.junit.jupiter.api.TestInstance.Lifecycle;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
@@ -79,7 +79,6 @@ import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.web.context.WebApplicationContext;
-@TestInstance(Lifecycle.PER_CLASS)
class ModelServletTest extends JerseyTest {
private static final String USER_ID = "cs0008";
@@ -121,8 +120,20 @@ class ModelServletTest extends JerseyTest {
private final Path rootPath = Path.of("/v1/catalog/model");
private final Path importsPath = rootPath.resolve("imports");
- @BeforeAll
- public void initClass() {
+ @BeforeEach
+ void resetMock() throws Exception {
+ super.setUp();
+ initMocks();
+ initConfig();
+ initTestData();
+ }
+
+ @AfterEach
+ void after() throws Exception {
+ super.tearDown();
+ }
+
+ private void initMocks() {
when(request.getSession()).thenReturn(session);
when(session.getServletContext()).thenReturn(servletContext);
when(servletContext.getAttribute(Constants.WEB_APPLICATION_CONTEXT_WRAPPER_ATTR))
@@ -132,6 +143,9 @@ class ModelServletTest extends JerseyTest {
when(request.getHeader(Constants.USER_ID_HEADER)).thenReturn(USER_ID);
when(webApplicationContext.getBean(ServletUtils.class)).thenReturn(servletUtils);
when(servletUtils.getComponentsUtils()).thenReturn(componentsUtils);
+ }
+
+ private void initConfig() {
final String appConfigDir = "src/test/resources/config/catalog-be";
final ConfigurationSource configurationSource = new FSConfigurationSource(ExternalConfiguration.getChangeListener(), appConfigDir);
final ConfigurationManager configurationManager = new ConfigurationManager(configurationSource);
@@ -141,17 +155,6 @@ class ModelServletTest extends JerseyTest {
ExternalConfiguration.setAppName("catalog-be");
}
- @BeforeEach
- void resetMock() throws Exception {
- super.setUp();
- initTestData();
- }
-
- @AfterEach
- void after() throws Exception {
- super.tearDown();
- }
-
private void initTestData() {
final String modelName = "MY-INTEGRATION-TEST-MODEL";
model = new Model(modelName);
@@ -287,6 +290,40 @@ class ModelServletTest extends JerseyTest {
assertEquals(Status.INTERNAL_SERVER_ERROR.getStatusCode(), response.getStatus());
}
+ @Test
+ void listModelSuccessTest() throws IOException {
+ var model1 = new Model("model1");
+ var model2 = new Model("model2");
+ var model3 = new Model("model3");
+ final List<Model> modelList = List.of(model1, model2, model3);
+ when(responseFormat.getStatus()).thenReturn(HttpStatus.OK_200);
+ when(componentsUtils.getResponseFormat(ActionStatus.OK)).thenReturn(responseFormat);
+ when(modelBusinessLogic.listModels()).thenReturn(modelList);
+
+ final var response = target(rootPath.toString()).request(MediaType.APPLICATION_JSON)
+ .header(Constants.USER_ID_HEADER, USER_ID)
+ .get();
+
+ assertEquals(Status.OK.getStatusCode(), response.getStatus());
+ assertEquals(MediaType.APPLICATION_JSON, response.getHeaderString(HttpHeaders.CONTENT_TYPE));
+ final String responseBody = response.readEntity(String.class);
+ final String toRepresentation = (String) RepresentationUtils.toRepresentation(modelList);
+ assertEquals(toRepresentation, responseBody);
+ }
+
+ @Test
+ void listModelErrorTest() {
+ when(responseFormat.getStatus()).thenReturn(HttpStatus.INTERNAL_SERVER_ERROR_500);
+ when(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR)).thenReturn(responseFormat);
+ doThrow(new RuntimeException()).when(modelBusinessLogic).listModels();
+
+ final var response = target(rootPath.toString()).request(MediaType.APPLICATION_JSON)
+ .header(Constants.USER_ID_HEADER, USER_ID)
+ .get();
+
+ assertEquals(Status.INTERNAL_SERVER_ERROR.getStatusCode(), response.getStatus());
+ }
+
private FormDataMultiPart buildUpdateFormDataMultiPart(final String modelName, final byte[] importFilesZip) {
return new FormDataMultiPart()
.field("modelName", modelName)
diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/operations/exception/ModelOperationExceptionSupplier.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/operations/exception/ModelOperationExceptionSupplier.java
index c2ad071d13..6622bf5bd8 100644
--- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/operations/exception/ModelOperationExceptionSupplier.java
+++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/operations/exception/ModelOperationExceptionSupplier.java
@@ -21,6 +21,7 @@ package org.openecomp.sdc.be.model.jsonjanusgraph.operations.exception;
import java.util.function.Supplier;
import org.openecomp.sdc.be.dao.api.ActionStatus;
+import org.openecomp.sdc.be.dao.janusgraph.JanusGraphOperationStatus;
/**
* Supplies operation exception needed by the the Model logic
@@ -47,4 +48,9 @@ public class ModelOperationExceptionSupplier {
return () -> new OperationException(ActionStatus.MODEL_ALREADY_EXISTS, modelName);
}
+ public static Supplier<OperationException> failedToRetrieveModels(final JanusGraphOperationStatus janusGraphOperationStatus) {
+ var errorMsg = String.format("Failed to retrieve models. Status '%s'", janusGraphOperationStatus);
+ return () -> new OperationException(ActionStatus.GENERAL_ERROR, errorMsg);
+ }
+
}
diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/ModelOperation.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/ModelOperation.java
index ccc18e57dd..ddc0367a44 100644
--- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/ModelOperation.java
+++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/ModelOperation.java
@@ -20,6 +20,7 @@ package org.openecomp.sdc.be.model.operations.impl;
import fj.data.Either;
import java.nio.charset.StandardCharsets;
+import java.util.Collections;
import java.util.EnumMap;
import java.util.List;
import java.util.Map;
@@ -99,18 +100,11 @@ public class ModelOperation {
final Map<GraphPropertyEnum, Object> props = new EnumMap<>(GraphPropertyEnum.class);
props.put(GraphPropertyEnum.NAME, name);
props.put(GraphPropertyEnum.UNIQUE_ID, UniqueIdBuilder.buildModelUid(name));
- final Either<List<GraphVertex>, JanusGraphOperationStatus> result = janusGraphDao.getByCriteria(VertexTypeEnum.MODEL, props);
- if (result.isRight()) {
- final JanusGraphOperationStatus janusGraphOperationStatus = result.right().value();
- if (janusGraphOperationStatus == JanusGraphOperationStatus.NOT_FOUND) {
- return Optional.empty();
- }
- log.error(EcompLoggerErrorCode.DATA_ERROR, this.getClass().getName(),
- String.format("Problem while getting model %s. reason %s", name, janusGraphOperationStatus));
- throw new OperationException(ActionStatus.GENERAL_ERROR,
- String.format("Failed to get model %s on JanusGraph with %s error", name, janusGraphOperationStatus));
+ final List<GraphVertex> modelVerticesList = findModelVerticesByCriteria(props);
+ if (modelVerticesList.isEmpty()) {
+ return Optional.empty();
}
- return Optional.ofNullable(result.left().value().get(0));
+ return Optional.ofNullable(modelVerticesList.get(0));
}
public Optional<Model> findModelByName(final String name) {
@@ -123,8 +117,7 @@ public class ModelOperation {
}
final GraphVertex graphVertex = modelVertexOpt.get();
- final var model = new Model((String) graphVertex.getMetadataProperty(GraphPropertyEnum.NAME));
- return Optional.of(model);
+ return Optional.of(convertToModel(graphVertex));
}
public void createModelImports(final String modelId, final Map<String, byte[]> zipContent) {
@@ -144,6 +137,42 @@ public class ModelOperation {
}).collect(Collectors.toList());
toscaModelImportCassandraDao.importAll(modelId, toscaImportByModelList);
}
+
+ /**
+ * Finds all the models.
+ *
+ * @return the list of models
+ */
+ public List<Model> findAllModels() {
+ return findModelsByCriteria(Collections.emptyMap());
+ }
+
+ private List<Model> findModelsByCriteria(final Map<GraphPropertyEnum, Object> propertyCriteria) {
+ final List<GraphVertex> modelVerticesByCriteria = findModelVerticesByCriteria(propertyCriteria);
+ if (modelVerticesByCriteria.isEmpty()) {
+ return Collections.emptyList();
+ }
+
+ return modelVerticesByCriteria.stream().map(this::convertToModel).collect(Collectors.toList());
+ }
+
+ private List<GraphVertex> findModelVerticesByCriteria(final Map<GraphPropertyEnum, Object> propertyCriteria) {
+ final Either<List<GraphVertex>, JanusGraphOperationStatus> result = janusGraphDao.getByCriteria(VertexTypeEnum.MODEL, propertyCriteria);
+ if (result.isRight()) {
+ final var janusGraphOperationStatus = result.right().value();
+ if (janusGraphOperationStatus == JanusGraphOperationStatus.NOT_FOUND) {
+ return Collections.emptyList();
+ }
+ final var operationException = ModelOperationExceptionSupplier.failedToRetrieveModels(janusGraphOperationStatus).get();
+ log.error(EcompLoggerErrorCode.DATA_ERROR, this.getClass().getName(), operationException.getMessage());
+ throw operationException;
+ }
+ return result.left().value();
+ }
+
+ private Model convertToModel(final GraphVertex modelGraphVertex) {
+ return new Model((String) modelGraphVertex.getMetadataProperty(GraphPropertyEnum.NAME));
+ }
}
diff --git a/catalog-model/src/test/java/org/openecomp/sdc/be/model/operations/impl/ModelOperationTest.java b/catalog-model/src/test/java/org/openecomp/sdc/be/model/operations/impl/ModelOperationTest.java
index 620c7f76a6..c48a1524b8 100644
--- a/catalog-model/src/test/java/org/openecomp/sdc/be/model/operations/impl/ModelOperationTest.java
+++ b/catalog-model/src/test/java/org/openecomp/sdc/be/model/operations/impl/ModelOperationTest.java
@@ -20,6 +20,7 @@ package org.openecomp.sdc.be.model.operations.impl;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.ArgumentMatchers.any;
@@ -55,6 +56,7 @@ import org.openecomp.sdc.be.data.model.ToscaImportByModel;
import org.openecomp.sdc.be.datatypes.enums.GraphPropertyEnum;
import org.openecomp.sdc.be.model.Model;
import org.openecomp.sdc.be.model.ModelTestBase;
+import org.openecomp.sdc.be.model.jsonjanusgraph.operations.exception.ModelOperationExceptionSupplier;
import org.openecomp.sdc.be.model.jsonjanusgraph.operations.exception.OperationException;
import org.openecomp.sdc.be.resources.data.ModelData;
import org.springframework.test.context.ContextConfiguration;
@@ -225,4 +227,38 @@ class ModelOperationTest extends ModelTestBase {
assertTrue(modelOperation.findModelByName(null).isEmpty());
}
+ @Test
+ void findAllModelsSuccessTest() {
+ final GraphVertex expectedVertex = mock(GraphVertex.class);
+ when(expectedVertex.getMetadataProperty(GraphPropertyEnum.NAME)).thenReturn(modelName);
+ when(janusGraphDao.getByCriteria(VertexTypeEnum.MODEL, Collections.emptyMap())).thenReturn(Either.left(List.of(expectedVertex)));
+ final List<Model> actualModelList = modelOperation.findAllModels();
+ assertFalse(actualModelList.isEmpty());
+ assertEquals(1, actualModelList.size());
+ assertEquals(modelName, actualModelList.get(0).getName());
+ }
+
+ @Test
+ void findAllModelsTest_noModelsFound() {
+ when(janusGraphDao.getByCriteria(VertexTypeEnum.MODEL, Collections.emptyMap())).thenReturn(Either.left(Collections.emptyList()));
+ final List<Model> actualModelList = modelOperation.findAllModels();
+ assertTrue(actualModelList.isEmpty());
+ }
+
+ @Test
+ void findAllModelsTest_janusGraphNotFound() {
+ when(janusGraphDao.getByCriteria(VertexTypeEnum.MODEL, Collections.emptyMap()))
+ .thenReturn(Either.right(JanusGraphOperationStatus.NOT_FOUND));
+ final List<Model> actualModelList = modelOperation.findAllModels();
+ assertTrue(actualModelList.isEmpty());
+ }
+
+ @Test
+ void findAllModelsTest_janusGraphError() {
+ when(janusGraphDao.getByCriteria(VertexTypeEnum.MODEL, Collections.emptyMap()))
+ .thenReturn(Either.right(JanusGraphOperationStatus.GENERAL_ERROR));
+ final var actualException = assertThrows(OperationException.class, () -> modelOperation.findAllModels());
+ final var expectedException = ModelOperationExceptionSupplier.failedToRetrieveModels(JanusGraphOperationStatus.GENERAL_ERROR).get();
+ assertEquals(expectedException.getMessage(), actualException.getMessage());
+ }
}