summaryrefslogtreecommitdiffstats
path: root/catalog-be/src/main
diff options
context:
space:
mode:
authorvasraz <vasyl.razinkov@est.tech>2023-06-28 15:34:47 +0100
committerVasyl Razinkov <vasyl.razinkov@est.tech>2023-06-29 10:31:23 +0000
commit2e4af1e0c0611851f450b2e215485064f6795958 (patch)
tree2c766e17841c24dc40faa98ff260234ea2cfa80a /catalog-be/src/main
parent6d4057b032a30daa8388f9f1a323eae1581eb91c (diff)
Implement YAML Validator
Signed-off-by: Vasyl Razinkov <vasyl.razinkov@est.tech> Change-Id: I0365d4160984e4d68906959fb801ec7da5449b77 Issue-ID: SDC-4537
Diffstat (limited to 'catalog-be/src/main')
-rw-r--r--catalog-be/src/main/docker/backend/chef-repo/cookbooks/sdc-catalog-be/files/default/error-configuration.yaml10
-rw-r--r--catalog-be/src/main/java/org/openecomp/sdc/be/servlets/TypesUploadServlet.java207
-rw-r--r--catalog-be/src/main/resources/config/error-configuration.yaml10
-rw-r--r--catalog-be/src/main/resources/validateYaml/schema.json121
4 files changed, 259 insertions, 89 deletions
diff --git a/catalog-be/src/main/docker/backend/chef-repo/cookbooks/sdc-catalog-be/files/default/error-configuration.yaml b/catalog-be/src/main/docker/backend/chef-repo/cookbooks/sdc-catalog-be/files/default/error-configuration.yaml
index 0cdcd01a00..006752ee0c 100644
--- a/catalog-be/src/main/docker/backend/chef-repo/cookbooks/sdc-catalog-be/files/default/error-configuration.yaml
+++ b/catalog-be/src/main/docker/backend/chef-repo/cookbooks/sdc-catalog-be/files/default/error-configuration.yaml
@@ -2894,4 +2894,12 @@ errors:
code: 409,
message: "System deployed %1 cannot be archived. Component: '%2'",
messageId: "SVC4018"
- } \ No newline at end of file
+ }
+
+ #---------SVC4010-----------------------------
+ # %1 - error's list
+ YAML_IS_INVALID: {
+ code: 402,
+ message: "Error: Uploaded YAML file is invalid.\n%1",
+ messageId: "SVC4010"
+ }
diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/TypesUploadServlet.java b/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/TypesUploadServlet.java
index f7ea9bb407..309bff28c3 100644
--- a/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/TypesUploadServlet.java
+++ b/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/TypesUploadServlet.java
@@ -19,8 +19,13 @@
*/
package org.openecomp.sdc.be.servlets;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
import com.google.gson.reflect.TypeToken;
import com.jcabi.aspects.Loggable;
+import com.networknt.schema.JsonSchemaFactory;
+import com.networknt.schema.SpecVersion;
+import com.networknt.schema.ValidationMessage;
import fj.data.Either;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
@@ -30,25 +35,6 @@ import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.servers.Server;
import io.swagger.v3.oas.annotations.tags.Tag;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.nio.charset.StandardCharsets;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.function.Supplier;
-import java.util.stream.Collectors;
-import javax.inject.Inject;
-import javax.servlet.http.HttpServletRequest;
-import javax.ws.rs.Consumes;
-import javax.ws.rs.HeaderParam;
-import javax.ws.rs.POST;
-import javax.ws.rs.Path;
-import javax.ws.rs.Produces;
-import javax.ws.rs.core.Context;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
import org.apache.commons.lang3.tuple.ImmutablePair;
import org.glassfish.jersey.media.multipart.FormDataParam;
import org.jetbrains.annotations.NotNull;
@@ -64,6 +50,7 @@ import org.openecomp.sdc.be.components.impl.RelationshipTypeImportManager;
import org.openecomp.sdc.be.components.impl.ResourceImportManager;
import org.openecomp.sdc.be.components.impl.aaf.AafPermission;
import org.openecomp.sdc.be.components.impl.aaf.PermissionAllowed;
+import org.openecomp.sdc.be.components.impl.exceptions.ByActionStatusComponentException;
import org.openecomp.sdc.be.components.impl.model.ToscaTypeImportData;
import org.openecomp.sdc.be.config.BeEcompErrorManager;
import org.openecomp.sdc.be.dao.api.ActionStatus;
@@ -85,6 +72,28 @@ import org.openecomp.sdc.common.log.wrappers.Logger;
import org.openecomp.sdc.exception.ResponseFormat;
import org.springframework.stereotype.Controller;
+import javax.inject.Inject;
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.HeaderParam;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.function.Supplier;
+import java.util.stream.Collectors;
+
@Loggable(prepend = true, value = Loggable.DEBUG, trim = false)
@Path("/v1/catalog/uploadType")
@Consumes(MediaType.MULTIPART_FORM_DATA)
@@ -129,67 +138,67 @@ public class TypesUploadServlet extends AbstractValidationsServlet {
@POST
@Path("/capability")
@Operation(description = "Create Capability Type from yaml", method = "POST", summary = "Returns created Capability Type", responses = {
- @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
- @ApiResponse(responseCode = "201", description = "Capability Type created"),
- @ApiResponse(responseCode = "403", description = "Restricted operation"),
- @ApiResponse(responseCode = "400", description = "Invalid content / Missing content"),
- @ApiResponse(responseCode = "409", description = "Capability Type already exist")})
+ @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
+ @ApiResponse(responseCode = "201", description = "Capability Type created"),
+ @ApiResponse(responseCode = "403", description = "Restricted operation"),
+ @ApiResponse(responseCode = "400", description = "Invalid content / Missing content"),
+ @ApiResponse(responseCode = "409", description = "Capability Type already exist")})
@PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE)
public Response uploadCapabilityType(@Parameter(description = "FileInputStream") @FormDataParam("capabilityTypeZip") File file,
@Context final HttpServletRequest request, @HeaderParam("USER_ID") String creator,
@Parameter(description = "model name") @FormDataParam("model") String modelName,
@Parameter(description = "includeToModelImport") @FormDataParam("includeToModelImport") boolean includeToModelDefaultImports) {
ConsumerFourParam<Wrapper<Response>, String, String, Boolean> createElementsMethod = (responseWrapper, ymlPayload, model, includeToModelImport) ->
- createElementsType(responseWrapper, () -> capabilityTypeImportManager.createCapabilityTypes(ymlPayload, modelName,
- includeToModelDefaultImports));
+ createElementsType(responseWrapper, () -> capabilityTypeImportManager.createCapabilityTypes(ymlPayload, modelName,
+ includeToModelDefaultImports));
return uploadElementTypeServletLogic(createElementsMethod, file, request, creator, NodeTypeEnum.CapabilityType.name(), modelName,
- includeToModelDefaultImports);
+ includeToModelDefaultImports);
}
@POST
@Path("/relationship")
@Operation(description = "Create Relationship Type from yaml", method = "POST", summary = "Returns created Relationship Type", responses = {
- @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
- @ApiResponse(responseCode = "201", description = "Relationship Type created"),
- @ApiResponse(responseCode = "403", description = "Restricted operation"),
- @ApiResponse(responseCode = "400", description = "Invalid content / Missing content"),
- @ApiResponse(responseCode = "409", description = "Relationship Type already exist")})
+ @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
+ @ApiResponse(responseCode = "201", description = "Relationship Type created"),
+ @ApiResponse(responseCode = "403", description = "Restricted operation"),
+ @ApiResponse(responseCode = "400", description = "Invalid content / Missing content"),
+ @ApiResponse(responseCode = "409", description = "Relationship Type already exist")})
@PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE)
public Response uploadRelationshipType(@Parameter(description = "FileInputStream") @FormDataParam("relationshipTypeZip") File file,
@Context final HttpServletRequest request, @HeaderParam("USER_ID") String creator,
@Parameter(description = "model name") @FormDataParam("model") String modelName,
@Parameter(description = "includeToModelImport") @FormDataParam("includeToModelImport") boolean includeToModelDefaultImports) {
return uploadElementTypeServletLogic(this::createRelationshipTypes, file, request, creator, NodeTypeEnum.RelationshipType.getName(),
- modelName, includeToModelDefaultImports);
+ modelName, includeToModelDefaultImports);
}
@POST
@Path("/interfaceLifecycle")
@Operation(description = "Create Interface Lyfecycle Type from yaml", method = "POST", summary = "Returns created Interface Lifecycle Type", responses = {
- @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
- @ApiResponse(responseCode = "201", description = "Interface Lifecycle Type created"),
- @ApiResponse(responseCode = "403", description = "Restricted operation"),
- @ApiResponse(responseCode = "400", description = "Invalid content / Missing content"),
- @ApiResponse(responseCode = "409", description = "Interface Lifecycle Type already exist")})
+ @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
+ @ApiResponse(responseCode = "201", description = "Interface Lifecycle Type created"),
+ @ApiResponse(responseCode = "403", description = "Restricted operation"),
+ @ApiResponse(responseCode = "400", description = "Invalid content / Missing content"),
+ @ApiResponse(responseCode = "409", description = "Interface Lifecycle Type already exist")})
@PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE)
public Response uploadInterfaceLifecycleType(@Parameter(description = "FileInputStream") @FormDataParam("interfaceLifecycleTypeZip") File file,
@Context final HttpServletRequest request, @HeaderParam("USER_ID") String creator,
@Parameter(description = "model name") @FormDataParam("model") String modelName,
@Parameter(description = "includeToModelImport") @FormDataParam("includeToModelImport") boolean includeToModelDefaultImports) {
ConsumerTwoParam<Wrapper<Response>, String> createElementsMethod = (responseWrapper, ymlPayload) ->
- createElementsType(responseWrapper, () -> interfaceLifecycleTypeImportManager.createLifecycleTypes(ymlPayload, modelName,
- includeToModelDefaultImports));
+ createElementsType(responseWrapper, () -> interfaceLifecycleTypeImportManager.createLifecycleTypes(ymlPayload, modelName,
+ includeToModelDefaultImports));
return uploadElementTypeServletLogic(createElementsMethod, file, request, creator, "Interface Types");
}
@POST
@Path("/artifactTypes")
@Operation(description = "Create Tosca Artifact types from yaml", method = "POST", summary = "Returns created Tosca artifact types", responses = {
- @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
- @ApiResponse(responseCode = "201", description = "Tosca Artifact types created"),
- @ApiResponse(responseCode = "403", description = "Restricted operation"),
- @ApiResponse(responseCode = "400", description = "Invalid content / Missing content"),
- @ApiResponse(responseCode = "409", description = "Tosca Artifact Type already exist")})
+ @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
+ @ApiResponse(responseCode = "201", description = "Tosca Artifact types created"),
+ @ApiResponse(responseCode = "403", description = "Restricted operation"),
+ @ApiResponse(responseCode = "400", description = "Invalid content / Missing content"),
+ @ApiResponse(responseCode = "409", description = "Tosca Artifact Type already exist")})
@PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE)
public Response uploadArtifactTypes(@Parameter(description = "Zip file containing a yaml with the TOSCA artifact types definition")
@FormDataParam("artifactsZip") File file,
@@ -198,69 +207,69 @@ public class TypesUploadServlet extends AbstractValidationsServlet {
@Parameter(description = "A flag to add types to the default imports")
@FormDataParam("includeToModelImport") boolean includeToModelDefaultImports) {
final ConsumerTwoParam<Wrapper<Response>, String> createElementsMethod = (responseWrapper, ymlPayload) ->
- createElementsType(responseWrapper,
- () -> artifactTypeImportManager.createArtifactTypes(ymlPayload, modelName, includeToModelDefaultImports));
+ createElementsType(responseWrapper,
+ () -> artifactTypeImportManager.createArtifactTypes(ymlPayload, modelName, includeToModelDefaultImports));
return uploadElementTypeServletLogic(createElementsMethod, file, request, creator, NodeTypeEnum.ArtifactType.getName());
}
@POST
@Path("/categories")
@Operation(description = "Create Categories from yaml", method = "POST", summary = "Returns created categories", responses = {
- @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
- @ApiResponse(responseCode = "201", description = "Categories created"),
- @ApiResponse(responseCode = "403", description = "Restricted operation"),
- @ApiResponse(responseCode = "400", description = "Invalid content / Missing content"),
- @ApiResponse(responseCode = "409", description = "Category already exist")})
+ @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
+ @ApiResponse(responseCode = "201", description = "Categories created"),
+ @ApiResponse(responseCode = "403", description = "Restricted operation"),
+ @ApiResponse(responseCode = "400", description = "Invalid content / Missing content"),
+ @ApiResponse(responseCode = "409", description = "Category already exist")})
@PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE)
public Response uploadCategories(@Parameter(description = "FileInputStream") @FormDataParam("categoriesZip") File file,
@Context final HttpServletRequest request, @HeaderParam("USER_ID") String creator) {
ConsumerTwoParam<Wrapper<Response>, String> createElementsMethod = (responseWrapper, ymlPayload) ->
- createElementsType(responseWrapper, () -> categoriesImportManager.createCategories(ymlPayload));
+ createElementsType(responseWrapper, () -> categoriesImportManager.createCategories(ymlPayload));
return uploadElementTypeServletLogic(createElementsMethod, file, request, creator, "categories");
}
@POST
@Path("/datatypes")
@Operation(description = "Create Data Types from zip", method = "POST", summary = "Returns created data types", responses = {
- @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
- @ApiResponse(responseCode = "201", description = "Data types created"),
- @ApiResponse(responseCode = "403", description = "Restricted operation"),
- @ApiResponse(responseCode = "400", description = "Invalid content / Missing content"),
- @ApiResponse(responseCode = "409", description = "Data types already exist")})
+ @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
+ @ApiResponse(responseCode = "201", description = "Data types created"),
+ @ApiResponse(responseCode = "403", description = "Restricted operation"),
+ @ApiResponse(responseCode = "400", description = "Invalid content / Missing content"),
+ @ApiResponse(responseCode = "409", description = "Data types already exist")})
@PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE)
public Response uploadDataTypes(@Parameter(description = "FileInputStream") @FormDataParam("dataTypesZip") File file,
@Context final HttpServletRequest request, @HeaderParam("USER_ID") String creator,
@Parameter(description = "model name") @FormDataParam("model") String modelName,
@Parameter(description = "includeToModelImport") @FormDataParam("includeToModelImport") boolean includeToModelDefaultImports) {
return uploadElementTypeServletLogic(this::createDataTypes, file, request, creator, NodeTypeEnum.DataType.getName(), modelName,
- includeToModelDefaultImports);
+ includeToModelDefaultImports);
}
@POST
@Path("/datatypesyaml")
@Operation(description = "Create Data Types from yaml", method = "POST", summary = "Returns created data types", responses = {
- @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
- @ApiResponse(responseCode = "201", description = "Data types created"),
- @ApiResponse(responseCode = "403", description = "Restricted operation"),
- @ApiResponse(responseCode = "400", description = "Invalid content / Missing content"),
- @ApiResponse(responseCode = "409", description = "Data types already exist")})
+ @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
+ @ApiResponse(responseCode = "201", description = "Data types created"),
+ @ApiResponse(responseCode = "403", description = "Restricted operation"),
+ @ApiResponse(responseCode = "400", description = "Invalid content / Missing content"),
+ @ApiResponse(responseCode = "409", description = "Data types already exist")})
@PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE)
public Response uploadDataTypesYaml(@Parameter(description = "FileInputStream") @FormDataParam("dataTypesYaml") File file,
@Context final HttpServletRequest request, @HeaderParam("USER_ID") String creator,
@Parameter(description = "model name") @FormDataParam("model") String modelName,
@Parameter(description = "includeToModelImport") @FormDataParam("includeToModelImport") boolean includeToModelDefaultImports) {
return uploadElementTypeServletLogicYaml(this::createDataTypes, file, request, creator, NodeTypeEnum.DataType.getName(), modelName,
- includeToModelDefaultImports);
+ includeToModelDefaultImports);
}
@POST
@Path("/grouptypes")
@Operation(description = "Create GroupTypes from yaml", method = "POST", summary = "Returns created group types", responses = {
- @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
- @ApiResponse(responseCode = "201", description = "group types created"),
- @ApiResponse(responseCode = "403", description = "Restricted operation"),
- @ApiResponse(responseCode = "400", description = "Invalid content / Missing content"),
- @ApiResponse(responseCode = "409", description = "group types already exist")})
+ @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
+ @ApiResponse(responseCode = "201", description = "group types created"),
+ @ApiResponse(responseCode = "403", description = "Restricted operation"),
+ @ApiResponse(responseCode = "400", description = "Invalid content / Missing content"),
+ @ApiResponse(responseCode = "409", description = "group types already exist")})
@PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE)
public Response uploadGroupTypes(@Parameter(description = "toscaTypeMetadata") @FormDataParam("toscaTypeMetadata") String toscaTypesMetaData,
@Parameter(description = "model name") @FormDataParam("model") String modelName,
@@ -269,17 +278,17 @@ public class TypesUploadServlet extends AbstractValidationsServlet {
@Parameter(description = "includeToModelImport") @FormDataParam("includeToModelImport") boolean includeToModelDefaultImports) {
Map<String, ToscaTypeMetadata> typesMetadata = getTypesMetadata(toscaTypesMetaData);
return uploadTypesWithMetaData(this::createGroupTypes, typesMetadata, file, request, creator, NodeTypeEnum.GroupType.getName(), modelName,
- includeToModelDefaultImports);
+ includeToModelDefaultImports);
}
@POST
@Path("/policytypes")
@Operation(description = "Create PolicyTypes from yaml", method = "POST", summary = "Returns created policy types", responses = {
- @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
- @ApiResponse(responseCode = "201", description = "policy types created"),
- @ApiResponse(responseCode = "403", description = "Restricted operation"),
- @ApiResponse(responseCode = "400", description = "Invalid content / Missing content"),
- @ApiResponse(responseCode = "409", description = "policy types already exist")})
+ @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
+ @ApiResponse(responseCode = "201", description = "policy types created"),
+ @ApiResponse(responseCode = "403", description = "Restricted operation"),
+ @ApiResponse(responseCode = "400", description = "Invalid content / Missing content"),
+ @ApiResponse(responseCode = "409", description = "policy types already exist")})
@PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE)
public Response uploadPolicyTypes(@Parameter(description = "toscaTypeMetadata") @FormDataParam("toscaTypeMetadata") String toscaTypesMetaData,
@Parameter(description = "model name") @FormDataParam("model") String modelName,
@@ -288,7 +297,7 @@ public class TypesUploadServlet extends AbstractValidationsServlet {
@Parameter(description = "includeToModelImport") @FormDataParam("includeToModelImport") boolean includeToModelDefaultImports) {
Map<String, ToscaTypeMetadata> typesMetadata = getTypesMetadata(toscaTypesMetaData);
return uploadTypesWithMetaData(this::createPolicyTypes, typesMetadata, file, request, creator, NodeTypeEnum.PolicyType.getName(), modelName,
- includeToModelDefaultImports);
+ includeToModelDefaultImports);
}
private Map<String, ToscaTypeMetadata> getTypesMetadata(String toscaTypesMetaData) {
@@ -346,6 +355,12 @@ public class TypesUploadServlet extends AbstractValidationsServlet {
final String elementTypeName, final String modelName,
final boolean includeToModelDefaultImports) {
init();
+ final Set<ValidationMessage> validationMessages = validateYaml(file);
+ if (!validationMessages.isEmpty()) {
+ throw new ByActionStatusComponentException(ActionStatus.YAML_IS_INVALID, validationMessages.stream().map(validationMessage -> {
+ return validationMessage.getMessage();
+ }).collect(Collectors.joining("\n")));
+ }
final String userId = initHeaderParam(creator, request, Constants.USER_ID_HEADER);
try {
final String url = request.getMethod() + " " + request.getRequestURI();
@@ -365,6 +380,24 @@ public class TypesUploadServlet extends AbstractValidationsServlet {
}
}
+ private Set<ValidationMessage> validateYaml(final File file) {
+ final ObjectMapper mapper = new ObjectMapper(new YAMLFactory());
+ final JsonSchemaFactory factory =
+ JsonSchemaFactory.builder(JsonSchemaFactory.getInstance(SpecVersion.VersionFlag.V202012)).objectMapper(mapper).build();
+
+ final Set<ValidationMessage> validationMessages = new HashSet<>();
+ try (final InputStream yamlFile = new FileInputStream(file);
+ final InputStream schemaFile = Thread.currentThread().getContextClassLoader().getResourceAsStream("validateYaml/schema.json")) {
+ validationMessages.addAll(factory.getSchema(schemaFile).validate(mapper.readTree(yamlFile)));
+ } catch (final IOException e) {
+ ValidationMessage.Builder builder = new ValidationMessage.Builder();
+ builder.customMessage(e.getMessage());
+ validationMessages.add(builder.build());
+ }
+
+ return validationMessages;
+ }
+
@NotNull
private String getFileAsString(File file) throws IOException {
try (final FileInputStream fl = new FileInputStream(file)) {
@@ -423,7 +456,7 @@ public class TypesUploadServlet extends AbstractValidationsServlet {
} else {
try {
Response response = buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.CREATED),
- RepresentationUtils.toRepresentation(eitherResult.left().value()));
+ RepresentationUtils.toRepresentation(eitherResult.left().value()));
responseWrapper.setInnerElement(response);
} catch (Exception e) {
responseWrapper.setInnerElement(buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR)));
@@ -436,27 +469,27 @@ public class TypesUploadServlet extends AbstractValidationsServlet {
private void createDataTypes(Wrapper<Response> responseWrapper, String dataTypesYml, final String modelName,
final boolean includeToModelDefaultImports) {
final Supplier<Either<List<ImmutablePair<DataTypeDefinition, Boolean>>, ResponseFormat>> generateElementTypeFromYml = () ->
- dataTypeImportManager.createDataTypes(dataTypesYml, modelName, includeToModelDefaultImports);
+ dataTypeImportManager.createDataTypes(dataTypesYml, modelName, includeToModelDefaultImports);
buildStatusForElementTypeCreate(responseWrapper, generateElementTypeFromYml, ActionStatus.DATA_TYPE_ALREADY_EXIST,
- NodeTypeEnum.DataType.name());
+ NodeTypeEnum.DataType.name());
}
// group types
private void createGroupTypes(Wrapper<Response> responseWrapper, ToscaTypeImportData toscaTypeImportData, String modelName,
final boolean includeToModelDefaultImports) {
final Supplier<Either<List<ImmutablePair<GroupTypeDefinition, Boolean>>, ResponseFormat>> generateElementTypeFromYml = () ->
- groupTypeImportManager.createGroupTypes(toscaTypeImportData, modelName, includeToModelDefaultImports);
+ groupTypeImportManager.createGroupTypes(toscaTypeImportData, modelName, includeToModelDefaultImports);
buildStatusForElementTypeCreate(responseWrapper, generateElementTypeFromYml, ActionStatus.GROUP_TYPE_ALREADY_EXIST,
- NodeTypeEnum.GroupType.name());
+ NodeTypeEnum.GroupType.name());
}
// policy types
private void createPolicyTypes(Wrapper<Response> responseWrapper, ToscaTypeImportData toscaTypeImportData, String modelName,
final boolean includeToModelDefaultImports) {
final Supplier<Either<List<ImmutablePair<PolicyTypeDefinition, Boolean>>, ResponseFormat>> generateElementTypeFromYml = () ->
- policyTypeImportManager.createPolicyTypes(toscaTypeImportData, modelName, includeToModelDefaultImports);
+ policyTypeImportManager.createPolicyTypes(toscaTypeImportData, modelName, includeToModelDefaultImports);
buildStatusForElementTypeCreate(responseWrapper, generateElementTypeFromYml, ActionStatus.POLICY_TYPE_ALREADY_EXIST,
- NodeTypeEnum.PolicyType.name());
+ NodeTypeEnum.PolicyType.name());
}
// data types
@@ -475,7 +508,7 @@ public class TypesUploadServlet extends AbstractValidationsServlet {
// Group result by the right value - true or false.
// I.e., get the number of data types which are new and which are old.
final Map<Boolean, List<ImmutablePair<T, Boolean>>> collect =
- list.stream().collect(Collectors.groupingBy(ImmutablePair<T, Boolean>::getRight));
+ list.stream().collect(Collectors.groupingBy(ImmutablePair<T, Boolean>::getRight));
if (collect != null) {
Set<Boolean> keySet = collect.keySet();
if (keySet.size() == 1) {
@@ -506,8 +539,8 @@ public class TypesUploadServlet extends AbstractValidationsServlet {
final String modelName,
final boolean includeToModelDefaultImports) {
final Supplier<Either<List<ImmutablePair<RelationshipTypeDefinition, Boolean>>, ResponseFormat>> generateElementTypeFromYml = () -> relationshipTypeImportManager
- .createRelationshipTypes(relationshipTypesYml, modelName, includeToModelDefaultImports);
+ .createRelationshipTypes(relationshipTypesYml, modelName, includeToModelDefaultImports);
buildStatusForElementTypeCreate(responseWrapper, generateElementTypeFromYml, ActionStatus.RELATIONSHIP_TYPE_ALREADY_EXIST,
- NodeTypeEnum.RelationshipType.name());
+ NodeTypeEnum.RelationshipType.name());
}
}
diff --git a/catalog-be/src/main/resources/config/error-configuration.yaml b/catalog-be/src/main/resources/config/error-configuration.yaml
index 7589511f54..d77f98ed28 100644
--- a/catalog-be/src/main/resources/config/error-configuration.yaml
+++ b/catalog-be/src/main/resources/config/error-configuration.yaml
@@ -2886,4 +2886,12 @@ errors:
code: 409,
message: "System deployed %1 cannot be archived. Component: '%2'",
messageId: "SVC4018"
- } \ No newline at end of file
+ }
+
+ #---------SVC4010-----------------------------
+ # %1 - error's list
+ YAML_IS_INVALID: {
+ code: 402,
+ message: "Error: Uploaded YAML file is invalid.\n%1",
+ messageId: "SVC4010"
+ }
diff --git a/catalog-be/src/main/resources/validateYaml/schema.json b/catalog-be/src/main/resources/validateYaml/schema.json
new file mode 100644
index 0000000000..df43dc4fe3
--- /dev/null
+++ b/catalog-be/src/main/resources/validateYaml/schema.json
@@ -0,0 +1,121 @@
+{
+ "$schema": "https://json-schema.org/draft/2019-09/schema",
+ "$id": "http://example.com/example.json",
+ "title": "Root Schema",
+ "type": "object",
+ "default": {},
+ "properties": {
+ "tosca_definitions_version": {
+ "title": "The tosca_definitions_version Schema",
+ "type": "string",
+ "default": ""
+ },
+ "data_types": {
+ "title": "The data_types Schema",
+ "type": "object",
+ "default": {},
+ "required": [],
+ "additionalProperties": {
+ "title": "The additionalProperties Schema",
+ "type": "object",
+ "default": {},
+ "required": [
+ "derived_from",
+ "properties"
+ ],
+ "properties": {
+ "derived_from": {
+ "title": "The derived_from Schema",
+ "type": "string",
+ "default": ""
+ },
+ "properties": {
+ "title": "The properties Schema",
+ "type": "object",
+ "default": {},
+ "required": [],
+ "additionalProperties": {
+ "title": "The additionalProperties Schema",
+ "type": "object",
+ "default": {},
+ "required": [
+ "type"
+ ],
+ "properties": {
+ "type": {
+ "title": "The type Schema",
+ "type": "string",
+ "default": ""
+ },
+ "description": {
+ "title": "The description Schema",
+ "type": "string",
+ "default": ""
+ },
+ "default": {
+ "title": "The default Schema",
+ "type": [
+ "string",
+ "integer",
+ "boolean",
+ "number"
+ ],
+ "default": ""
+ },
+ "required": {
+ "title": "The required Schema",
+ "type": "boolean",
+ "default": false
+ },
+ "status": {
+ "title": "The status Schema",
+ "type": "string",
+ "default": ""
+ },
+ "constraints": {
+ "title": "The constraints Schema",
+ "type": [
+ "array"
+ ],
+ "default": {}
+ },
+ "entry_schema": {
+ "title": "The entry_schema Schema",
+ "type": "object",
+ "default": {},
+ "properties": {
+ "type": {
+ "title": "The type Schema",
+ "type": [
+ "string",
+ "integer",
+ "boolean",
+ "number"
+ ],
+ "default": ""
+ }
+ }
+ }
+ },
+ "if": {
+ "properties": {
+ "type": {
+ "enum": [
+ "map",
+ "list"
+ ]
+ }
+ }
+ },
+ "then": {
+ "required": [
+ "entry_schema"
+ ]
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}