summaryrefslogtreecommitdiffstats
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
parent0d38c9a8ed4701b860901f67049920e9b1ca72f2 (diff)
Create inputs independent of properties
Issue-ID: SDC-3431 Signed-off-by: KrupaNagabhushan <krupa.nagabhushan@est.tech> Change-Id: I4f29d0e490a14292fd1aa9f96ca6621b37f325d8
-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
-rw-r--r--catalog-dao/src/main/java/org/openecomp/sdc/be/dao/api/ActionStatus.java3
-rw-r--r--catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/operations/ToscaOperationFacade.java43
-rw-r--r--catalog-ui/src/app/ng2/components/logic/inputs-table/inputs-table.component.html6
-rw-r--r--catalog-ui/src/app/ng2/components/logic/inputs-table/inputs-table.component.less3
-rw-r--r--catalog-ui/src/app/ng2/components/logic/inputs-table/inputs-table.component.ts12
-rw-r--r--catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.page.component.html5
-rw-r--r--catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.page.component.ts35
-rw-r--r--catalog-ui/src/app/ng2/pages/properties-assignment/services/inputs.utils.ts11
-rw-r--r--catalog-ui/src/app/ng2/services/component-services/topology-template.service.ts10
13 files changed, 353 insertions, 20 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);
+ }
+ }
}
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 09a941347c..1d0c54b747 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
@@ -100,6 +100,8 @@ public enum ActionStatus {
// Inputs
INPUT_IS_NOT_CHILD_OF_COMPONENT,
CFVC_LOOP_DETECTED,
+ INPUT_ALREADY_EXIST,
+
//Forwarding Path related
FORWARDING_PATH_NAME_MAXIMUM_LENGTH, FORWARDING_PATH_NAME_ALREADY_IN_USE, FORWARDING_PATH_NAME_EMPTY,
FORWARDING_PATH_PROTOCOL_MAXIMUM_LENGTH, FORWARDING_PATH_DESTINATION_PORT_MAXIMUM_LENGTH,
@@ -158,6 +160,7 @@ public enum ActionStatus {
INTERFACE_LIFECYCLE_TYPES_NOT_FOUND,
INVALID_PROPERTY_NAME,
+ INVALID_INPUT_NAME,
//Property Constraints
INVALID_PROPERTY_CONSTRAINTS, INVALID_PROPERTY_CONSTRAINTS_FORMAT, CANNOT_DELETE_VALID_VALUES,
diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/operations/ToscaOperationFacade.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/operations/ToscaOperationFacade.java
index 957c5f9d66..532a641e2f 100644
--- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/operations/ToscaOperationFacade.java
+++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/operations/ToscaOperationFacade.java
@@ -2482,6 +2482,46 @@ public class ToscaOperationFacade {
return Either.left(newProperty);
}
+ public Either<InputDefinition, StorageOperationStatus> addInputToComponent(String inputName,
+ InputDefinition newInputDefinition,
+ Component component) {
+ newInputDefinition.setName(inputName);
+
+ StorageOperationStatus status = getToscaElementOperation(component)
+ .addToscaDataToToscaElement(component.getUniqueId(), EdgeLabelEnum.INPUTS, VertexTypeEnum.INPUTS, newInputDefinition, JsonPresentationFields.NAME);
+ if (status != StorageOperationStatus.OK) {
+ CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to add the input {} to the component {}. Status is {}. ", inputName, component.getName(), status);
+ return Either.right(status);
+ }
+
+ ComponentParametersView filter = new ComponentParametersView(true);
+ filter.setIgnoreProperties(false);
+ filter.setIgnoreInputs(false);
+ Either<Component, StorageOperationStatus> getUpdatedComponentRes = getToscaElement(component.getUniqueId(), filter);
+ if (getUpdatedComponentRes.isRight()) {
+ CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to get updated component {}. Status is {}. ", component.getUniqueId(), getUpdatedComponentRes.right().value());
+ return Either.right(status);
+ }
+
+ InputDefinition newInput = null;
+ List<InputDefinition> inputs =
+ (getUpdatedComponentRes.left().value()).getInputs();
+ if (CollectionUtils.isNotEmpty(inputs)) {
+ Optional<InputDefinition> inputOptional = inputs.stream().filter(
+ inputEntry -> inputEntry.getName().equals(inputName)).findAny();
+ if (inputOptional.isPresent()) {
+ newInput = inputOptional.get();
+ }
+ }
+ if (newInput == null) {
+ CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to find recently added input {} " +
+ "on the component {}. Status is {}. ", inputs, component.getUniqueId(), StorageOperationStatus.NOT_FOUND);
+ return Either.right(StorageOperationStatus.NOT_FOUND);
+ }
+
+ return Either.left(newInput);
+ }
+
public StorageOperationStatus deletePropertyOfComponent(Component component, String propertyName) {
return getToscaElementOperation(component).deleteToscaDataElement(component.getUniqueId(), EdgeLabelEnum.PROPERTIES, VertexTypeEnum.PROPERTIES, propertyName, JsonPresentationFields.NAME);
}
@@ -2536,8 +2576,7 @@ public class ToscaOperationFacade {
return result;
}
-
- public Either<AttributeDataDefinition, StorageOperationStatus> addAttributeOfResource(Component component, AttributeDataDefinition newAttributeDef) {
+ public Either<AttributeDataDefinition, StorageOperationStatus> addAttributeOfResource(Component component, AttributeDataDefinition newAttributeDef) {
Either<Component, StorageOperationStatus> getUpdatedComponentRes = null;
Either<AttributeDataDefinition, StorageOperationStatus> result = null;
diff --git a/catalog-ui/src/app/ng2/components/logic/inputs-table/inputs-table.component.html b/catalog-ui/src/app/ng2/components/logic/inputs-table/inputs-table.component.html
index ee090245f0..e1638fb00f 100644
--- a/catalog-ui/src/app/ng2/components/logic/inputs-table/inputs-table.component.html
+++ b/catalog-ui/src/app/ng2/components/logic/inputs-table/inputs-table.component.html
@@ -49,6 +49,9 @@
<span *ngIf="input.description"
class="property-description-icon sprite-new show-desc"
tooltip="{{input.description}}" tooltipDelay="0"></span>
+ <div class="delete-button-container">
+ <span *ngIf="showDelete" class="sprite-new delete-btn" (click)="openDeleteModal(input)" data-tests-id="delete-input-button"></span>
+ </div>
</div>
<!-- From Instance -->
<div class="table-cell col3">
@@ -124,9 +127,6 @@
[testId]="'input-' + input.name"
[constraints] = "getConstraints(input)">
</dynamic-element>
- <div class="delete-button-container">
- <span *ngIf="input.instanceUniqueId && !readonly" class="sprite-new delete-btn" (click)="openDeleteModal(input)" data-tests-id="delete-input-button"></span>
- </div>
</div>
</div>
</div>
diff --git a/catalog-ui/src/app/ng2/components/logic/inputs-table/inputs-table.component.less b/catalog-ui/src/app/ng2/components/logic/inputs-table/inputs-table.component.less
index 74520b6314..ae6d58e72e 100644
--- a/catalog-ui/src/app/ng2/components/logic/inputs-table/inputs-table.component.less
+++ b/catalog-ui/src/app/ng2/components/logic/inputs-table/inputs-table.component.less
@@ -182,7 +182,8 @@
// Column: Property Name
&.col1 {
flex: 1 0 130px;
- max-width: 250px;
+ max-width: 300px;
+ display: flex;
justify-content: space-between;
diff --git a/catalog-ui/src/app/ng2/components/logic/inputs-table/inputs-table.component.ts b/catalog-ui/src/app/ng2/components/logic/inputs-table/inputs-table.component.ts
index 3fa7ab4a80..5ca119c075 100644
--- a/catalog-ui/src/app/ng2/components/logic/inputs-table/inputs-table.component.ts
+++ b/catalog-ui/src/app/ng2/components/logic/inputs-table/inputs-table.component.ts
@@ -43,14 +43,14 @@ export class InputsTableComponent {
@Input() readonly: boolean;
@Input() isLoading: boolean;
@Input() componentType: string;
-
+ @Input() showDelete:boolean;
@Output() inputChanged: EventEmitter<any> = new EventEmitter<any>();
@Output() deleteInput: EventEmitter<any> = new EventEmitter<any>();
@Input() fePropertiesMap: InstanceFePropertiesMap;
@ViewChildren('metadataViewChildren') public metadataViewChildren: QueryList<DynamicElementComponent>;
-
+
sortBy: String;
reverse: boolean;
selectedInputToDelete: InputFEModel;
@@ -107,15 +107,15 @@ export class InputsTableComponent {
var mapKeyError = input.metadataMapKeyError;
if(input.metadataMapKeyError){
dynamicElementComponent.cmpRef.instance.control.setErrors({mapKeyError});
- }
+ }
};
onMetadataValueChanged = (input: InputFEModel, event, metadataEntry: MetadataEntry) => {
input.updateMetadataValue(metadataEntry, event.value);
this.inputChanged.emit(input);
};
-
-
+
+
createNewMetadataEntry = (input: InputFEModel): void => {
let metadataEntry = new MetadataEntry("", "");
input.addMetadataEntry(metadataEntry);
@@ -126,7 +126,7 @@ export class InputsTableComponent {
input.deleteMetadataEntry(metadataEntry);
this.inputChanged.emit(input);
}
-
+
onDeleteInput = () => {
this.deleteInput.emit(this.selectedInputToDelete);
this.modalService.closeCurrentModal();
diff --git a/catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.page.component.html b/catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.page.component.html
index 6856ae8358..6b3e92adfd 100644
--- a/catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.page.component.html
+++ b/catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.page.component.html
@@ -44,6 +44,7 @@
<inputs-table class="properties-table"
[fePropertiesMap]="instanceFePropertiesMap"
[readonly]="isReadonly"
+ [showDelete]="!isReadOnly && isSelf()"
[inputs]="inputs | searchFilter:'name':searchQuery"
[instanceNamesMap]="componentInstanceNamesMap"
[isLoading]="loadingInputs"
@@ -80,8 +81,10 @@
</div>
</div>
<div class="right-column">
- <div *ngIf="!isReadonly" class="add-btn"
+ <div *ngIf="!isReadonly && !isInputsTabSelected" class="add-btn"
(click)="addProperty()" [ngClass]="{'disabled': !isSelf()}">Add Property</div>
+ <div *ngIf="!isReadonly && isInputsTabSelected" class="add-btn"
+ (click)="addInput()" [ngClass]="{'disabled': !isSelf()}">Add Input</div>
<tabs #hierarchyNavTabs tabStyle="simple-tabs" class="gray-border">
<tab tabTitle="Composition">
<div class="hierarchy-nav-container">
diff --git a/catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.page.component.ts b/catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.page.component.ts
index e4a8749386..74e2680b80 100644
--- a/catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.page.component.ts
+++ b/catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.page.component.ts
@@ -1052,6 +1052,41 @@ export class PropertiesAssignmentComponent {
modal.instance.open();
}
+ /*** addInput ***/
+ addInput = () => {
+ let modalTitle = 'Add Input';
+ let modal = this.ModalService.createCustomModal(new ModalModel(
+ 'sm',
+ modalTitle,
+ null,
+ [
+ new ButtonModel('Save', 'blue', () => {
+ modal.instance.dynamicContent.instance.isLoading = true;
+ const newInput: InputBEModel = modal.instance.dynamicContent.instance.propertyModel;
+ this.topologyTemplateService.createServiceInput(this.component.uniqueId, newInput)
+ .subscribe((response) => {
+ modal.instance.dynamicContent.instance.isLoading = false;
+ const newInputProp: InputFEModel = this.inputsUtils.convertInputBEToInputFE(response);
+ this.inputs.push(newInputProp);
+ modal.instance.close();
+ }, (error) => {
+ modal.instance.dynamicContent.instance.isLoading = false;
+ this.Notification.error({
+ message: 'Failed to add input:' + error,
+ title: 'Failure'
+ });
+ });
+ }, () => !modal.instance.dynamicContent.instance.checkFormValidForSubmit()),
+ new ButtonModel('Cancel', 'outline grey', () => {
+ modal.instance.close();
+ }),
+ ],
+ null
+ ));
+ this.ModalService.addDynamicContentToModal(modal, PropertyCreatorComponent, {});
+ modal.instance.open();
+ }
+
/*** SEARCH RELATED FUNCTIONS ***/
searchPropertiesInstances = (filterData:FilterPropertiesAssignmentData) => {
let instanceBePropertiesMap:InstanceBePropertiesMap;
diff --git a/catalog-ui/src/app/ng2/pages/properties-assignment/services/inputs.utils.ts b/catalog-ui/src/app/ng2/pages/properties-assignment/services/inputs.utils.ts
index 408a00e7b4..948c9032bf 100644
--- a/catalog-ui/src/app/ng2/pages/properties-assignment/services/inputs.utils.ts
+++ b/catalog-ui/src/app/ng2/pages/properties-assignment/services/inputs.utils.ts
@@ -19,12 +19,13 @@
*/
import { Injectable } from '@angular/core';
-import { InputFEModel} from "app/models";
+import { InputBEModel, InputFEModel } from "app/models";
+import { DataTypeService } from "app/ng2/services/data-type.service";
@Injectable()
export class InputsUtils {
- constructor() {}
+ constructor(private dataTypeService:DataTypeService) {}
public initDefaultValueObject = (input: InputFEModel): void => {
input.resetDefaultValueObjValidation();
@@ -37,4 +38,10 @@ export class InputsUtils {
this.initDefaultValueObject(input);
}
+ public convertInputBEToInputFE = (input: InputBEModel): InputFEModel => {
+ const newFEInput: InputFEModel = new InputFEModel(input); //Convert input to FE
+ this.initDefaultValueObject(newFEInput);
+ return newFEInput;
+ }
+
}
diff --git a/catalog-ui/src/app/ng2/services/component-services/topology-template.service.ts b/catalog-ui/src/app/ng2/services/component-services/topology-template.service.ts
index 14bf84599c..492acdc1d6 100644
--- a/catalog-ui/src/app/ng2/services/component-services/topology-template.service.ts
+++ b/catalog-ui/src/app/ng2/services/component-services/topology-template.service.ts
@@ -227,6 +227,16 @@ export class TopologyTemplateService {
});
}
+ createServiceInput(componentId: string, inputModel: InputBEModel): Observable<InputBEModel> {
+ const serverObject = {};
+ serverObject[inputModel.name] = inputModel;
+ return this.http.post<InputBEModel>(this.baseUrl + 'services/' + componentId + '/create/input', serverObject)
+ .map((res) => {
+ const input: InputBEModel = new InputBEModel(res);
+ return input;
+ });
+ }
+
getDependencies(componentType: string, componentId: string): Observable<IDependenciesServerResponse[]> {
return this.http.get<IDependenciesServerResponse[]>(this.baseUrl + this.getServerTypeUrl(componentType) + componentId + '/dependencies');
}