aboutsummaryrefslogtreecommitdiffstats
path: root/catalog-be
diff options
context:
space:
mode:
authorKrupaNagabhushan <krupa.nagabhushan@est.tech>2020-11-19 14:28:00 +0000
committerChristophe Closset <christophe.closset@intl.att.com>2021-01-14 13:56:39 +0000
commit3849231a17930b1bb2ba09af15673bfd07538b9d (patch)
tree9ca26d4457093bbb30924d6731b5615e795ed238 /catalog-be
parent0d38c9a8ed4701b860901f67049920e9b1ca72f2 (diff)
Create inputs independent of properties
Issue-ID: SDC-3431 Signed-off-by: KrupaNagabhushan <krupa.nagabhushan@est.tech> Change-Id: I4f29d0e490a14292fd1aa9f96ca6621b37f325d8
Diffstat (limited to 'catalog-be')
-rw-r--r--catalog-be/src/main/docker/backend/chef-repo/cookbooks/sdc-catalog-be/files/default/error-configuration.yaml17
-rw-r--r--catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/InputsBusinessLogic.java110
-rw-r--r--catalog-be/src/main/java/org/openecomp/sdc/be/servlets/BeGenericServlet.java56
-rw-r--r--catalog-be/src/main/java/org/openecomp/sdc/be/servlets/InputsServlet.java62
4 files changed, 240 insertions, 5 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 4aa93cb268..ecaf852a16 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
@@ -2410,10 +2410,23 @@ errors:
message: 'Error: Invalid Content. %1 has invalid format.',
messageId: "SVC4723"
}
-#---------SVC4732------------------------------
+#---------SVC4734------------------------------
# %1 - list of validation errors
INVALID_PM_DICTIONARY_FILE: {
code: 400,
message: 'Error: Invalid PM Dictionary File. %1',
- messageId: "SVC4732"
+ messageId: "SVC4734"
+ }
+#-----------SVC4735---------------------------
+ #%1 - input name
+ INPUT_ALREADY_EXIST: {
+ code: 409,
+ message: "Error: Input with '%1' name already exists.",
+ messageId: "SVC4735"
+ }
+#---------SVC4736------------------------------
+ INVALID_INPUT_NAME: {
+ code: 400,
+ message: "Error: Input name contains invalid characters. It should have only letters, numbers and underscores.",
+ messageId: "SVC4736"
}
diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/InputsBusinessLogic.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/InputsBusinessLogic.java
index 69adb90493..5b197de183 100644
--- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/InputsBusinessLogic.java
+++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/InputsBusinessLogic.java
@@ -23,6 +23,7 @@
package org.openecomp.sdc.be.components.impl;
import fj.data.Either;
+import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections4.ListUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang.BooleanUtils;
@@ -33,6 +34,7 @@ import org.openecomp.sdc.be.components.impl.exceptions.ByResponseFormatComponent
import org.openecomp.sdc.be.components.impl.exceptions.ComponentException;
import org.openecomp.sdc.be.components.property.PropertyDeclarationOrchestrator;
import org.openecomp.sdc.be.components.validation.ComponentValidations;
+import org.openecomp.sdc.be.config.BeEcompErrorManager;
import org.openecomp.sdc.be.dao.api.ActionStatus;
import org.openecomp.sdc.be.dao.janusgraph.JanusGraphOperationStatus;
import org.openecomp.sdc.be.dao.utils.MapUtil;
@@ -40,7 +42,9 @@ import org.openecomp.sdc.be.datamodel.utils.PropertyValueConstraintValidationUti
import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition;
import org.openecomp.sdc.be.datatypes.elements.SchemaDefinition;
import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
+import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum;
import org.openecomp.sdc.be.datatypes.tosca.ToscaDataDefinition;
+import org.openecomp.sdc.be.model.Component;
import org.openecomp.sdc.be.model.ComponentInstInputsMap;
import org.openecomp.sdc.be.model.ComponentInstListInput;
import org.openecomp.sdc.be.model.ComponentInstance;
@@ -61,15 +65,16 @@ import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
import org.openecomp.sdc.be.model.operations.impl.DaoStatusConverter;
import org.openecomp.sdc.be.model.operations.impl.InterfaceLifecycleOperation;
import org.openecomp.sdc.be.model.operations.impl.UniqueIdBuilder;
+import org.openecomp.sdc.be.model.operations.utils.ComponentValidationUtils;
import org.openecomp.sdc.be.model.tosca.ToscaPropertyType;
import org.openecomp.sdc.be.model.tosca.converters.PropertyValueConverter;
+import org.openecomp.sdc.be.resources.data.EntryData;
import org.openecomp.sdc.common.log.elements.LoggerSupportability;
import org.openecomp.sdc.common.log.enums.LoggerSupportabilityActions;
import org.openecomp.sdc.common.log.enums.StatusCode;
import org.openecomp.sdc.common.log.wrappers.Logger;
import org.openecomp.sdc.exception.ResponseFormat;
import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.Arrays;
@@ -81,7 +86,7 @@ import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;
-@Component("inputsBusinessLogic")
+@org.springframework.stereotype.Component("inputsBusinessLogic")
public class InputsBusinessLogic extends BaseBusinessLogic {
private static final String CREATE_INPUT = "CreateInput";
@@ -874,4 +879,105 @@ public class InputsBusinessLogic extends BaseBusinessLogic {
}
+ public Either<EntryData<String, InputDefinition>, ResponseFormat> addInputToComponent(String componentId,
+ String inputName,
+ InputDefinition newInputDefinition,
+ String userId) {
+ Either<EntryData<String, InputDefinition>, ResponseFormat> result = null;
+
+ validateUserExists(userId);
+
+ Either<Component, StorageOperationStatus> serviceElement =
+ toscaOperationFacade.getToscaElement(componentId);
+ if (serviceElement.isRight()) {
+ result = Either.right(componentsUtils.getResponseFormat(ActionStatus.RESOURCE_NOT_FOUND, ""));
+ return result;
+ }
+
+ Component component = serviceElement.left().value();
+ NodeTypeEnum nodeType = component.getComponentType().getNodeType();
+
+ StorageOperationStatus lockResult = graphLockOperation.lockComponent(componentId, nodeType);
+ if (!lockResult.equals(StorageOperationStatus.OK)) {
+ BeEcompErrorManager.getInstance()
+ .logBeFailedLockObjectError(CREATE_INPUT, nodeType.name().toLowerCase(), componentId);
+ log.info("Failed to lock component {}. Error - {}", componentId, lockResult);
+ result = Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR));
+ return result;
+ }
+
+ try {
+ if (!ComponentValidationUtils.canWorkOnComponent(component, userId)) {
+ result = Either.right(componentsUtils.getResponseFormat(ActionStatus.RESTRICTED_OPERATION));
+ return result;
+ }
+
+ List<InputDefinition> inputs = component.getInputs();
+
+ if (CollectionUtils.isEmpty(inputs)) {
+ inputs = new ArrayList<>();
+ }
+
+ if (isInputExistInComponent(inputs, inputName)) {
+
+ result = Either.right(componentsUtils.getResponseFormat(ActionStatus
+ .INPUT_ALREADY_EXIST, inputName));
+ return result;
+ }
+
+ Map<String, DataTypeDefinition> allDataTypes = getAllDataTypes(applicationDataTypeCache);
+
+ // validate input default values
+ Either<Boolean, ResponseFormat> defaultValuesValidation = validatePropertyDefaultValue(
+ newInputDefinition, allDataTypes);
+ if (defaultValuesValidation.isRight()) {
+ result = Either.right(defaultValuesValidation.right().value());
+ return result;
+ }
+
+ // convert Input
+ ToscaPropertyType type = getType(newInputDefinition.getType());
+ if (type != null) {
+ PropertyValueConverter converter = type.getConverter();
+ // get inner type
+ String innerType = null;
+ SchemaDefinition schema = newInputDefinition.getSchema();
+ if (schema != null) {
+ PropertyDataDefinition prop = schema.getProperty();
+ if (prop != null) {
+ innerType = prop.getType();
+ }
+ }
+ if (newInputDefinition.getDefaultValue() != null) {
+ String convertedValue = converter
+ .convert(newInputDefinition.getDefaultValue(), innerType, allDataTypes);
+ newInputDefinition.setDefaultValue(convertedValue);
+ }
+ }
+
+ Either<InputDefinition, StorageOperationStatus> addInputEither =
+ toscaOperationFacade.addInputToComponent(inputName, newInputDefinition, component);
+
+ if (addInputEither.isRight()) {
+ log.info("Failed to add new input {}. Error - {}", componentId,
+ addInputEither.right().value());
+ result = Either.right(componentsUtils.getResponseFormat(ActionStatus
+ .GENERAL_ERROR));
+ return result;
+ }
+
+ result = Either.left(new EntryData<>(inputName, newInputDefinition));
+ return result;
+ } finally {
+ commitOrRollback(result);
+ // unlock component
+ graphLockOperation.unlockComponent(componentId, nodeType);
+ }
+ }
+
+ private boolean isInputExistInComponent(List<InputDefinition> inputs, String inputName) {
+ return CollectionUtils.isNotEmpty(inputs) &&
+ inputs.stream().anyMatch(input -> input.getName().equals(inputName));
+ }
+
}
diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/BeGenericServlet.java b/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/BeGenericServlet.java
index b497b702c3..1a8a305d2a 100644
--- a/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/BeGenericServlet.java
+++ b/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/BeGenericServlet.java
@@ -68,6 +68,7 @@ import org.openecomp.sdc.be.impl.WebAppContextWrapper;
import org.openecomp.sdc.be.model.ComponentInstInputsMap;
import org.openecomp.sdc.be.model.PropertyConstraint;
import org.openecomp.sdc.be.model.PropertyDefinition;
+import org.openecomp.sdc.be.model.InputDefinition;
import org.openecomp.sdc.be.model.User;
import org.openecomp.sdc.be.model.operations.impl.PropertyOperation;
import org.openecomp.sdc.be.model.operations.impl.PropertyOperation.PropertyConstraintJacksonDeserializer;
@@ -393,6 +394,19 @@ public class BeGenericServlet extends BasicServlet {
return Either.left(propertyDefinition);
}
+ private Either<InputDefinition, ActionStatus> getInputDefinitionFromJson(String componentId, String inputName, JSONObject value) {
+ String jsonString = value.toJSONString();
+ Either<InputDefinition, ActionStatus> convertJsonToObject = convertJsonToObject(jsonString, InputDefinition.class);
+ if (convertJsonToObject.isRight()) {
+ return Either.right(convertJsonToObject.right().value());
+ }
+ InputDefinition inputDefinition = convertJsonToObject.left().value();
+ String uniqueId = UniqueIdBuilder.buildPropertyUniqueId(componentId, inputName);
+ inputDefinition.setUniqueId(uniqueId);
+
+ return Either.left(inputDefinition);
+ }
+
protected Either<Map<String, PropertyDefinition>, ActionStatus> getPropertiesListForUpdate(String data) {
Map<String, PropertyDefinition> properties = new HashMap<>();
@@ -421,7 +435,6 @@ public class BeGenericServlet extends BasicServlet {
}
-
protected String propertyToJson(Map.Entry<String, PropertyDefinition> property) {
JSONObject root = new JSONObject();
String propertyName = property.getKey();
@@ -565,4 +578,45 @@ public class BeGenericServlet extends BasicServlet {
return getInputBL(context);
}
+
+ protected Either<Map<String, InputDefinition>, ActionStatus> getInputModel(String componentId, String data) {
+ JSONParser parser = new JSONParser();
+ JSONObject root;
+ try {
+ Map<String, InputDefinition> inputs = new HashMap<>();
+ root = (JSONObject) parser.parse(data);
+
+ Set entrySet = root.entrySet();
+ Iterator iterator = entrySet.iterator();
+ while (iterator.hasNext()) {
+ Entry next = (Entry) iterator.next();
+ String inputName = (String) next.getKey();
+
+ if(!isInputNameValid(inputName)) {
+ return Either.right(ActionStatus.INVALID_INPUT_NAME);
+ }
+
+ JSONObject value = (JSONObject) next.getValue();
+ Either<InputDefinition, ActionStatus> inputDefinitionEither =
+ getInputDefinitionFromJson(componentId, inputName, value);
+
+ if(inputDefinitionEither.isRight()) {
+ return Either.right(inputDefinitionEither.right().value());
+ }
+
+ inputs.put(inputName, inputDefinitionEither.left().value());
+ }
+
+ return Either.left(inputs);
+ } catch (ParseException e) {
+ log.warn("Input content is invalid - {}", data, e);
+ return Either.right(ActionStatus.INVALID_CONTENT);
+ }
+ }
+
+ protected boolean isInputNameValid(String inputName) {
+ return Objects.nonNull(inputName)
+ && inputName.matches(PROPERTY_NAME_REGEX);
+
+ }
}
diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/InputsServlet.java b/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/InputsServlet.java
index bff8436fa4..1f80b4be87 100644
--- a/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/InputsServlet.java
+++ b/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/InputsServlet.java
@@ -57,6 +57,7 @@ import org.openecomp.sdc.be.model.InputDefinition;
import org.openecomp.sdc.be.model.Resource;
import org.openecomp.sdc.be.model.User;
import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
+import org.openecomp.sdc.be.resources.data.EntryData;
import org.openecomp.sdc.be.resources.data.auditing.AuditingActionEnum;
import org.openecomp.sdc.be.user.UserBusinessLogic;
import org.openecomp.sdc.common.api.Constants;
@@ -84,6 +85,7 @@ import javax.ws.rs.core.Response;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
+import java.util.Map;
@Loggable(prepend = true, value = Loggable.DEBUG, trim = false)
@Tags({@Tag(name = "SDC Internal APIs")})
@@ -97,6 +99,7 @@ public class InputsServlet extends AbstractValidationsServlet {
private static final Logger log = Logger.getLogger(InputsServlet.class);
private static final LoggerSupportability loggerSupportability = LoggerSupportability.getLogger(InputsServlet.class.getName());
private static final String START_HANDLE_REQUEST_OF = "(get) Start handle request of {}";
+ private static final String CREATE_INPUT = "CreateInput";
private final DataTypeBusinessLogic businessLogic;
private final InputsBusinessLogic inputsBusinessLogic;
@@ -334,6 +337,21 @@ public class InputsServlet extends AbstractValidationsServlet {
DeclarationTypeEnum.INPUT, request);
}
+ @POST
+ @Path("/{componentType}/{componentId}/create/input")
+ @Operation(description = "Create inputs on service", method = "POST", summary = "Return inputs list", responses = {
+ @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Resource.class)))),
+ @ApiResponse(responseCode = "200", description = "Component found"),
+ @ApiResponse(responseCode = "403", description = "Restricted operation"),
+ @ApiResponse(responseCode = "404", description = "Component not found")})
+ public Response createInput(@PathParam("componentType") final String componentType,
+ @PathParam("componentId") final String componentId, @Context final HttpServletRequest request,
+ @HeaderParam(value = Constants.USER_ID_HEADER) String userId,
+ @Parameter(description = "ComponentIns Inputs Object to be created",
+ required = true) String componentInstInputsMapObj) {
+
+ return createInput(componentId, componentInstInputsMapObj, request, userId);
+ }
/**
* Creates a "list input" and updates given list of properties to get value from the input.
@@ -566,4 +584,48 @@ public class InputsServlet extends AbstractValidationsServlet {
return response;
}
}
+
+ private Response createInput(String componentId, String data, HttpServletRequest request,String userId) {
+ String url = request.getMethod() + " " + request.getRequestURI();
+ log.debug("Start handle request of {} modifier id is {} data is {}", url, userId, data);
+ loggerSupportability.log(LoggerSupportabilityActions.CREATE_INPUTS, StatusCode.STARTED,"CREATE_INPUTS by user {} ", userId);
+
+ try{
+ Either<Map<String, InputDefinition>, ActionStatus> inputDefinition =
+ getInputModel(componentId, data);
+ if (inputDefinition.isRight()) {
+ ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(inputDefinition.right().value());
+ return buildErrorResponse(responseFormat);
+ }
+
+ Map<String, InputDefinition> inputs = inputDefinition.left().value();
+ if (inputs == null || inputs.size() != 1) {
+ log.info("Input content is invalid - {}", data);
+ ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT);
+ return buildErrorResponse(responseFormat);
+ }
+
+ Map.Entry<String, InputDefinition> entry = inputs.entrySet().iterator().next();
+ InputDefinition newInputDefinition = entry.getValue();
+ newInputDefinition.setParentUniqueId(componentId);
+ String inputName = newInputDefinition.getName();
+
+ Either<EntryData<String, InputDefinition>, ResponseFormat> addInputEither =
+ inputsBusinessLogic.addInputToComponent(componentId, inputName, newInputDefinition, userId);
+
+ if(addInputEither.isRight()) {
+ return buildErrorResponse(addInputEither.right().value());
+ }
+
+ loggerSupportability.log(LoggerSupportabilityActions.CREATE_INPUTS, StatusCode.COMPLETE,"CREATE_INPUTS by user {} ", userId);
+ return buildOkResponse(newInputDefinition);
+
+ } catch (Exception e) {
+ BeEcompErrorManager.getInstance().logBeRestApiGeneralError(CREATE_INPUT);
+ log.debug("create input failed with exception", e);
+ ResponseFormat responseFormat =
+ getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR);
+ return buildErrorResponse(responseFormat);
+ }
+ }
}