summaryrefslogtreecommitdiffstats
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
parent6d4057b032a30daa8388f9f1a323eae1581eb91c (diff)
Implement YAML Validator
Signed-off-by: Vasyl Razinkov <vasyl.razinkov@est.tech> Change-Id: I0365d4160984e4d68906959fb801ec7da5449b77 Issue-ID: SDC-4537
-rw-r--r--asdctool/src/main/resources/config/error-configuration.yaml16
-rw-r--r--catalog-be/pom.xml20
-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
-rw-r--r--catalog-be/src/test/java/org/openecomp/sdc/be/tosca/SchemaFiles.java76
-rw-r--r--catalog-be/src/test/java/org/openecomp/sdc/be/tosca/SchemaFilesTest.java131
-rw-r--r--catalog-be/src/test/resources/config/catalog-be/error-configuration.yaml10
-rw-r--r--catalog-be/src/test/resources/yamlValidation/noValid/data_types_no-valid-001.yaml1
-rw-r--r--catalog-be/src/test/resources/yamlValidation/noValid/data_types_no-valid-002.yaml1
-rw-r--r--catalog-be/src/test/resources/yamlValidation/noValid/data_types_no-valid-003.yaml2
-rw-r--r--catalog-be/src/test/resources/yamlValidation/noValid/data_types_no-valid-004.yaml3
-rw-r--r--catalog-be/src/test/resources/yamlValidation/noValid/data_types_no-valid-005.yaml4
-rw-r--r--catalog-be/src/test/resources/yamlValidation/noValid/data_types_no-valid-006.yaml4
-rw-r--r--catalog-be/src/test/resources/yamlValidation/noValid/data_types_no-valid-007.yaml5
-rw-r--r--catalog-be/src/test/resources/yamlValidation/noValid/data_types_no-valid-008.yaml6
-rw-r--r--catalog-be/src/test/resources/yamlValidation/noValid/data_types_no-valid-009.yaml7
-rw-r--r--catalog-be/src/test/resources/yamlValidation/noValid/data_types_no-valid-010.yaml7
-rw-r--r--catalog-be/src/test/resources/yamlValidation/noValid/data_types_no-valid-011.yaml9
-rw-r--r--catalog-be/src/test/resources/yamlValidation/noValid/data_types_no-valid-012.yaml14
-rw-r--r--catalog-be/src/test/resources/yamlValidation/noValid/data_types_no-valid-013.yaml20
-rw-r--r--catalog-be/src/test/resources/yamlValidation/noValid/data_types_valid-01.yaml85
-rw-r--r--catalog-be/src/test/resources/yamlValidation/noValid/data_types_valid-02.yaml84
-rw-r--r--catalog-be/src/test/resources/yamlValidation/noValid/data_types_valid-03.yaml83
-rw-r--r--catalog-be/src/test/resources/yamlValidation/noValid/schema.json121
-rw-r--r--catalog-dao/src/main/java/org/openecomp/sdc/be/dao/api/ActionStatus.java2
-rw-r--r--catalog-ui/src/app/utils/service-data-type-reader.ts11
28 files changed, 888 insertions, 182 deletions
diff --git a/asdctool/src/main/resources/config/error-configuration.yaml b/asdctool/src/main/resources/config/error-configuration.yaml
index e8f100da3f..0ac4369aa2 100644
--- a/asdctool/src/main/resources/config/error-configuration.yaml
+++ b/asdctool/src/main/resources/config/error-configuration.yaml
@@ -2874,7 +2874,15 @@ errors:
# %1 - componentType
# %2 - component id
CANNOT_ARCHIVE_SYSTEM_DEPLOYED_RESOURCES: {
- code: 409,
- message: "System deployed %1 cannot be archived. Component: '%2'",
- messageId: "SVC4018"
- } \ No newline at end of file
+ code: 409,
+ message: "System deployed %1 cannot be archived. Component: '%2'",
+ messageId: "SVC4018"
+ }
+
+ #---------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/pom.xml b/catalog-be/pom.xml
index 5dc9423def..54d6ce2f6a 100644
--- a/catalog-be/pom.xml
+++ b/catalog-be/pom.xml
@@ -22,6 +22,7 @@
</properties>
<dependencies>
+
<dependency>
<groupId>org.openecomp.sdc</groupId>
<artifactId>togglz-rest-services</artifactId>
@@ -42,6 +43,11 @@
<!--JSON and YAML Parsing-->
<dependency>
+ <groupId>com.networknt</groupId>
+ <artifactId>json-schema-validator</artifactId>
+ <version>1.0.84</version>
+ </dependency>
+ <dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>${jackson.version}</version>
@@ -57,7 +63,6 @@
</exclusion>
</exclusions>
</dependency>
-
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
@@ -220,11 +225,11 @@
</exclusions>
</dependency>
- <dependency>
- <groupId>io.micrometer</groupId>
- <artifactId>micrometer-registry-prometheus</artifactId>
- <version>${micrometer.version}</version>
- </dependency>
+ <dependency>
+ <groupId>io.micrometer</groupId>
+ <artifactId>micrometer-registry-prometheus</artifactId>
+ <version>${micrometer.version}</version>
+ </dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
@@ -1183,6 +1188,9 @@
<exclude>
src/test/resources/artifacts/pnfSoftwareInformation/**
</exclude>
+ <exclude>
+ src/test/resources/yamlValidation/noValid/**
+ </exclude>
</excludes>
</validationSet>
<validationSet>
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"
+ ]
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/tosca/SchemaFiles.java b/catalog-be/src/test/java/org/openecomp/sdc/be/tosca/SchemaFiles.java
deleted file mode 100644
index 839095f1ca..0000000000
--- a/catalog-be/src/test/java/org/openecomp/sdc/be/tosca/SchemaFiles.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
- */
-
-package org.openecomp.sdc.be.tosca;
-
-import org.junit.Test;
-import org.yaml.snakeyaml.Yaml;
-
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.util.List;
-import java.util.stream.Collectors;
-
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-
-public class SchemaFiles {
-
- @Test
- public void testValidateYamlNormativeFiles(){
- String importToscaPath = "src/main/resources/import/tosca";
- assertTrue(checkValidYamlInFileTree(importToscaPath));
- }
-
- @Test
- public void testRainyYamlNormativeFiles(){
- String importToscaPathTest = "src/test/resources/yamlValidation";
- assertFalse(checkValidYamlInFileTree(importToscaPathTest));
- }
-
- private boolean checkValidYamlInFileTree(String fileTree) {
-
- try {
- List<Path> fileTreeYamlList = Files.walk(Paths.get(fileTree))
- .filter(path -> path.getFileName().toString().toLowerCase().endsWith(".yml"))
- .collect(Collectors.toList());
-
- for (Path yamlFile : fileTreeYamlList) {
- try {
- FileInputStream inputStream = new FileInputStream(yamlFile.toAbsolutePath().toString());
- Yaml yaml = new Yaml();
- Object content = yaml.load(inputStream);
- } catch (Exception e) {
- System.out.println("Not valid yaml in file creation : " + yamlFile.toAbsolutePath().toString());
- return false;
- }
- }
- } catch (IOException e) {
- System.out.println("Error in reading file from folder : " + fileTree);
- return false;
- }
- return true;
- }
-
-
-}
diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/tosca/SchemaFilesTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/tosca/SchemaFilesTest.java
new file mode 100644
index 0000000000..ddcf649c22
--- /dev/null
+++ b/catalog-be/src/test/java/org/openecomp/sdc/be/tosca/SchemaFilesTest.java
@@ -0,0 +1,131 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.sdc.be.tosca;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.fail;
+
+import com.fasterxml.jackson.core.JsonParseException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
+import com.networknt.schema.JsonSchemaFactory;
+import com.networknt.schema.SpecVersion;
+import com.networknt.schema.ValidationMessage;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.stream.Stream;
+import org.junit.jupiter.api.Test;
+import org.openecomp.sdc.be.test.util.TestResourcesHandler;
+import org.yaml.snakeyaml.Yaml;
+import org.yaml.snakeyaml.parser.ParserException;
+import org.yaml.snakeyaml.scanner.ScannerException;
+
+class SchemaFilesTest {
+
+ @Test
+ void testValidateYamlNormativeFiles() {
+ String importToscaPath = "src/main/resources/import/tosca";
+ assertTrue(checkValidYamlInFileTree(importToscaPath));
+ }
+
+ @Test
+ void testRainyYamlNormativeFiles() {
+ String importToscaPathTest = "src/test/resources/yamlValidation";
+ assertFalse(checkValidYamlInFileTree(importToscaPathTest));
+ }
+
+ private boolean checkValidYamlInFileTree(final String fileTree) {
+ AtomicBoolean ret = new AtomicBoolean(true);
+ try (final Stream<Path> pathStream = Files.walk(Paths.get(fileTree))) {
+ pathStream
+ .filter(path -> path.getFileName().toString().toLowerCase().endsWith(".yml"))
+ .forEach(yamlFile -> {
+ try {
+ new Yaml().load(new FileInputStream(yamlFile.toAbsolutePath().toString()));
+ } catch (final Exception e) {
+ System.out.println("Not valid yaml in file creation : " + yamlFile.toAbsolutePath());
+ ret.set(false);
+ }
+ });
+ } catch (final IOException e) {
+ System.out.println("Error in reading file from folder : " + fileTree);
+ return false;
+ }
+ return ret.get();
+ }
+
+ @Test
+ void yamlValidation_test_no_valid() {
+ final ObjectMapper mapper = new ObjectMapper(new YAMLFactory());
+ final JsonSchemaFactory factory =
+ JsonSchemaFactory.builder(JsonSchemaFactory.getInstance(SpecVersion.VersionFlag.V202012)).objectMapper(mapper).build();
+
+ try (final Stream<Path> pathStream = Files.walk(Paths.get("src/test/resources/yamlValidation"))) {
+ pathStream
+ .filter(path -> path.getFileName().toString().toLowerCase().startsWith("data_types_no-valid-"))
+ .forEach(path -> {
+ try (final InputStream schemaFile = TestResourcesHandler.getResourceAsStream("yamlValidation/noValid/" + "schema.json");
+ final InputStream yamlFile = TestResourcesHandler.getResourceAsStream("yamlValidation/noValid/" + path.getFileName())) {
+ final Set<ValidationMessage> validationMessages = factory.getSchema(schemaFile).validate(mapper.readTree(yamlFile));
+ validationMessages.forEach(System.out::println);
+ assertFalse(validationMessages.isEmpty());
+ } catch (JsonParseException e) {
+ assertTrue(e.getCause() instanceof ParserException || e.getCause() instanceof ScannerException);
+ } catch (IOException e) {
+ fail(e.getMessage());
+ }
+ });
+ } catch (final IOException e) {
+ fail(e.getMessage());
+ }
+ }
+ @Test
+ void yamlValidation_test_valid() {
+ final ObjectMapper mapper = new ObjectMapper(new YAMLFactory());
+ final JsonSchemaFactory factory =
+ JsonSchemaFactory.builder(JsonSchemaFactory.getInstance(SpecVersion.VersionFlag.V202012)).objectMapper(mapper).build();
+
+ try (final Stream<Path> pathStream = Files.walk(Paths.get("src/test/resources/yamlValidation"))) {
+ pathStream
+ .filter(path -> path.getFileName().toString().toLowerCase().startsWith("data_types_valid-"))
+ .forEach(path -> {
+ try (final InputStream schemaFile = TestResourcesHandler.getResourceAsStream("yamlValidation/noValid/" + "schema.json");
+ final InputStream yamlFile = TestResourcesHandler.getResourceAsStream("yamlValidation/noValid/" + path.getFileName())) {
+ final Set<ValidationMessage> validationMessages = factory.getSchema(schemaFile).validate(mapper.readTree(yamlFile));
+ validationMessages.forEach(System.out::println);
+ assertTrue(validationMessages.isEmpty());
+ } catch (IOException e) {
+ fail(e.getMessage());
+ }
+ });
+ } catch (final IOException e) {
+ fail(e.getMessage());
+ }
+ }
+
+}
diff --git a/catalog-be/src/test/resources/config/catalog-be/error-configuration.yaml b/catalog-be/src/test/resources/config/catalog-be/error-configuration.yaml
index 6911570d16..0937c1d58e 100644
--- a/catalog-be/src/test/resources/config/catalog-be/error-configuration.yaml
+++ b/catalog-be/src/test/resources/config/catalog-be/error-configuration.yaml
@@ -2872,4 +2872,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/test/resources/yamlValidation/noValid/data_types_no-valid-001.yaml b/catalog-be/src/test/resources/yamlValidation/noValid/data_types_no-valid-001.yaml
new file mode 100644
index 0000000000..ca05128ddd
--- /dev/null
+++ b/catalog-be/src/test/resources/yamlValidation/noValid/data_types_no-valid-001.yaml
@@ -0,0 +1 @@
+tosca_definitions_version:
diff --git a/catalog-be/src/test/resources/yamlValidation/noValid/data_types_no-valid-002.yaml b/catalog-be/src/test/resources/yamlValidation/noValid/data_types_no-valid-002.yaml
new file mode 100644
index 0000000000..ca05128ddd
--- /dev/null
+++ b/catalog-be/src/test/resources/yamlValidation/noValid/data_types_no-valid-002.yaml
@@ -0,0 +1 @@
+tosca_definitions_version:
diff --git a/catalog-be/src/test/resources/yamlValidation/noValid/data_types_no-valid-003.yaml b/catalog-be/src/test/resources/yamlValidation/noValid/data_types_no-valid-003.yaml
new file mode 100644
index 0000000000..85683a0e63
--- /dev/null
+++ b/catalog-be/src/test/resources/yamlValidation/noValid/data_types_no-valid-003.yaml
@@ -0,0 +1,2 @@
+tosca_definitions_version: tosca_simple_yaml_1_2
+data_types:
diff --git a/catalog-be/src/test/resources/yamlValidation/noValid/data_types_no-valid-004.yaml b/catalog-be/src/test/resources/yamlValidation/noValid/data_types_no-valid-004.yaml
new file mode 100644
index 0000000000..ae209d17da
--- /dev/null
+++ b/catalog-be/src/test/resources/yamlValidation/noValid/data_types_no-valid-004.yaml
@@ -0,0 +1,3 @@
+tosca_definitions_version: tosca_simple_yaml_1_2
+data_types:
+ datatype_test:
diff --git a/catalog-be/src/test/resources/yamlValidation/noValid/data_types_no-valid-005.yaml b/catalog-be/src/test/resources/yamlValidation/noValid/data_types_no-valid-005.yaml
new file mode 100644
index 0000000000..00d452c440
--- /dev/null
+++ b/catalog-be/src/test/resources/yamlValidation/noValid/data_types_no-valid-005.yaml
@@ -0,0 +1,4 @@
+tosca_definitions_version: tosca_simple_yaml_1_2
+data_types:
+ datatype_test:
+ derived_from:
diff --git a/catalog-be/src/test/resources/yamlValidation/noValid/data_types_no-valid-006.yaml b/catalog-be/src/test/resources/yamlValidation/noValid/data_types_no-valid-006.yaml
new file mode 100644
index 0000000000..74e2c8a114
--- /dev/null
+++ b/catalog-be/src/test/resources/yamlValidation/noValid/data_types_no-valid-006.yaml
@@ -0,0 +1,4 @@
+tosca_definitions_version: tosca_simple_yaml_1_2
+data_types:
+ datatype_test:
+ derived_from: tosca.datatypes.Root
diff --git a/catalog-be/src/test/resources/yamlValidation/noValid/data_types_no-valid-007.yaml b/catalog-be/src/test/resources/yamlValidation/noValid/data_types_no-valid-007.yaml
new file mode 100644
index 0000000000..6eb68d05d8
--- /dev/null
+++ b/catalog-be/src/test/resources/yamlValidation/noValid/data_types_no-valid-007.yaml
@@ -0,0 +1,5 @@
+tosca_definitions_version: tosca_simple_yaml_1_2
+data_types:
+ datatype_test:
+ derived_from: tosca.datatypes.Root
+ properties:
diff --git a/catalog-be/src/test/resources/yamlValidation/noValid/data_types_no-valid-008.yaml b/catalog-be/src/test/resources/yamlValidation/noValid/data_types_no-valid-008.yaml
new file mode 100644
index 0000000000..21b54453b2
--- /dev/null
+++ b/catalog-be/src/test/resources/yamlValidation/noValid/data_types_no-valid-008.yaml
@@ -0,0 +1,6 @@
+tosca_definitions_version: tosca_simple_yaml_1_2
+data_types:
+ datatype_test:
+ derived_from: tosca.datatypes.Root
+ properties:
+ pr_2:
diff --git a/catalog-be/src/test/resources/yamlValidation/noValid/data_types_no-valid-009.yaml b/catalog-be/src/test/resources/yamlValidation/noValid/data_types_no-valid-009.yaml
new file mode 100644
index 0000000000..00073a3cac
--- /dev/null
+++ b/catalog-be/src/test/resources/yamlValidation/noValid/data_types_no-valid-009.yaml
@@ -0,0 +1,7 @@
+tosca_definitions_version: tosca_simple_yaml_1_2
+data_types:
+ datatype_test:
+ derived_from: tosca.datatypes.Root
+ properties:
+ pr_2:
+ type:
diff --git a/catalog-be/src/test/resources/yamlValidation/noValid/data_types_no-valid-010.yaml b/catalog-be/src/test/resources/yamlValidation/noValid/data_types_no-valid-010.yaml
new file mode 100644
index 0000000000..2ccb8dd3fa
--- /dev/null
+++ b/catalog-be/src/test/resources/yamlValidation/noValid/data_types_no-valid-010.yaml
@@ -0,0 +1,7 @@
+tosca_definitions_version: tosca_simple_yaml_1_2
+data_types:
+ datatype_test:
+ derived_from: tosca.datatypes.Root
+ properties:
+ pr_2:
+ type: map
diff --git a/catalog-be/src/test/resources/yamlValidation/noValid/data_types_no-valid-011.yaml b/catalog-be/src/test/resources/yamlValidation/noValid/data_types_no-valid-011.yaml
new file mode 100644
index 0000000000..d7e219726f
--- /dev/null
+++ b/catalog-be/src/test/resources/yamlValidation/noValid/data_types_no-valid-011.yaml
@@ -0,0 +1,9 @@
+tosca_definitions_version: tosca_simple_yaml_1_2
+data_types:
+ datatype_test:
+ derived_from: tosca.datatypes.Root
+ properties:
+ pr_2:
+ type: map
+ entry_schema:
+ type:
diff --git a/catalog-be/src/test/resources/yamlValidation/noValid/data_types_no-valid-012.yaml b/catalog-be/src/test/resources/yamlValidation/noValid/data_types_no-valid-012.yaml
new file mode 100644
index 0000000000..8e9ade8473
--- /dev/null
+++ b/catalog-be/src/test/resources/yamlValidation/noValid/data_types_no-valid-012.yaml
@@ -0,0 +1,14 @@
+tosca_definitions_version: tosca_simple_yaml_1_2
+data_types:
+ datatype_test:
+ derived_from: tosca.datatypes.Root
+ properties:
+ pr_2:
+ type: map
+ entry_schema:
+ type: boolean
+ descriptor_id:
+ type: string
+ description: Globally unique identifier of the VNFD
+ required: true
+ constraints:
diff --git a/catalog-be/src/test/resources/yamlValidation/noValid/data_types_no-valid-013.yaml b/catalog-be/src/test/resources/yamlValidation/noValid/data_types_no-valid-013.yaml
new file mode 100644
index 0000000000..bfc5f2a48f
--- /dev/null
+++ b/catalog-be/src/test/resources/yamlValidation/noValid/data_types_no-valid-013.yaml
@@ -0,0 +1,20 @@
+tosca_definitions_version: tosca_simple_yaml_1_2
+data_types:
+ datatype_test:
+ derived_from: tosca.datatypes.Root
+ properties:
+ pr_1:
+ type: list
+ entry_schema:
+ type: boolean
+ default: [
+ pr_2:
+ type: map
+ entry_schema:
+ type: boolean
+ default: }
+ descriptor_id:
+ type: string
+ description: Globally unique identifier of the VNFD
+ default: 'Missing quote
+ required: true
diff --git a/catalog-be/src/test/resources/yamlValidation/noValid/data_types_valid-01.yaml b/catalog-be/src/test/resources/yamlValidation/noValid/data_types_valid-01.yaml
new file mode 100644
index 0000000000..991477ccbd
--- /dev/null
+++ b/catalog-be/src/test/resources/yamlValidation/noValid/data_types_valid-01.yaml
@@ -0,0 +1,85 @@
+tosca_definitions_version: tosca_simple_yaml_1_2
+data_types:
+ datatype_test:
+ derived_from: tosca.datatypes.Root
+ properties:
+ pr_1:
+ type: map
+ entry_schema:
+ type: boolean
+ pr_2:
+ type: string
+ description: Globally unique identifier of the VNFD
+ required: true
+ constraints:
+ - equal: fgh
+ pr_3:
+ type: string
+ description: Globally unique identifier of the VNFD
+ required: true
+ constraints:
+ - greater_than: a
+ pr_4:
+ type: string
+ description: Globally unique identifier of the VNFD
+ required: true
+ constraints:
+ - greater_or_equal: b
+ pr_5:
+ type: string
+ description: Globally unique identifier of the VNFD
+ required: true
+ constraints:
+ - less_than: z
+ pr_6:
+ type: string
+ description: Globally unique identifier of the VNFD
+ required: true
+ constraints:
+ - less_or_equal: y
+ pr_7:
+ type: string
+ description: Globally unique identifier of the VNFD
+ required: true
+ constraints:
+ - in_range:
+ - bb
+ - yy
+ pr_8:
+ type: string
+ description: Globally unique identifier of the VNFD
+ required: true
+ constraints:
+ - valid_values:
+ - dd
+ - rr
+ pr_9:
+ type: string
+ description: Globally unique identifier of the VNFD
+ required: true
+ constraints:
+ - length: 3
+ pr_10:
+ type: string
+ description: Globally unique identifier of the VNFD
+ required: true
+ constraints:
+ - min_length: 3
+ pr_11:
+ type: string
+ description: Globally unique identifier of the VNFD
+ required: true
+ constraints:
+ - min_length: 3
+ pr_12:
+ type: string
+ description: Globally unique identifier of the VNFD
+ required: true
+ constraints:
+ - max_length: 3
+ pr_13:
+ type: string
+ description: Globally unique identifier of the VNFD
+ required: true
+ constraints:
+ - pattern: '[a-z]'
diff --git a/catalog-be/src/test/resources/yamlValidation/noValid/data_types_valid-02.yaml b/catalog-be/src/test/resources/yamlValidation/noValid/data_types_valid-02.yaml
new file mode 100644
index 0000000000..d4ba271134
--- /dev/null
+++ b/catalog-be/src/test/resources/yamlValidation/noValid/data_types_valid-02.yaml
@@ -0,0 +1,84 @@
+data_types:
+ datatype_test:
+ derived_from: tosca.datatypes.Root
+ properties:
+ pr_1:
+ type: map
+ entry_schema:
+ type: boolean
+ pr_2:
+ type: string
+ description: Globally unique identifier of the VNFD
+ required: true
+ constraints:
+ - equal: fgh
+ pr_3:
+ type: string
+ description: Globally unique identifier of the VNFD
+ required: true
+ constraints:
+ - greater_than: a
+ pr_4:
+ type: string
+ description: Globally unique identifier of the VNFD
+ required: true
+ constraints:
+ - greater_or_equal: b
+ pr_5:
+ type: string
+ description: Globally unique identifier of the VNFD
+ required: true
+ constraints:
+ - less_than: z
+ pr_6:
+ type: string
+ description: Globally unique identifier of the VNFD
+ required: true
+ constraints:
+ - less_or_equal: y
+ pr_7:
+ type: string
+ description: Globally unique identifier of the VNFD
+ required: true
+ constraints:
+ - in_range:
+ - bb
+ - yy
+ pr_8:
+ type: string
+ description: Globally unique identifier of the VNFD
+ required: true
+ constraints:
+ - valid_values:
+ - dd
+ - rr
+ pr_9:
+ type: string
+ description: Globally unique identifier of the VNFD
+ required: true
+ constraints:
+ - length: 3
+ pr_10:
+ type: string
+ description: Globally unique identifier of the VNFD
+ required: true
+ constraints:
+ - min_length: 3
+ pr_11:
+ type: string
+ description: Globally unique identifier of the VNFD
+ required: true
+ constraints:
+ - min_length: 3
+ pr_12:
+ type: string
+ description: Globally unique identifier of the VNFD
+ required: true
+ constraints:
+ - max_length: 3
+ pr_13:
+ type: string
+ description: Globally unique identifier of the VNFD
+ required: true
+ constraints:
+ - pattern: '[a-z]'
diff --git a/catalog-be/src/test/resources/yamlValidation/noValid/data_types_valid-03.yaml b/catalog-be/src/test/resources/yamlValidation/noValid/data_types_valid-03.yaml
new file mode 100644
index 0000000000..a15f36899f
--- /dev/null
+++ b/catalog-be/src/test/resources/yamlValidation/noValid/data_types_valid-03.yaml
@@ -0,0 +1,83 @@
+datatype_test:
+ derived_from: tosca.datatypes.Root
+ properties:
+ pr_1:
+ type: map
+ entry_schema:
+ type: boolean
+ pr_2:
+ type: string
+ description: Globally unique identifier of the VNFD
+ required: true
+ constraints:
+ - equal: fgh
+ pr_3:
+ type: string
+ description: Globally unique identifier of the VNFD
+ required: true
+ constraints:
+ - greater_than: a
+ pr_4:
+ type: string
+ description: Globally unique identifier of the VNFD
+ required: true
+ constraints:
+ - greater_or_equal: b
+ pr_5:
+ type: string
+ description: Globally unique identifier of the VNFD
+ required: true
+ constraints:
+ - less_than: z
+ pr_6:
+ type: string
+ description: Globally unique identifier of the VNFD
+ required: true
+ constraints:
+ - less_or_equal: y
+ pr_7:
+ type: string
+ description: Globally unique identifier of the VNFD
+ required: true
+ constraints:
+ - in_range:
+ - bb
+ - yy
+ pr_8:
+ type: string
+ description: Globally unique identifier of the VNFD
+ required: true
+ constraints:
+ - valid_values:
+ - dd
+ - rr
+ pr_9:
+ type: string
+ description: Globally unique identifier of the VNFD
+ required: true
+ constraints:
+ - length: 3
+ pr_10:
+ type: string
+ description: Globally unique identifier of the VNFD
+ required: true
+ constraints:
+ - min_length: 3
+ pr_11:
+ type: string
+ description: Globally unique identifier of the VNFD
+ required: true
+ constraints:
+ - min_length: 3
+ pr_12:
+ type: string
+ description: Globally unique identifier of the VNFD
+ required: true
+ constraints:
+ - max_length: 3
+ pr_13:
+ type: string
+ description: Globally unique identifier of the VNFD
+ required: true
+ constraints:
+ - pattern: '[a-z]'
diff --git a/catalog-be/src/test/resources/yamlValidation/noValid/schema.json b/catalog-be/src/test/resources/yamlValidation/noValid/schema.json
new file mode 100644
index 0000000000..df43dc4fe3
--- /dev/null
+++ b/catalog-be/src/test/resources/yamlValidation/noValid/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"
+ ]
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/api/ActionStatus.java b/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/api/ActionStatus.java
index 352f09e138..5434f1ffb7 100644
--- a/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/api/ActionStatus.java
+++ b/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/api/ActionStatus.java
@@ -75,7 +75,7 @@ public enum ActionStatus {
EMPTY_OCCURRENCES_LIST, INVALID_OCCURRENCES, NOT_TOPOLOGY_TOSCA_TEMPLATE, INVALID_NODE_TEMPLATE,
// Data type related
DATA_TYPE_ALREADY_EXIST, DATA_TYPE_NOR_PROPERTIES_NEITHER_DERIVED_FROM, DATA_TYPE_PROPERTIES_CANNOT_BE_EMPTY, DATA_TYPE_DERIVED_IS_MISSING, DATA_TYPE_PROPERTY_ALREADY_DEFINED_IN_ANCESTOR, DATA_TYPE_DUPLICATE_PROPERTY, DATA_TYPE_PROEPRTY_CANNOT_HAVE_SAME_TYPE_OF_DATA_TYPE, DATA_TYPE_CANNOT_HAVE_PROPERTIES, DATA_TYPE_CANNOT_BE_EMPTY, DATA_TYPE_CANNOT_BE_UPDATED_BAD_REQUEST,
- DATA_TYPES_NOT_LOADED, DATA_TYPE_NOT_FOUND, DATA_TYPE_PROPERTIES_NOT_FOUND,
+ DATA_TYPES_NOT_LOADED, DATA_TYPE_NOT_FOUND, DATA_TYPE_PROPERTIES_NOT_FOUND, YAML_IS_INVALID,
// Policy Type related
TARGETS_EMPTY, TARGETS_NON_VALID, POLICY_TYPE_ALREADY_EXIST,
// Group Type related
diff --git a/catalog-ui/src/app/utils/service-data-type-reader.ts b/catalog-ui/src/app/utils/service-data-type-reader.ts
index 9686f3d40e..dbb550894a 100644
--- a/catalog-ui/src/app/utils/service-data-type-reader.ts
+++ b/catalog-ui/src/app/utils/service-data-type-reader.ts
@@ -35,10 +35,11 @@ export class ServiceDataTypeReader {
const result = <String>reader.result;
const loadedContent = load(result);
console.log("Readed content: " + loadedContent);
- this.readName(this.getDataType(loadedContent));
- this.readDerivedFrom(this.getDataType(loadedContent));
- this.readDescription(this.getDataType(loadedContent));
- this.readProperties(this.getDataType(loadedContent));
+ const dataType = this.getDataType(loadedContent);
+ this.readName(dataType);
+ this.readDerivedFrom(dataType);
+ this.readDescription(dataType);
+ this.readProperties(dataType);
resolve(this.serviceDataType);
} catch (error) {
reject(error);
@@ -201,4 +202,4 @@ export class ServiceDataTypeReader {
value:constraintValue
}
}
-} \ No newline at end of file
+}