diff options
author | vasraz <vasyl.razinkov@est.tech> | 2023-07-22 13:07:27 +0100 |
---|---|---|
committer | Michael Morris <michael.morris@est.tech> | 2023-07-28 13:00:55 +0000 |
commit | 216ea4998de9ae4ee603d7f8f5f6725b218ca710 (patch) | |
tree | 891920a916a6301836061e29f6154b5973431f99 /catalog-be/src/main | |
parent | 47317bba3db6c7426a5461aa6c20716bf7db8c96 (diff) |
Implement 'Update Service by importing Tosca Template'-story
Signed-off-by: Vasyl Razinkov <vasyl.razinkov@est.tech>
Change-Id: Ia2842c49cc81eb30174d783805261d0e73835e48
Issue-ID: SDC-4576
Diffstat (limited to 'catalog-be/src/main')
19 files changed, 351 insertions, 258 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 006752ee0c..b91e378239 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 @@ -2903,3 +2903,18 @@ errors: message: "Error: Uploaded YAML file is invalid.\n%1", messageId: "SVC4010" } + + #---------SVC4019----------------------------- + # %1 - metadata property name + UNCHANGEABLE_PROPERTY_ERROR: { + code: 402, + message: "Error: '%1' cannot change", + messageId: "SVC4019" + } + + #---------SVC4020----------------------------- + MISSING_SERVICE_METADATA: { + code: 402, + message: "Error: Missing metadata in Service", + messageId: "SVC4020" + } diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/csar/CsarBusinessLogic.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/csar/CsarBusinessLogic.java index 36c16bed9e..be3a408bfa 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/csar/CsarBusinessLogic.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/csar/CsarBusinessLogic.java @@ -98,9 +98,7 @@ public class CsarBusinessLogic extends BaseBusinessLogic { } public void validateCsarBeforeCreate(Service resource, String csarUUID) { - // check if VF with the same Csar UUID or with he same name already - - // exists + // check if VF with the same Csar UUID or with he same name already exists StorageOperationStatus status = toscaOperationFacade.validateCsarUuidUniqueness(csarUUID); log.debug("enter validateCsarBeforeCreate,get status:{}", status); if (status == StorageOperationStatus.ENTITY_ALREADY_EXISTS) { @@ -111,7 +109,7 @@ public class CsarBusinessLogic extends BaseBusinessLogic { } } - public OnboardedCsarInfo getCsarInfo(Resource resource, Resource oldResource, User user, Map<String, byte[]> payload, String csarUUID) { + public OnboardedCsarInfo getCsarInfo(Resource resource, Resource oldResource, User user, Map<String, byte[]> payload, String csarUUID, AuditingActionEnum auditingAction) { Map<String, byte[]> csar = payload; if (csar == null) { final var vendorSoftwareProduct = getCsar(resource, user); @@ -119,7 +117,7 @@ public class CsarBusinessLogic extends BaseBusinessLogic { csar = vendorSoftwareProduct.getFileMap(); } - ImmutablePair<String, String> toscaYamlCsarStatus = validateAndParseCsar(resource, user, csar, csarUUID).left() + ImmutablePair<String, String> toscaYamlCsarStatus = validateAndParseCsar(resource, user, csar, csarUUID, auditingAction).left() .on(this::throwComponentException); String checksum = CsarValidationUtils.getToscaYamlChecksum(csar, csarUUID, componentsUtils).left() .on(r -> logAndThrowComponentException(r, "Failed to calculate checksum for casrUUID {} error {} ", csarUUID)); @@ -149,9 +147,9 @@ public class CsarBusinessLogic extends BaseBusinessLogic { } } - public ServiceCsarInfo getCsarInfo(Service service, Service oldResource, User user, Map<String, byte[]> payload, String csarUUID) { + public ServiceCsarInfo getCsarInfo(Service service, Service oldResource, User user, Map<String, byte[]> payload, String csarUUID, AuditingActionEnum auditingAction) { Map<String, byte[]> csar = getCsar(service, user, payload, csarUUID); - ImmutablePair<String, String> toscaYamlCsarStatus = validateAndParseCsar(service, user, csar, csarUUID).left() + ImmutablePair<String, String> toscaYamlCsarStatus = validateAndParseCsar(service, user, csar, csarUUID, auditingAction).left() .on(this::throwComponentException); String checksum = CsarValidationUtils.getToscaYamlChecksum(csar, csarUUID, componentsUtils).left() .on(r -> logAndThrowComponentException(r, "Failed to calculate checksum for casrUUID {} error {} ", csarUUID)); @@ -199,7 +197,7 @@ public class CsarBusinessLogic extends BaseBusinessLogic { } private Either<ImmutablePair<String, String>, ResponseFormat> validateAndParseCsar(Component component, User user, Map<String, byte[]> csar, - String csarUUID) { + String csarUUID, AuditingActionEnum auditingAction) { Either<Boolean, ResponseFormat> validateCsarStatus = CsarValidationUtils.validateCsar(csar, csarUUID, componentsUtils); if (validateCsarStatus.isRight()) { ResponseFormat responseFormat = validateCsarStatus.right().value(); @@ -210,7 +208,7 @@ public class CsarBusinessLogic extends BaseBusinessLogic { } return Either.right(responseFormat); } - Either<ImmutablePair<String, String>, ResponseFormat> toscaYamlCsarStatus = CsarValidationUtils.getToscaYaml(csar, csarUUID, componentsUtils); + Either<ImmutablePair<String, String>, ResponseFormat> toscaYamlCsarStatus = CsarValidationUtils.getToscaYaml(csar, csarUUID, componentsUtils, auditingAction); if (toscaYamlCsarStatus.isRight()) { ResponseFormat responseFormat = toscaYamlCsarStatus.right().value(); log.debug("Error when try to get csar toscayamlFile with csar ID {}, error: {}", csarUUID, responseFormat); @@ -278,7 +276,7 @@ public class CsarBusinessLogic extends BaseBusinessLogic { } private Either<ImmutablePair<String, String>, ResponseFormat> validateAndParseCsar(Service service, User user, Map<String, byte[]> payload, - String csarUUID) { + String csarUUID, AuditingActionEnum auditingAction) { Map<String, byte[]> csar = getCsar(service, user, payload, csarUUID); Either<Boolean, ResponseFormat> validateCsarStatus = CsarValidationUtils.validateCsar(csar, csarUUID, componentsUtils); if (validateCsarStatus.isRight()) { @@ -287,7 +285,7 @@ public class CsarBusinessLogic extends BaseBusinessLogic { BeEcompErrorManager.getInstance().logBeDaoSystemError(CREATING_RESOURCE_FROM_CSAR_FETCHING_CSAR_WITH_ID + csarUUID + FAILED); return Either.right(responseFormat); } - Either<ImmutablePair<String, String>, ResponseFormat> toscaYamlCsarStatus = CsarValidationUtils.getToscaYaml(csar, csarUUID, componentsUtils); + Either<ImmutablePair<String, String>, ResponseFormat> toscaYamlCsarStatus = CsarValidationUtils.getToscaYaml(csar, csarUUID, componentsUtils, auditingAction); if (toscaYamlCsarStatus.isRight()) { ResponseFormat responseFormat = toscaYamlCsarStatus.right().value(); log.debug("Error when try to get csar toscayamlFile with csar ID {}, error: {}", csarUUID, responseFormat); diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/csar/ServiceCsarInfo.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/csar/ServiceCsarInfo.java index cd73f70cc5..7837588178 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/csar/ServiceCsarInfo.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/csar/ServiceCsarInfo.java @@ -170,19 +170,9 @@ public class ServiceCsarInfo extends CsarInfo { return getTypes(ToscaTagNamesEnum.CAPABILITY_TYPES); } - private Map<String, Object> getTypes(ToscaTagNamesEnum toscaTag) { - final Map<String, Object> types = new HashMap<>(); - mainTemplateImports.entrySet().forEach(entry -> types.putAll(getTypesFromTemplate(entry.getValue(), toscaTag))); - types.putAll(getTypesFromTemplate(getMappedToscaMainTemplate(), toscaTag)); - return types; - } - + @Override public Map<String, Object> getArtifactTypes() { - final Map<String, Object> artifactsTypes = new HashMap<>(); - mainTemplateImports.entrySet() - .forEach(entry -> artifactsTypes.putAll(getTypesFromTemplate(entry.getValue(), TypeUtils.ToscaTagNamesEnum.ARTIFACT_TYPES))); - artifactsTypes.putAll(getTypesFromTemplate(getMappedToscaMainTemplate(), TypeUtils.ToscaTagNamesEnum.ARTIFACT_TYPES)); - return artifactsTypes; + return getTypes(ToscaTagNamesEnum.ARTIFACT_TYPES); } @Override @@ -190,6 +180,13 @@ public class ServiceCsarInfo extends CsarInfo { return getTypes(ToscaTagNamesEnum.INTERFACE_TYPES); } + private Map<String, Object> getTypes(ToscaTagNamesEnum toscaTag) { + final Map<String, Object> types = new HashMap<>(); + mainTemplateImports.entrySet().forEach(entry -> types.putAll(getTypesFromTemplate(entry.getValue(), toscaTag))); + types.putAll(getTypesFromTemplate(getMappedToscaMainTemplate(), toscaTag)); + return types; + } + public List<NodeTypeDefinition> getNodeTypesUsed() { if (nodeTypeDefinitions == null) { nodeTypeDefinitions = new ArrayList<>(); @@ -249,7 +246,6 @@ public class ServiceCsarInfo extends CsarInfo { return nodeTypesToReturn; } - private Map<String, NodeTypeDefinition> getTypes(final Set<String> nodeTypes) { final Map<String, NodeTypeDefinition> nodeTypeDefinitionsMap = new HashMap<>(); final Set<String> lowerPrecedenceImports = new HashSet<>(); @@ -274,7 +270,6 @@ public class ServiceCsarInfo extends CsarInfo { return nodeTypeDefinitionsMap; } - private void addTypesFromTemplate(final Map<String, NodeTypeDefinition> nodeTypeDefinitionsMap, final Map<String, Object> mappedTemplate, final Set<String> nodeTypes) { final Map<String, Object> types = getTypesFromTemplate(mappedTemplate, ToscaTagNamesEnum.NODE_TYPES, nodeTypes); diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/csar/YamlTemplateParsingHandler.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/csar/YamlTemplateParsingHandler.java index fd2fa4bf1a..2ec342ec24 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/csar/YamlTemplateParsingHandler.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/csar/YamlTemplateParsingHandler.java @@ -200,14 +200,14 @@ public class YamlTemplateParsingHandler { Map<String, Object> substitutionMappings = getSubstitutionMappings(mappedToscaTemplate); if (substitutionMappings != null) { if (component.isService()) { - if (!interfaceTemplateYaml.isEmpty()) { - parsedToscaYamlInfo.setProperties(getProperties(loadYamlAsStrictMap(interfaceTemplateYaml))); - parsedToscaYamlInfo.setSubstitutionFilterProperties(getSubstitutionFilterProperties(mappedToscaTemplate)); - } else { + if (interfaceTemplateYaml.isEmpty()) { Resource resource = serviceBusinessLogic.fetchDerivedFromGenericType(component, null); List<PropertyDefinition> properties = resource.getProperties(); parsedToscaYamlInfo.setProperties(properties.stream().collect(Collectors.toMap(PropertyDefinition::getName, prop -> prop))); parsedToscaYamlInfo.setSubstitutionFilterProperties(getSubstitutionFilterProperties(mappedToscaTemplate)); + } else { + parsedToscaYamlInfo.setProperties(getProperties(loadYamlAsStrictMap(interfaceTemplateYaml))); + parsedToscaYamlInfo.setSubstitutionFilterProperties(getSubstitutionFilterProperties(mappedToscaTemplate)); } } if (substitutionMappings.get("properties") != null) { diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/CsarValidationUtils.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/CsarValidationUtils.java index c6aa1b7237..a45a04ea2a 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/CsarValidationUtils.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/CsarValidationUtils.java @@ -37,6 +37,7 @@ import org.openecomp.sdc.be.config.BeEcompErrorManager; import org.openecomp.sdc.be.config.BeEcompErrorManager.ErrorSeverity; import org.openecomp.sdc.be.dao.api.ActionStatus; import org.openecomp.sdc.be.impl.ComponentsUtils; +import org.openecomp.sdc.be.resources.data.auditing.AuditingActionEnum; import org.openecomp.sdc.be.tosca.CsarUtils; import org.openecomp.sdc.common.log.wrappers.Logger; import org.openecomp.sdc.common.util.GeneralUtility; @@ -137,18 +138,20 @@ public class CsarValidationUtils { } public static Either<ImmutablePair<String, String>, ResponseFormat> getToscaYaml(Map<String, byte[]> csar, String csarUUID, - ComponentsUtils componentsUtils) { - Either<Boolean, ResponseFormat> validateStatus = validateIsTOSCAMetadataExist(csar, csarUUID, componentsUtils); - if (validateStatus.isRight()) { - return Either.right(validateStatus.right().value()); + ComponentsUtils componentsUtils, AuditingActionEnum auditingAction) { + if (!AuditingActionEnum.UPDATE_SERVICE_TOSCA_TEMPLATE.equals(auditingAction)) { + Either<Boolean, ResponseFormat> validateStatus = validateIsTOSCAMetadataExist(csar, csarUUID, componentsUtils); + if (validateStatus.isRight()) { + return Either.right(validateStatus.right().value()); + } } Pattern pattern = Pattern.compile(TOSCA_METADATA_PATH_PATTERN); Optional<String> keyOp = csar.keySet().stream().filter(k -> pattern.matcher(k).matches()).findAny(); if (!keyOp.isPresent()) { log.debug(TOSCA_METADATA_TOSCA_META_FILE_IS_NOT_IN_EXPECTED_KEY_VALUE_FORM_IN_CSAR_CSAR_ID, csarUUID); BeEcompErrorManager.getInstance() - .logInternalDataError(TOSCA_METADATA_TOSCA_META_FILE_NOT_IN_EXPECTED_KEY_VALUE_FORM_IN_CSAR_WITH_ID + csarUUID, - CSAR_INTERNALS_ARE_INVALID, ErrorSeverity.ERROR); + .logInternalDataError(TOSCA_METADATA_TOSCA_META_FILE_NOT_IN_EXPECTED_KEY_VALUE_FORM_IN_CSAR_WITH_ID + csarUUID, + CSAR_INTERNALS_ARE_INVALID, ErrorSeverity.ERROR); return Either.right(componentsUtils.getResponseFormat(ActionStatus.CSAR_INVALID_FORMAT, csarUUID)); } byte[] toscaMetaBytes = csar.get(keyOp.get()); @@ -159,8 +162,8 @@ public class CsarValidationUtils { } catch (IOException e) { log.debug(TOSCA_METADATA_TOSCA_META_FILE_IS_NOT_IN_EXPECTED_KEY_VALUE_FORM_IN_CSAR_CSAR_ID, csarUUID, e); BeEcompErrorManager.getInstance() - .logInternalDataError(TOSCA_METADATA_TOSCA_META_FILE_NOT_IN_EXPECTED_KEY_VALUE_FORM_IN_CSAR_WITH_ID + csarUUID, - CSAR_INTERNALS_ARE_INVALID, ErrorSeverity.ERROR); + .logInternalDataError(TOSCA_METADATA_TOSCA_META_FILE_NOT_IN_EXPECTED_KEY_VALUE_FORM_IN_CSAR_WITH_ID + csarUUID, + CSAR_INTERNALS_ARE_INVALID, ErrorSeverity.ERROR); return Either.right(componentsUtils.getResponseFormat(ActionStatus.CSAR_INVALID_FORMAT, csarUUID)); } String yamlFileName = props.getProperty(TOSCA_META_ENTRY_DEFINITIONS); @@ -171,8 +174,8 @@ public class CsarValidationUtils { if (!keyOp.isPresent()) { log.debug(ENTRY_DEFINITIONS_ENTRY_NOT_FOUND_IN_TOSCA_METADATA_TOSCA_META_FILE_CSAR_ID, csarUUID); BeEcompErrorManager.getInstance() - .logInternalDataError(ENTRY_DEFINITIONS_ENTRY_NOT_FOUND_IN_TOSCA_METADATA_TOSCA_META_FILE_CSAR_ID + csarUUID, - CSAR_INTERNALS_ARE_INVALID, ErrorSeverity.ERROR); + .logInternalDataError(ENTRY_DEFINITIONS_ENTRY_NOT_FOUND_IN_TOSCA_METADATA_TOSCA_META_FILE_CSAR_ID + csarUUID, + CSAR_INTERNALS_ARE_INVALID, ErrorSeverity.ERROR); return Either.right(componentsUtils.getResponseFormat(ActionStatus.YAML_NOT_FOUND_IN_CSAR, csarUUID, yamlFileName)); } log.trace("Found Entry-Definitions property in TOSCA-Metadata/TOSCA.meta, Entry-Definitions: {}, CSAR id: {}", yamlFileName, csarUUID); @@ -180,8 +183,8 @@ public class CsarValidationUtils { if (yamlFileBytes == null) { log.debug("Entry-Definitions {} file not found in csar, csar ID {}", yamlFileName, csarUUID); BeEcompErrorManager.getInstance() - .logInternalDataError(ENTRY_DEFINITIONS + yamlFileName + FILE_NOT_FOUND_IN_CSAR_WITH_ID + csarUUID, CSAR_STRUCTURE_IS_INVALID, - ErrorSeverity.ERROR); + .logInternalDataError(ENTRY_DEFINITIONS + yamlFileName + FILE_NOT_FOUND_IN_CSAR_WITH_ID + csarUUID, CSAR_STRUCTURE_IS_INVALID, + ErrorSeverity.ERROR); return Either.right(componentsUtils.getResponseFormat(ActionStatus.YAML_NOT_FOUND_IN_CSAR, csarUUID, yamlFileName)); } String yamlFileContents = new String(yamlFileBytes); @@ -340,7 +343,7 @@ public class CsarValidationUtils { } public static Either<String, ResponseFormat> getToscaYamlChecksum(Map<String, byte[]> csar, String csarUUID, ComponentsUtils componentsUtils) { - Either<ImmutablePair<String, String>, ResponseFormat> toscaYamlRes = getToscaYaml(csar, csarUUID, componentsUtils); + Either<ImmutablePair<String, String>, ResponseFormat> toscaYamlRes = getToscaYaml(csar, csarUUID, componentsUtils, AuditingActionEnum.GET_TOSCA_MODEL); if (toscaYamlRes.isRight() || toscaYamlRes.left().value() == null || toscaYamlRes.left().value().getRight() == null) { log.debug("Faild to create toscaYamlChecksum for csar, csar ID {}", csarUUID); return Either.right(toscaYamlRes.right().value()); diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ResourceBusinessLogic.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ResourceBusinessLogic.java index 8442db9bab..7e7348d89e 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ResourceBusinessLogic.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ResourceBusinessLogic.java @@ -517,7 +517,7 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { validateLifecycleState(oldResource, user); String lockedResourceId = oldResource.getUniqueId(); List<ArtifactDefinition> createdArtifacts = new ArrayList<>(); - CsarInfo csarInfo = csarBusinessLogic.getCsarInfo(newResource, oldResource, user, csarUIPayload, csarUUID); + CsarInfo csarInfo = csarBusinessLogic.getCsarInfo(newResource, oldResource, user, csarUIPayload, csarUUID, null); lockComponent(lockedResourceId, oldResource, "update Resource From Csar"); Map<String, NodeTypeInfo> nodeTypesInfo = csarInfo.extractTypesInfo(); Either<Map<String, EnumMap<ArtifactOperationEnum, List<ArtifactDefinition>>>, ResponseFormat> findNodeTypesArtifactsToHandleRes = findNodeTypesArtifactsToHandle( @@ -1034,7 +1034,7 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { loggerSupportability .log(LoggerSupportabilityActions.CREATE_RESOURCE_FROM_YAML, StatusCode.STARTED, "Starting to create Resource From Csar by user {}", user.getUserId()); - OnboardedCsarInfo csarInfo = csarBusinessLogic.getCsarInfo(resource, null, user, csarUIPayload, csarUUID); + OnboardedCsarInfo csarInfo = csarBusinessLogic.getCsarInfo(resource, null, user, csarUIPayload, csarUUID, null); Map<String, NodeTypeInfo> nodeTypesInfo = csarInfo.extractTypesInfo(); final String model = resource.getModel(); diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ResourceImportManager.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ResourceImportManager.java index 7710a4878b..d75b59be85 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ResourceImportManager.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ResourceImportManager.java @@ -209,15 +209,6 @@ public class ResourceImportManager { } } - public ImmutablePair<Resource, ActionStatus> importNormativeResourceFromCsar(String resourceYml, UploadResourceInfo resourceMetaData, - User creator, boolean createNewVersion, boolean needLock) { - LifecycleChangeInfoWithAction lifecycleChangeInfo = new LifecycleChangeInfoWithAction(); - lifecycleChangeInfo.setUserRemarks("certification on import"); - Function<Resource, Boolean> validator = resource -> resourceBusinessLogic.validatePropertiesDefaultValues(resource); - return importCertifiedResource(resourceYml, resourceMetaData, creator, validator, lifecycleChangeInfo, false, createNewVersion, needLock, - null, null, false, null, null, false); - } - public ImmutablePair<Resource, ActionStatus> importCertifiedResource(String resourceYml, UploadResourceInfo resourceMetaData, User creator, Function<Resource, Boolean> validationFunction, LifecycleChangeInfoWithAction lifecycleChangeInfo, boolean isInTransaction, diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ServiceBusinessLogic.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ServiceBusinessLogic.java index d03a238fce..9874020b49 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ServiceBusinessLogic.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ServiceBusinessLogic.java @@ -55,7 +55,6 @@ import java.util.function.Function; import java.util.stream.Collectors; import javax.servlet.ServletContext; import javax.servlet.http.HttpServletRequest; - import lombok.AccessLevel; import lombok.AllArgsConstructor; import lombok.Getter; @@ -219,7 +218,8 @@ public class ServiceBusinessLogic extends ComponentBusinessLogic { ComponentDescriptionValidator componentDescriptionValidator, ModelOperation modelOperation, final ServiceRoleValidator serviceRoleValidator, final ServiceInstantiationTypeValidator serviceInstantiationTypeValidator, - final ServiceCategoryValidator serviceCategoryValidator, final ServiceValidator serviceValidator, KafkaHandler kafkaHandler) { + final ServiceCategoryValidator serviceCategoryValidator, final ServiceValidator serviceValidator, + KafkaHandler kafkaHandler) { super(elementDao, groupOperation, groupInstanceOperation, groupTypeOperation, groupBusinessLogic, interfaceOperation, interfaceLifecycleTypeOperation, artifactsBusinessLogic, artifactToscaOperation, componentContactIdValidator, componentNameValidator, componentTagsValidator, componentValidator, componentIconValidator, componentProjectCodeValidator, componentDescriptionValidator); @@ -800,13 +800,13 @@ public class ServiceBusinessLogic extends ComponentBusinessLogic { componentsUtils.auditComponentAdmin(responseFormat, user, service, AuditingActionEnum.CREATE_SERVICE, ComponentTypeEnum.SERVICE); throw exp; } - service.setCreatorFullName(user.getFirstName() + " " + user.getLastName()); - service.setContactId(service.getContactId().toLowerCase()); - // Generate invariant UUID - must be here and not in operation since it - - // should stay constant during clone - String invariantUUID = UniqueIdBuilder.buildInvariantUUID(); - service.setInvariantUUID(invariantUUID); + if (!AuditingActionEnum.UPDATE_SERVICE_TOSCA_TEMPLATE.equals(actionEnum) && + !AuditingActionEnum.UPDATE_SERVICE_TOSCA_MODEL.equals(actionEnum)) { + service.setCreatorFullName(user.getFirstName() + " " + user.getLastName()); + service.setContactId(service.getContactId().toLowerCase()); + // Generate invariant UUID - must be here and not in operation since it should stay constant during clone + service.setInvariantUUID(UniqueIdBuilder.buildInvariantUUID()); + } return Either.left(service); } @@ -1153,14 +1153,14 @@ public class ServiceBusinessLogic extends ComponentBusinessLogic { } private void addInputsToService(Service currentService, List<PropertyDefinition> subNodePropsToBeAdded) { - ListUtils.emptyIfNull(subNodePropsToBeAdded).forEach(prop -> { - InputDefinition inputDef = new InputDefinition(prop); - Either<InputDefinition, StorageOperationStatus> status = - toscaOperationFacade.addInputToComponent(prop.getName(), inputDef, currentService); - if (status.isRight()) { - throw new ByActionStatusComponentException(ActionStatus.GENERAL_ERROR); - } - }); + ListUtils.emptyIfNull(subNodePropsToBeAdded).forEach(prop -> { + InputDefinition inputDef = new InputDefinition(prop); + Either<InputDefinition, StorageOperationStatus> status = + toscaOperationFacade.addInputToComponent(prop.getName(), inputDef, currentService); + if (status.isRight()) { + throw new ByActionStatusComponentException(ActionStatus.GENERAL_ERROR); + } + }); } private void removePropertiesFromService(Service currentService, List<String> subNodePropsToBeRemoved) { @@ -1249,25 +1249,25 @@ public class ServiceBusinessLogic extends ComponentBusinessLogic { if (!StringUtils.equals(currentService.getDerivedFromGenericType(), serviceUpdate.getDerivedFromGenericType())) { return currentProps.stream().map(PropertyDefinition::getName).collect(Collectors.toList()); } - + Map<String, PropertyDefinition> currentPropsMap = currentProps.stream().collect(Collectors.toMap(prop -> prop.getName(), prop -> prop)); Map<String, PropertyDefinition> updatedPropsMap = updatedProps.stream().collect(Collectors.toMap(prop -> prop.getName(), prop -> prop)); List<String> propNamesToBeRemoved = new ArrayList<>(); - for (String currentPropertyName: currentPropsMap.keySet()) { + for (String currentPropertyName : currentPropsMap.keySet()) { if (updatedPropsMap.containsKey(currentPropertyName)) { if (!haveSameType(currentPropsMap.get(currentPropertyName), updatedPropsMap.get(currentPropertyName))) { propNamesToBeRemoved.add(currentPropertyName); - } + } } else { propNamesToBeRemoved.add(currentPropertyName); } } - + return propNamesToBeRemoved; } - - private boolean haveSameType(final PropertyDefinition property1, final PropertyDefinition property2){ + + private boolean haveSameType(final PropertyDefinition property1, final PropertyDefinition property2) { if (property1.getType().equals("list")) { return property2.getType().equals("list") && property1.getSchema().equals(property2.getSchema()); } @@ -1276,28 +1276,30 @@ public class ServiceBusinessLogic extends ComponentBusinessLogic { } return property1.getType().equals(property2.getType()); } - + private List<PropertyDefinition> getSubstitutionNodePropertiesToBeAdded(Service currentService, Service serviceUpdate) { List<PropertyDefinition> propsInCurrentVersion = ListUtils.emptyIfNull(fetchDerivedFromGenericType(currentService, null).getProperties()); List<PropertyDefinition> propsInUpdatedVersion = ListUtils.emptyIfNull(fetchDerivedFromGenericType(serviceUpdate, null).getProperties()); if (!StringUtils.equals(currentService.getDerivedFromGenericType(), serviceUpdate.getDerivedFromGenericType())) { return propsInUpdatedVersion; } - - Map<String, PropertyDefinition> mapOfPropsInCurrentVersion = propsInCurrentVersion.stream().collect(Collectors.toMap(prop -> prop.getName(), prop -> prop)); - Map<String, PropertyDefinition> mapOfPropsInUpdatedVersion = propsInUpdatedVersion.stream().collect(Collectors.toMap(prop -> prop.getName(), prop -> prop)); - + + Map<String, PropertyDefinition> mapOfPropsInCurrentVersion = propsInCurrentVersion.stream() + .collect(Collectors.toMap(prop -> prop.getName(), prop -> prop)); + Map<String, PropertyDefinition> mapOfPropsInUpdatedVersion = propsInUpdatedVersion.stream() + .collect(Collectors.toMap(prop -> prop.getName(), prop -> prop)); + List<PropertyDefinition> propsToBeAdded = new ArrayList<>(); - for (Entry<String, PropertyDefinition> propertyInUpdatedVersion: mapOfPropsInUpdatedVersion.entrySet()) { + for (Entry<String, PropertyDefinition> propertyInUpdatedVersion : mapOfPropsInUpdatedVersion.entrySet()) { if (mapOfPropsInCurrentVersion.containsKey(propertyInUpdatedVersion.getKey())) { if (!haveSameType(mapOfPropsInCurrentVersion.get(propertyInUpdatedVersion.getKey()), propertyInUpdatedVersion.getValue())) { propsToBeAdded.add(propertyInUpdatedVersion.getValue()); - } + } } else { propsToBeAdded.add(propertyInUpdatedVersion.getValue()); } } - + return propsToBeAdded; } @@ -1751,9 +1753,9 @@ public class ServiceBusinessLogic extends ComponentBusinessLogic { if (serviceRes.isRight()) { log.debug("failed retrieving service"); response = componentsUtils - .getResponseFormat(componentsUtils.convertFromStorageResponse(serviceRes.right().value(), ComponentTypeEnum.SERVICE), serviceId); + .getResponseFormat(componentsUtils.convertFromStorageResponse(serviceRes.right().value(), ComponentTypeEnum.SERVICE), serviceId); componentsUtils.auditComponent(response, user, null, AuditingActionEnum.DISTRIBUTION_STATE_CHANGE_REQUEST, - new ResourceCommonInfo(ComponentTypeEnum.SERVICE.getValue()), ResourceVersionInfo.newBuilder().build(), did); + new ResourceCommonInfo(ComponentTypeEnum.SERVICE.getValue()), ResourceVersionInfo.newBuilder().build(), did); return Either.right(response); } Service service = serviceRes.left().value(); @@ -1764,7 +1766,7 @@ public class ServiceBusinessLogic extends ComponentBusinessLogic { if (service.getLifecycleState() != LifecycleStateEnum.CERTIFIED) { log.info("service {} is not available for distribution. Should be in certified state", service.getUniqueId()); ResponseFormat responseFormat = componentsUtils - .getResponseFormat(ActionStatus.SERVICE_NOT_AVAILABLE_FOR_DISTRIBUTION, service.getVersion(), service.getName()); + .getResponseFormat(ActionStatus.SERVICE_NOT_AVAILABLE_FOR_DISTRIBUTION, service.getVersion(), service.getName()); return Either.right(responseFormat); } String dcurrStatus = service.getDistributionStatus().name(); @@ -1775,7 +1777,7 @@ public class ServiceBusinessLogic extends ComponentBusinessLogic { ActionStatus notifyServiceResponse = distributionEngine.notifyService(did, service, notificationData, envName, user); if (notifyServiceResponse == ActionStatus.OK) { Either<Service, ResponseFormat> updateStateRes = updateDistributionStatusForActivation(service, user, - DistributionStatusEnum.DISTRIBUTED); + DistributionStatusEnum.DISTRIBUTED); if (updateStateRes.isLeft() && updateStateRes.left().value() != null) { updatedService = updateStateRes.left().value(); updatedStatus = updatedService.getDistributionStatus().name(); @@ -1794,13 +1796,13 @@ public class ServiceBusinessLogic extends ComponentBusinessLogic { } } else { response = componentsUtils - .getResponseFormatByDE(componentsUtils.convertFromStorageResponse(readyForDistribution, ComponentTypeEnum.SERVICE), envName); + .getResponseFormatByDE(componentsUtils.convertFromStorageResponse(readyForDistribution, ComponentTypeEnum.SERVICE), envName); result = Either.right(response); } componentsUtils.auditComponent(response, user, service, AuditingActionEnum.DISTRIBUTION_STATE_CHANGE_REQUEST, - new ResourceCommonInfo(service.getName(), ComponentTypeEnum.SERVICE.getValue()), - ResourceVersionInfo.newBuilder().distributionStatus(dcurrStatus).build(), - ResourceVersionInfo.newBuilder().distributionStatus(updatedStatus).build(), null, null, did); + new ResourceCommonInfo(service.getName(), ComponentTypeEnum.SERVICE.getValue()), + ResourceVersionInfo.newBuilder().distributionStatus(dcurrStatus).build(), + ResourceVersionInfo.newBuilder().distributionStatus(updatedStatus).build(), null, null, did); return result; } @@ -2333,9 +2335,6 @@ public class ServiceBusinessLogic extends ComponentBusinessLogic { return toscaOperationFacade.getLatestByServiceName(serviceName).isLeft(); } - public void updateService(Service service, Map<String, Object> map) { - } - interface ArtifactGenerator<CallVal> extends Callable<Either<CallVal, ResponseFormat>> { } diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ServiceImportBusinessLogic.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ServiceImportBusinessLogic.java index 3eca461970..ac14a3c683 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ServiceImportBusinessLogic.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ServiceImportBusinessLogic.java @@ -20,6 +20,7 @@ import static java.util.stream.Collectors.joining; import static java.util.stream.Collectors.toList; import static java.util.stream.Collectors.toMap; import static org.apache.commons.collections.CollectionUtils.isNotEmpty; +import static org.apache.hc.core5.http.HttpStatus.SC_BAD_REQUEST; import static org.openecomp.sdc.be.components.impl.ImportUtils.findFirstToscaMapElement; import static org.openecomp.sdc.be.components.impl.ImportUtils.findFirstToscaStringElement; import static org.openecomp.sdc.be.components.impl.ImportUtils.getPropertyJsonStringValue; @@ -30,7 +31,11 @@ import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonParser; import fj.data.Either; +import java.io.IOException; +import java.io.InputStream; +import java.lang.reflect.Method; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.EnumMap; @@ -48,6 +53,7 @@ import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicReference; import java.util.regex.Pattern; import java.util.stream.Collectors; +import javax.validation.constraints.NotNull; import lombok.Getter; import lombok.Setter; import org.apache.commons.collections.CollectionUtils; @@ -55,6 +61,8 @@ import org.apache.commons.collections.MapUtils; import org.apache.commons.lang3.StringEscapeUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.tuple.ImmutablePair; +import org.janusgraph.core.JanusGraph; +import org.janusgraph.core.JanusGraphTransaction; import org.json.simple.JSONObject; import org.openecomp.sdc.be.components.csar.CsarArtifactsAndGroupsBusinessLogic; import org.openecomp.sdc.be.components.csar.CsarBusinessLogic; @@ -63,6 +71,7 @@ import org.openecomp.sdc.be.components.csar.ServiceCsarInfo; import org.openecomp.sdc.be.components.impl.ArtifactsBusinessLogic.ArtifactOperationEnum; import org.openecomp.sdc.be.components.impl.artifact.ArtifactOperationInfo; import org.openecomp.sdc.be.components.impl.exceptions.BusinessLogicException; +import org.openecomp.sdc.be.components.impl.exceptions.ByActionStatusComponentException; import org.openecomp.sdc.be.components.impl.exceptions.ByResponseFormatComponentException; import org.openecomp.sdc.be.components.impl.exceptions.ComponentException; import org.openecomp.sdc.be.components.impl.model.ToscaTypeImportData; @@ -150,6 +159,7 @@ import org.openecomp.sdc.be.model.operations.impl.ArtifactTypeOperation; import org.openecomp.sdc.be.model.operations.impl.CapabilityTypeOperation; import org.openecomp.sdc.be.model.operations.impl.GroupTypeOperation; import org.openecomp.sdc.be.model.operations.impl.InterfaceLifecycleOperation; +import org.openecomp.sdc.be.model.operations.impl.ModelOperation; import org.openecomp.sdc.be.model.operations.impl.UniqueIdBuilder; import org.openecomp.sdc.be.model.tosca.ToscaPropertyType; import org.openecomp.sdc.be.resources.data.auditing.AuditingActionEnum; @@ -165,6 +175,8 @@ import org.openecomp.sdc.common.datastructure.Wrapper; import org.openecomp.sdc.common.kpi.api.ASDCKpiApi; import org.openecomp.sdc.common.log.wrappers.Logger; import org.openecomp.sdc.common.util.ValidationUtils; +import org.openecomp.sdc.common.zip.ZipUtils; +import org.openecomp.sdc.common.zip.exception.ZipException; import org.openecomp.sdc.exception.ResponseFormat; import org.springframework.beans.factory.annotation.Autowired; import org.yaml.snakeyaml.Yaml; @@ -210,8 +222,9 @@ public class ServiceImportBusinessLogic { private final CapabilityTypeImportManager capabilityTypeImportManager; private final CapabilityTypeOperation capabilityTypeOperation; private ApplicationDataTypeCache applicationDataTypeCache; - private InterfaceLifecycleOperation interfaceLifecycleTypeOperation; - private InterfaceLifecycleTypeImportManager interfaceLifecycleTypeImportManager; + private final InterfaceLifecycleOperation interfaceLifecycleTypeOperation; + private final InterfaceLifecycleTypeImportManager interfaceLifecycleTypeImportManager; + private final ModelOperation modelOperation; public ServiceImportBusinessLogic(final GroupBusinessLogic groupBusinessLogic, final ArtifactsBusinessLogic artifactsBusinessLogic, final ComponentsUtils componentsUtils, final ToscaOperationFacade toscaOperationFacade, @@ -228,7 +241,8 @@ public class ServiceImportBusinessLogic { final InterfaceLifecycleOperation interfaceLifecycleTypeOperation, final InterfaceLifecycleTypeImportManager interfaceLifecycleTypeImportManager, final CapabilityTypeImportManager capabilityTypeImportManager, - final CapabilityTypeOperation capabilityTypeOperation) { + final CapabilityTypeOperation capabilityTypeOperation, + final ModelOperation modelOperation) { this.componentsUtils = componentsUtils; this.toscaOperationFacade = toscaOperationFacade; this.serviceBusinessLogic = serviceBusinessLogic; @@ -254,6 +268,7 @@ public class ServiceImportBusinessLogic { this.interfaceLifecycleTypeImportManager = interfaceLifecycleTypeImportManager; this.capabilityTypeImportManager = capabilityTypeImportManager; this.capabilityTypeOperation = capabilityTypeOperation; + this.modelOperation = modelOperation; } @Autowired @@ -261,14 +276,64 @@ public class ServiceImportBusinessLogic { this.applicationDataTypeCache = applicationDataTypeCache; } + public Service updateServiceFromToscaTemplate(final String serviceId, final User modifier, final String data) { + final Either<Service, ResponseFormat> serviceResponseFormatEither = serviceBusinessLogic.getService(serviceId, modifier); + if (serviceResponseFormatEither.isRight()) { + throw new ByActionStatusComponentException(ActionStatus.SERVICE_NOT_FOUND, serviceId); + } + final Service serviceOriginal = serviceResponseFormatEither.left().value(); + final Map<String, String> metadata = (Map<String, String>) new Yaml().loadAs(data, Map.class).get("metadata"); + validateServiceMetadataBeforeCreate(serviceOriginal, metadata); + + final Service newService = cloneServiceIdentifications(serviceOriginal); + final Map<String, byte[]> payload = new HashMap<>(); + payload.put("Definitions/service-" + metadata.get("name") + "-template.yml", data.getBytes()); + updateServiceMetadata(newService, metadata); + return createService(newService, AuditingActionEnum.UPDATE_SERVICE_TOSCA_TEMPLATE, modifier, payload, null); + } + + private Service cloneServiceIdentifications(final Service serviceOriginal) { + final Service newService = new Service(serviceOriginal.getComponentMetadataDefinition()); + newService.setCategories(serviceOriginal.getCategories()); + newService.setInvariantUUID(serviceOriginal.getInvariantUUID()); + newService.setUniqueId(serviceOriginal.getUniqueId()); + newService.setName(serviceOriginal.getName()); + newService.setUUID(serviceOriginal.getUUID()); + return newService; + } + + private void validateServiceMetadataBeforeCreate(final Service service, final Map<String, String> metadata) { + if (MapUtils.isEmpty(metadata)) { + throw new ByActionStatusComponentException(ActionStatus.MISSING_SERVICE_METADATA); + } + final String uuid = metadata.get("UUID"); + if (!service.getUUID().equals(uuid)) { + throw new ByActionStatusComponentException(ActionStatus.UNCHANGEABLE_PROPERTY_ERROR, "UUID"); + } + final String invariantUUID = metadata.get("invariantUUID"); + if (!service.getInvariantUUID().equals(invariantUUID)) { + throw new ByActionStatusComponentException(ActionStatus.UNCHANGEABLE_PROPERTY_ERROR, "invariantUUID"); + } + final String name = metadata.get("name"); + if (!service.getName().equals(name)) { + throw new ByActionStatusComponentException(ActionStatus.UNCHANGEABLE_PROPERTY_ERROR, "name"); + } + final String version = metadata.get("template_version"); + if (!service.getVersion().equals(version)) { + throw new ByActionStatusComponentException(ActionStatus.UNCHANGEABLE_PROPERTY_ERROR, "template_version"); + } + } + public Service createService(Service service, AuditingActionEnum auditingAction, User user, Map<String, byte[]> csarUIPayload, String payloadName) { log.debug("enter createService"); - service.setCreatorUserId(user.getUserId()); - service.setState(LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT); - service.setVersion(INITIAL_VERSION); - service.setConformanceLevel(ConfigurationManager.getConfigurationManager().getConfiguration().getToscaConformanceLevel()); - service.setDistributionStatus(DistributionStatusEnum.DISTRIBUTION_NOT_APPROVED); + if (AuditingActionEnum.CREATE_SERVICE.equals(auditingAction)) { + service.setCreatorUserId(user.getUserId()); + service.setState(LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT); + service.setVersion(INITIAL_VERSION); + service.setConformanceLevel(ConfigurationManager.getConfigurationManager().getConfiguration().getToscaConformanceLevel()); + service.setDistributionStatus(DistributionStatusEnum.DISTRIBUTION_NOT_APPROVED); + } try { final var serviceBeforeCreate = serviceBusinessLogic.validateServiceBeforeCreate(service, user, auditingAction); if (serviceBeforeCreate.isRight()) { @@ -276,10 +341,12 @@ public class ServiceImportBusinessLogic { } log.debug("enter createService,validateServiceBeforeCreate success"); String csarUUID = payloadName == null ? service.getCsarUUID() : payloadName; - log.debug("enter createService,get csarUUID:{}", csarUUID); - csarBusinessLogic.validateCsarBeforeCreate(service, csarUUID); + if (AuditingActionEnum.CREATE_SERVICE.equals(auditingAction)) { + log.debug("enter createService,get csarUUID:{}", csarUUID); + csarBusinessLogic.validateCsarBeforeCreate(service, csarUUID); + } log.debug("CsarUUID is {} - going to create resource from CSAR", csarUUID); - return createServiceFromCsar(service, user, csarUIPayload, csarUUID); + return createServiceFromCsar(service, user, csarUIPayload, csarUUID, auditingAction); } catch (final ComponentException e) { log.debug("Exception occurred when createService: {}", e.getMessage(), e); throw e; @@ -289,10 +356,31 @@ public class ServiceImportBusinessLogic { } } - protected Service createServiceFromCsar(Service service, User user, Map<String, byte[]> csarUIPayload, String csarUUID) { + private void updateServiceMetadata(final Service service, final Map<String, String> metadata) { + metadata.entrySet().forEach(s -> { + final Optional<Method> find = + Arrays.stream(service.getClass().getMethods()).filter(method -> method.getName().equalsIgnoreCase("set" + s.getKey())).findAny(); + if (find.isPresent()) { + try { + find.get().invoke(service, s.getValue()); + } catch (final Exception e) { + log.warn("Unable to set '{}' with value '{}'", s.getKey(), s.getValue()); + } + } + }); + } + + protected Service createServiceFromCsar(Service service, User user, Map<String, byte[]> csarUIPayload, String csarUUID, + AuditingActionEnum auditingAction) { log.trace("************* created successfully from YAML, resource TOSCA "); try { - final ServiceCsarInfo csarInfo = csarBusinessLogic.getCsarInfo(service, null, user, csarUIPayload, csarUUID); + final ServiceCsarInfo csarInfo; + if (AuditingActionEnum.UPDATE_SERVICE_TOSCA_TEMPLATE.equals(auditingAction)) { + csarInfo = new ServiceCsarInfo(user, csarUUID, csarUIPayload, service.getName(), service.getModel(), + csarUIPayload.keySet().iterator().next(), new String(csarUIPayload.values().iterator().next()), true, modelOperation); + } else { + csarInfo = csarBusinessLogic.getCsarInfo(service, null, user, csarUIPayload, csarUUID, auditingAction); + } final String serviceModel = service.getModel(); final Map<String, Object> dataTypesToCreate = getDatatypesToCreate(serviceModel, csarInfo); if (MapUtils.isNotEmpty(dataTypesToCreate)) { @@ -325,7 +413,6 @@ public class ServiceImportBusinessLogic { } final Map<String, Object> capabilityTypesToCreate = getCapabilityTypesToCreate(serviceModel, csarInfo); - if (MapUtils.isNotEmpty(capabilityTypesToCreate)) { capabilityTypeImportManager.createCapabilityTypes(new Yaml().dump(capabilityTypesToCreate), serviceModel, true); } @@ -338,7 +425,7 @@ public class ServiceImportBusinessLogic { throw new ComponentException(findNodeTypesArtifactsToHandleRes.right().value()); } return createServiceFromYaml(service, csarInfo.getMainTemplateContent(), csarInfo.getMainTemplateName(), nodeTypesInfo, csarInfo, - findNodeTypesArtifactsToHandleRes.left().value(), true, false, null, user.getUserId()); + findNodeTypesArtifactsToHandleRes.left().value(), true, false, null, user.getUserId(), auditingAction); } catch (final ComponentException e) { log.debug("Exception occurred when createServiceFromCsar,error is:{}", e.getMessage(), e); throw e; @@ -624,8 +711,9 @@ public class ServiceImportBusinessLogic { protected Service createServiceFromYaml(Service service, String topologyTemplateYaml, String yamlName, Map<String, NodeTypeInfo> nodeTypesInfo, CsarInfo csarInfo, - Map<String, EnumMap<ArtifactsBusinessLogic.ArtifactOperationEnum, List<ArtifactDefinition>>> nodeTypesArtifactsToCreate, - boolean shouldLock, boolean inTransaction, String nodeName, final String userId) + Map<String, EnumMap<ArtifactOperationEnum, List<ArtifactDefinition>>> nodeTypesArtifactsToCreate, + boolean shouldLock, boolean inTransaction, String nodeName, final String userId, + AuditingActionEnum auditingAction) throws BusinessLogicException { List<ArtifactDefinition> createdArtifacts = new ArrayList<>(); Service createdService; @@ -641,7 +729,8 @@ public class ServiceImportBusinessLogic { csfyp.setNodeTypesInfo(nodeTypesInfo); csfyp.setCsarInfo(csarInfo); csfyp.setNodeName(nodeName); - createdService = createServiceAndRIsFromYaml(service, false, nodeTypesArtifactsToCreate, shouldLock, inTransaction, csfyp, userId); + createdService = createServiceAndRIsFromYaml(service, false, nodeTypesArtifactsToCreate, shouldLock, inTransaction, csfyp, userId, + auditingAction); log.debug("#createResourceFromYaml - The resource {} has been created ", service.getName()); } catch (ComponentException | BusinessLogicException e) { log.debug("Create Service from yaml failed", e); @@ -654,10 +743,11 @@ public class ServiceImportBusinessLogic { } protected Service createServiceAndRIsFromYaml(Service service, boolean isNormative, - Map<String, EnumMap<ArtifactsBusinessLogic.ArtifactOperationEnum, List<ArtifactDefinition>>> nodeTypesArtifactsToCreate, + Map<String, EnumMap<ArtifactOperationEnum, List<ArtifactDefinition>>> nodeTypesArtifactsToCreate, boolean shouldLock, boolean inTransaction, CreateServiceFromYamlParameter csfyp, - final String userId) + final String userId, AuditingActionEnum auditingAction) throws BusinessLogicException { + List<ArtifactDefinition> nodeTypesNewCreatedArtifacts = new ArrayList<>(); String yamlName = csfyp.getYamlName(); ParsedToscaYamlInfo parsedToscaYamlInfo = csfyp.getParsedToscaYamlInfo(); @@ -669,7 +759,6 @@ public class ServiceImportBusinessLogic { if (shouldLock) { Either<Boolean, ResponseFormat> lockResult = serviceBusinessLogic.lockComponentByName(service.getSystemName(), service, CREATE_RESOURCE); if (lockResult.isRight()) { - serviceImportParseLogic.rollback(inTransaction, service, createdArtifacts, nodeTypesNewCreatedArtifacts); throw new ComponentException(lockResult.right().value()); } log.debug("name is locked {} status = {}", service.getSystemName(), lockResult); @@ -687,7 +776,7 @@ public class ServiceImportBusinessLogic { service.setProperties(propertiesList); } log.trace("************* createResourceFromYaml before full create resource {}", yamlName); - service = serviceImportParseLogic.createServiceTransaction(service, csarInfo.getModifier(), isNormative); + service = serviceImportParseLogic.createServiceTransaction(service, csarInfo.getModifier(), isNormative, auditingAction); log.trace("************* Going to add inputs from yaml {}", yamlName); Map<String, InputDefinition> inputs = parsedToscaYamlInfo.getInputs(); service = serviceImportParseLogic.createInputsOnService(service, inputs); @@ -709,7 +798,6 @@ public class ServiceImportBusinessLogic { Either<Map<String, GroupDefinition>, ResponseFormat> validateUpdateVfGroupNamesRes = groupBusinessLogic.validateUpdateVfGroupNames(parsedToscaYamlInfo.getGroups(), service.getSystemName()); if (validateUpdateVfGroupNamesRes.isRight()) { - serviceImportParseLogic.rollback(inTransaction, service, createdArtifacts, nodeTypesNewCreatedArtifacts); throw new ComponentException(validateUpdateVfGroupNamesRes.right().value()); } Map<String, GroupDefinition> groups; @@ -721,23 +809,19 @@ public class ServiceImportBusinessLogic { } Either<Service, ResponseFormat> createGroupsOnResource = createGroupsOnResource(service, groups); if (createGroupsOnResource.isRight()) { - serviceImportParseLogic.rollback(inTransaction, service, createdArtifacts, nodeTypesNewCreatedArtifacts); throw new ComponentException(createGroupsOnResource.right().value()); } service = createGroupsOnResource.left().value(); Either<Service, ResponseFormat> createPoliciesOnResource = createPoliciesOnResource(service, parsedToscaYamlInfo.getPolicies()); if (createPoliciesOnResource.isRight()) { - serviceImportParseLogic.rollback(inTransaction, service, createdArtifacts, nodeTypesNewCreatedArtifacts); throw new ComponentException(createPoliciesOnResource.right().value()); } service = createPoliciesOnResource.left().value(); log.trace("************* Going to add artifacts from yaml {}", yamlName); - NodeTypeInfoToUpdateArtifacts nodeTypeInfoToUpdateArtifacts = new NodeTypeInfoToUpdateArtifacts(nodeName, nodeTypesArtifactsToCreate); Either<Service, ResponseFormat> createArtifactsEither = createOrUpdateArtifacts(ArtifactsBusinessLogic.ArtifactOperationEnum.CREATE, - createdArtifacts, yamlName, csarInfo, service, nodeTypeInfoToUpdateArtifacts, inTransaction, shouldLock); + createdArtifacts, yamlName, csarInfo, service, inTransaction, shouldLock); if (createArtifactsEither.isRight()) { - serviceImportParseLogic.rollback(inTransaction, service, createdArtifacts, nodeTypesNewCreatedArtifacts); throw new ComponentException(createArtifactsEither.right().value()); } service = serviceImportParseLogic.getServiceWithGroups(createArtifactsEither.left().value().getUniqueId()); @@ -1196,7 +1280,6 @@ public class ServiceImportBusinessLogic { protected Either<Service, ResponseFormat> createOrUpdateArtifacts(ArtifactOperationEnum operation, List<ArtifactDefinition> createdArtifacts, String yamlFileName, CsarInfo csarInfo, Service preparedService, - NodeTypeInfoToUpdateArtifacts nodeTypeInfoToUpdateArtifacts, boolean inTransaction, boolean shouldLock) { Either<Service, ResponseFormat> createdCsarArtifactsEither = handleVfCsarArtifacts(preparedService, csarInfo, createdArtifacts, new ArtifactOperationInfo(false, false, operation), shouldLock, inTransaction); diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ServiceImportManager.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ServiceImportManager.java index 595603ec07..1e26f4caf2 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ServiceImportManager.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ServiceImportManager.java @@ -19,31 +19,22 @@ */ package org.openecomp.sdc.be.components.impl; -import javax.servlet.ServletContext; +import lombok.Getter; import org.openecomp.sdc.be.datatypes.components.ServiceMetadataDataDefinition; -import org.openecomp.sdc.be.impl.WebAppContextWrapper; import org.openecomp.sdc.be.model.Service; import org.openecomp.sdc.be.model.UploadServiceInfo; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; -import org.springframework.web.context.WebApplicationContext; //upload Service model by Shiyong1989@hotmail.com @Component("ServiceImportManager") +@Getter public class ServiceImportManager { - private ServletContext servletContext; - private ResponseFormatManager responseFormatManager; - @Autowired - private ServiceBusinessLogic serviceBusinessLogic; - @Autowired - private ServiceImportBusinessLogic serviceImportBusinessLogic; + private final ServiceBusinessLogic serviceBusinessLogic; + private final ServiceImportBusinessLogic serviceImportBusinessLogic; - public ServiceImportBusinessLogic getServiceImportBusinessLogic() { - return serviceImportBusinessLogic; - } - - public void setServiceImportBusinessLogic(ServiceImportBusinessLogic serviceImportBusinessLogic) { + public ServiceImportManager(ServiceBusinessLogic serviceBusinessLogic, ServiceImportBusinessLogic serviceImportBusinessLogic) { + this.serviceBusinessLogic = serviceBusinessLogic; this.serviceImportBusinessLogic = serviceImportBusinessLogic; } @@ -51,14 +42,6 @@ public class ServiceImportManager { return serviceBusinessLogic.isServiceExist(serviceName); } - public ServiceBusinessLogic getServiceBusinessLogic() { - return serviceBusinessLogic; - } - - public void setServiceBusinessLogic(ServiceBusinessLogic serviceBusinessLogic) { - this.serviceBusinessLogic = serviceBusinessLogic; - } - public void populateServiceMetadata(UploadServiceInfo serviceMetaData, Service service) { if (service != null && serviceMetaData != null) { service.setDescription(serviceMetaData.getDescription()); @@ -70,13 +53,13 @@ public class ServiceImportManager { service.setIcon(serviceMetaData.getServiceIconPath()); service.setServiceVendorModelNumber(serviceMetaData.getServiceVendorModelNumber()); ServiceMetadataDataDefinition serviceMetadataDataDefinition = (ServiceMetadataDataDefinition) service.getComponentMetadataDefinition() - .getMetadataDataDefinition(); + .getMetadataDataDefinition(); serviceMetadataDataDefinition.getServiceVendorModelNumber(); service.setServiceType(serviceMetaData.getServiceType()); service.setServiceRole(serviceMetaData.getServiceRole()); service.setNamingPolicy(serviceMetaData.getNamingPolicy()); boolean ecompGeneratedNaming = serviceMetaData.getEcompGeneratedNaming() == null - || serviceMetaData.getEcompGeneratedNaming().equals("true"); + || serviceMetaData.getEcompGeneratedNaming().equals("true"); service.setEcompGeneratedNaming(ecompGeneratedNaming); service.setServiceFunction(serviceMetaData.getServiceFunction()); service.setInstantiationType(serviceMetaData.getInstantiationType()); @@ -95,18 +78,4 @@ public class ServiceImportManager { } } - public synchronized void init(ServletContext servletContext) { - if (this.servletContext == null) { - this.servletContext = servletContext; - responseFormatManager = ResponseFormatManager.getInstance(); - serviceBusinessLogic = getServiceBL(servletContext); - } - } - - private ServiceBusinessLogic getServiceBL(ServletContext context) { - WebAppContextWrapper webApplicationContextWrapper = (WebAppContextWrapper) context - .getAttribute(org.openecomp.sdc.common.api.Constants.WEB_APPLICATION_CONTEXT_WRAPPER_ATTR); - WebApplicationContext webApplicationContext = webApplicationContextWrapper.getWebAppContext(context); - return webApplicationContext.getBean(ServiceBusinessLogic.class); - } } diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ServiceImportParseLogic.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ServiceImportParseLogic.java index 41babdfba5..3c82df4a50 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ServiceImportParseLogic.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ServiceImportParseLogic.java @@ -15,7 +15,22 @@ */ package org.openecomp.sdc.be.components.impl; +import static java.util.stream.Collectors.joining; +import static java.util.stream.Collectors.toList; +import static java.util.stream.Collectors.toMap; +import static org.apache.commons.collections.CollectionUtils.isNotEmpty; + import fj.data.Either; +import java.util.ArrayList; +import java.util.EnumMap; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.ListIterator; +import java.util.Map; +import java.util.Optional; +import java.util.Set; +import java.util.function.Function; import lombok.Getter; import org.apache.commons.codec.binary.Base64; import org.apache.commons.collections.CollectionUtils; @@ -74,7 +89,6 @@ import org.openecomp.sdc.be.model.Service; import org.openecomp.sdc.be.model.UploadCapInfo; import org.openecomp.sdc.be.model.UploadComponentInstanceInfo; import org.openecomp.sdc.be.model.UploadInfo; -import org.openecomp.sdc.be.model.UploadInterfaceInfo; import org.openecomp.sdc.be.model.UploadNodeFilterInfo; import org.openecomp.sdc.be.model.UploadPropInfo; import org.openecomp.sdc.be.model.UploadReqInfo; @@ -103,22 +117,6 @@ import org.openecomp.sdc.exception.ResponseFormat; import org.yaml.snakeyaml.DumperOptions; import org.yaml.snakeyaml.Yaml; -import java.util.ArrayList; -import java.util.EnumMap; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.ListIterator; -import java.util.Map; -import java.util.Optional; -import java.util.Set; -import java.util.function.Function; - -import static java.util.stream.Collectors.joining; -import static java.util.stream.Collectors.toList; -import static java.util.stream.Collectors.toMap; -import static org.apache.commons.collections.CollectionUtils.isNotEmpty; - @Getter @org.springframework.stereotype.Component public class ServiceImportParseLogic { @@ -516,7 +514,8 @@ public class ServiceImportParseLogic { while (intItr.hasNext() && eitherResult.isLeft()) { InterfaceDefinition interfaceDefinition = intItr.next(); String intType = interfaceDefinition.getUniqueId(); - Either<InterfaceDefinition, StorageOperationStatus> eitherCapTypeFound = interfaceTypeOperation.getInterface(UniqueIdBuilder.buildInterfaceTypeUid(resource.getModel(), intType)); + Either<InterfaceDefinition, StorageOperationStatus> eitherCapTypeFound = interfaceTypeOperation.getInterface( + UniqueIdBuilder.buildInterfaceTypeUid(resource.getModel(), intType)); if (eitherCapTypeFound.isRight()) { if (eitherCapTypeFound.right().value() == StorageOperationStatus.NOT_FOUND) { BeEcompErrorManager.getInstance() @@ -1400,32 +1399,40 @@ public class ServiceImportParseLogic { } - public Service createServiceTransaction(Service service, User user, boolean isNormative) { - // validate resource name uniqueness - log.debug("validate resource name"); - Either<Boolean, StorageOperationStatus> eitherValidation = toscaOperationFacade - .validateComponentNameExists(service.getName(), null, service.getComponentType()); - if (eitherValidation.isRight()) { - log.debug("Failed to validate component name {}. Status is {}. ", service.getName(), eitherValidation.right().value()); - ResponseFormat errorResponse = componentsUtils - .getResponseFormat(componentsUtils.convertFromStorageResponse(eitherValidation.right().value())); - throw new ComponentException(errorResponse); - } - if (eitherValidation.left().value()) { - log.debug("resource with name: {}, already exists", service.getName()); - ResponseFormat errorResponse = componentsUtils - .getResponseFormat(ActionStatus.COMPONENT_NAME_ALREADY_EXIST, ComponentTypeEnum.RESOURCE.getValue(), service.getName()); - throw new ComponentException(errorResponse); + public Service createServiceTransaction(Service service, User user, boolean isNormative, AuditingActionEnum auditingAction) { + if (!AuditingActionEnum.UPDATE_SERVICE_TOSCA_TEMPLATE.equals(auditingAction) && + !AuditingActionEnum.UPDATE_SERVICE_TOSCA_MODEL.equals(auditingAction)) { + // validate resource name uniqueness + log.debug("validate resource name"); + Either<Boolean, StorageOperationStatus> eitherValidation = toscaOperationFacade + .validateComponentNameExists(service.getName(), null, service.getComponentType()); + if (eitherValidation.isRight()) { + log.debug("Failed to validate component name {}. Status is {}. ", service.getName(), eitherValidation.right().value()); + ResponseFormat errorResponse = componentsUtils + .getResponseFormat(componentsUtils.convertFromStorageResponse(eitherValidation.right().value())); + throw new ComponentException(errorResponse); + } + if (eitherValidation.left().value()) { + log.debug("resource with name: {}, already exists", service.getName()); + ResponseFormat errorResponse = componentsUtils + .getResponseFormat(ActionStatus.COMPONENT_NAME_ALREADY_EXIST, ComponentTypeEnum.RESOURCE.getValue(), service.getName()); + throw new ComponentException(errorResponse); + } } log.debug("send resource {} to dao for create", service.getName()); createArtifactsPlaceHolderData(service, user); // enrich object - if (!isNormative) { + if (!isNormative && !AuditingActionEnum.UPDATE_SERVICE_TOSCA_TEMPLATE.equals(auditingAction) && + !AuditingActionEnum.UPDATE_SERVICE_TOSCA_MODEL.equals(auditingAction)) { log.debug("enrich resource with creator, version and state"); service.setLifecycleState(LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT); service.setVersion(INITIAL_VERSION); service.setHighestVersion(true); } + if (AuditingActionEnum.UPDATE_SERVICE_TOSCA_TEMPLATE.equals(auditingAction) || + AuditingActionEnum.UPDATE_SERVICE_TOSCA_MODEL.equals(auditingAction)) { + toscaOperationFacade.deleteService(service.getInvariantUUID(), false); + } return toscaOperationFacade.createToscaComponent(service).left().on(r -> throwComponentExceptionByResource(r, service)); } @@ -2010,19 +2017,20 @@ public class ServiceImportParseLogic { } public void associateComponentInstanceInterfacesToComponent( - String yamlName, - Service service, - Map<String, Map<String, InterfaceDefinition>> instInterfaces + String yamlName, + Service service, + Map<String, Map<String, InterfaceDefinition>> instInterfaces ) { if (MapUtils.isNotEmpty(instInterfaces)) { Either<Map<String, MapInterfaceDataDefinition>, StorageOperationStatus> addInterfaceToInst = - toscaOperationFacade + toscaOperationFacade .associateComponentInstanceInterfacesToComponent( - instInterfaces, - service.getUniqueId() + instInterfaces, + service.getUniqueId() ); if (addInterfaceToInst.isRight()) { - log.error("failed to associate interfaces value of service {}, status is {}", service.getUniqueId(), addInterfaceToInst.right().value()); + log.error("failed to associate interfaces value of service {}, status is {}", service.getUniqueId(), + addInterfaceToInst.right().value()); throw new ComponentException( componentsUtils.getResponseFormat( componentsUtils.convertFromStorageResponse( diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/validation/component/ComponentNameValidator.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/validation/component/ComponentNameValidator.java index 3ca768bad2..4b20c3d6a6 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/validation/component/ComponentNameValidator.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/validation/component/ComponentNameValidator.java @@ -65,7 +65,9 @@ public class ComponentNameValidator implements ComponentFieldValidator { log.debug("Component name {} has invalid format", componentName); auditErrorAndThrow(user, component, actionEnum, ActionStatus.INVALID_COMPONENT_NAME); } - if (component.getComponentType().equals(ComponentTypeEnum.SERVICE)) { + if (component.getComponentType().equals(ComponentTypeEnum.SERVICE) && + !AuditingActionEnum.UPDATE_SERVICE_TOSCA_TEMPLATE.equals(actionEnum) && + !AuditingActionEnum.UPDATE_SERVICE_TOSCA_MODEL.equals(actionEnum)) { validateComponentNameUnique(user, component, actionEnum); } //TODO remove assignment here diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/AbstractValidationsServlet.java b/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/AbstractValidationsServlet.java index 58d1b23bd6..ade8637715 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/AbstractValidationsServlet.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/AbstractValidationsServlet.java @@ -712,7 +712,7 @@ public abstract class AbstractValidationsServlet extends BeGenericServlet { private void getAndValidateComponentCsarYaml(Map<String, byte[]> csarUIPayload, Component component, User user, String csarUUID) { Either<ImmutablePair<String, String>, ResponseFormat> getToscaYamlRes = CsarValidationUtils - .getToscaYaml(csarUIPayload, csarUUID, getComponentsUtils()); + .getToscaYaml(csarUIPayload, csarUUID, getComponentsUtils(), null); if (getToscaYamlRes.isRight()) { ResponseFormat responseFormat = getToscaYamlRes.right().value(); log.debug("Error when try to get csar toscayamlFile with csar ID {}, error: {}", csarUUID, responseFormat); diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ServiceServlet.java b/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ServiceServlet.java index 3c2b72be2a..746c9b1dfa 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ServiceServlet.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ServiceServlet.java @@ -19,6 +19,7 @@ */ package org.openecomp.sdc.be.servlets; +import static org.apache.hc.core5.http.HttpStatus.SC_BAD_REQUEST; import static org.openecomp.sdc.common.log.enums.EcompLoggerErrorCode.BUSINESS_PROCESS_ERROR; import com.fasterxml.jackson.core.JsonProcessingException; @@ -37,6 +38,7 @@ import io.swagger.v3.oas.annotations.tags.Tag; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; +import java.io.InputStream; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.List; @@ -45,6 +47,7 @@ import java.util.Set; import javax.inject.Inject; import javax.servlet.ServletContext; import javax.servlet.http.HttpServletRequest; +import javax.validation.constraints.NotNull; import javax.ws.rs.Consumes; import javax.ws.rs.DELETE; import javax.ws.rs.GET; @@ -58,14 +61,17 @@ import javax.ws.rs.QueryParam; import javax.ws.rs.core.Context; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; +import org.apache.commons.collections4.MapUtils; import org.apache.http.HttpStatus; import org.glassfish.jersey.media.multipart.FormDataContentDisposition; import org.glassfish.jersey.media.multipart.FormDataParam; +import org.keycloak.representations.AccessToken; import org.openecomp.sdc.be.components.impl.ComponentInstanceBusinessLogic; import org.openecomp.sdc.be.components.impl.ElementBusinessLogic; import org.openecomp.sdc.be.components.impl.ResourceBusinessLogic; import org.openecomp.sdc.be.components.impl.ResourceImportManager; import org.openecomp.sdc.be.components.impl.ServiceBusinessLogic; +import org.openecomp.sdc.be.components.impl.ServiceImportBusinessLogic; 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.ByResponseFormatComponentException; @@ -97,7 +103,8 @@ import org.openecomp.sdc.common.util.Multitenancy; import org.openecomp.sdc.common.zip.exception.ZipException; import org.openecomp.sdc.exception.ResponseFormat; import org.springframework.stereotype.Controller; -import org.keycloak.representations.AccessToken; +import org.yaml.snakeyaml.Yaml; + @Loggable(prepend = true, value = Loggable.DEBUG, trim = false) @Path("/v1/catalog") @Server(url = "/sdc2/rest") @@ -130,7 +137,7 @@ public class ServiceServlet extends AbstractValidationsServlet { @ApiResponse(responseCode = "201", description = "Service created"), @ApiResponse(responseCode = "403", description = "Restricted operation"), @ApiResponse(responseCode = "400", description = "Invalid content / Missing content"), @ApiResponse(responseCode = "409", description = "Service already exist"), - @ApiResponse(responseCode = "401", description = "Unauthorized Tenant")}) + @ApiResponse(responseCode = "401", description = "Unauthorized Tenant")}) @PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE) public Response createService(@Parameter(description = "Service object to be created", required = true) String data, @Context final HttpServletRequest request, @HeaderParam(value = Constants.USER_ID_HEADER) String userId) { @@ -157,7 +164,7 @@ public class ServiceServlet extends AbstractValidationsServlet { throw new ByResponseFormatComponentException(actionResponse.right().value()); } loggerSupportability.log(LoggerSupportabilityActions.CREATE_SERVICE, service.getComponentMetadataForSupportLog(), StatusCode.COMPLETE, - "Service {} has been created by user {} ", service.getName(), userId); + "Service {} has been created by user {} ", service.getName(), userId); return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.CREATED), actionResponse.left().value()); } else { log.debug("Unauthorized Tenant"); @@ -170,14 +177,14 @@ public class ServiceServlet extends AbstractValidationsServlet { throw new ByResponseFormatComponentException(actionResponse.right().value()); } loggerSupportability.log(LoggerSupportabilityActions.CREATE_SERVICE, service.getComponentMetadataForSupportLog(), StatusCode.COMPLETE, - "Service {} has been created by user {} ", service.getName(), userId); + "Service {} has been created by user {} ", service.getName(), userId); return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.CREATED), actionResponse.left().value()); } } public Either<Service, ResponseFormat> parseToService(String serviceJson, User user) { return getComponentsUtils() - .convertJsonToObjectUsingObjectMapper(serviceJson, user, Service.class, AuditingActionEnum.CREATE_RESOURCE, ComponentTypeEnum.SERVICE); + .convertJsonToObjectUsingObjectMapper(serviceJson, user, Service.class, AuditingActionEnum.CREATE_SERVICE, ComponentTypeEnum.SERVICE); } @GET @@ -806,5 +813,38 @@ public class ServiceServlet extends AbstractValidationsServlet { } } + + @PUT + @Path("/services/{serviceId}/toscaTemplate") + @Tag(name = "SDCE-2 APIs") + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + @Operation(description = "Update service by tosca template import", method = "PUT", summary = "Returns updated service", + responses = { + @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Service.class)))), + @ApiResponse(responseCode = "200", description = "Service Updated"), + @ApiResponse(responseCode = "403", description = "Restricted operation"), + @ApiResponse(responseCode = "400", description = "Invalid content / Missing content")}) + @PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE) + public Response importToscaTemplate(@PathParam("serviceId") final String serviceId, + @Parameter(description = "Service object to be Updated", required = true) final String data, + @Context final HttpServletRequest request, + @HeaderParam(value = Constants.USER_ID_HEADER) final String userId) throws IOException { + initSpringFromContext(); + final String url = request.getMethod() + " " + request.getRequestURI(); + log.debug(START_HANDLE_REQUEST_OF, url); + final User modifier = new User(userId); + log.debug(MODIFIER_ID_IS, userId); + try { + final ServiceImportBusinessLogic serviceImportBusinessLogic = serviceImportManager.getServiceImportBusinessLogic(); + final Service updatedService = serviceImportBusinessLogic.updateServiceFromToscaTemplate(serviceId, modifier, data); + return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), RepresentationUtils.toRepresentation(updatedService)); + } catch (Exception e) { + BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Update Service Metadata"); + log.debug("update service metadata failed with exception", e); + throw e; + } + } + public enum Action {DELETE, MARK_AS_DELETE} } diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ServiceUploadServlet.java b/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ServiceUploadServlet.java index 99c539357e..bfb6a2f95f 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ServiceUploadServlet.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ServiceUploadServlet.java @@ -21,14 +21,15 @@ package org.openecomp.sdc.be.servlets; import com.jcabi.aspects.Loggable; import io.swagger.v3.oas.annotations.tags.Tag; -import io.swagger.v3.oas.annotations.tags.Tags; -import javax.inject.Singleton; -import javax.ws.rs.Path; +import lombok.AllArgsConstructor; +import lombok.Getter; import org.openecomp.sdc.be.components.impl.ComponentInstanceBusinessLogic; import org.openecomp.sdc.be.components.impl.ResourceImportManager; import org.openecomp.sdc.be.impl.ComponentsUtils; import org.openecomp.sdc.be.impl.ServletUtils; -import org.openecomp.sdc.common.log.wrappers.Logger; + +import javax.inject.Singleton; +import javax.ws.rs.Path; /** * Root service (exposed at "/" path) @@ -37,7 +38,7 @@ import org.openecomp.sdc.common.log.wrappers.Logger; //upload Service model by Shiyong1989@hotmail.com @Loggable(prepend = true, value = Loggable.DEBUG, trim = false) @Path("/v1/catalog/uploadservice") -@Tags({@Tag(name = "SDCE-2 APIs")}) +@Tag(name = "SDCE-2 APIs") @Singleton public class ServiceUploadServlet extends AbstractValidationsServlet { @@ -45,46 +46,22 @@ public class ServiceUploadServlet extends AbstractValidationsServlet { public static final String CSAR_TYPE_SERVICE = "csar"; public static final String USER_TYPE_SERVICE = "user-service"; public static final String USER_TYPE_SERVICE_UI_IMPORT = "user-servcie-ui-import"; - private static final Logger log = Logger.getLogger(ServiceUploadServlet.class); public ServiceUploadServlet(ComponentInstanceBusinessLogic componentInstanceBL, ComponentsUtils componentsUtils, ServletUtils servletUtils, ResourceImportManager resourceImportManager) { super(componentInstanceBL, componentsUtils, servletUtils, resourceImportManager); } + @AllArgsConstructor + @Getter public enum ServiceAuthorityTypeEnum { - NORMATIVE_TYPE_BE(NORMATIVE_TYPE_SERVICE, true, false), USER_TYPE_BE(USER_TYPE_SERVICE, true, true), USER_TYPE_UI(USER_TYPE_SERVICE_UI_IMPORT, - false, true), CSAR_TYPE_BE(CSAR_TYPE_SERVICE, true, true); - private String urlPath; - private boolean isBackEndImport, isUserTypeService; - - private ServiceAuthorityTypeEnum(String urlPath, boolean isBackEndImport, boolean isUserTypeService) { - this.urlPath = urlPath; - this.isBackEndImport = isBackEndImport; - this.isUserTypeService = isUserTypeService; - } - - public static ServiceAuthorityTypeEnum findByUrlPath(String urlPath) { - ServiceAuthorityTypeEnum found = null; - for (ServiceAuthorityTypeEnum curr : ServiceAuthorityTypeEnum.values()) { - if (curr.getUrlPath().equals(urlPath)) { - found = curr; - break; - } - } - return found; - } - - public String getUrlPath() { - return urlPath; - } - - public boolean isBackEndImport() { - return isBackEndImport; - } + NORMATIVE_TYPE_BE(NORMATIVE_TYPE_SERVICE, true, false), + USER_TYPE_BE(USER_TYPE_SERVICE, true, true), + USER_TYPE_UI(USER_TYPE_SERVICE_UI_IMPORT, false, true), + CSAR_TYPE_BE(CSAR_TYPE_SERVICE, true, true); + private final String urlPath; + private final boolean isBackEndImport; + private final boolean isUserTypeService; - public boolean isUserTypeService() { - return isUserTypeService; - } } } diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/ToscaExportHandler.java b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/ToscaExportHandler.java index 540ea6ec5c..fa7d2a0d83 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/ToscaExportHandler.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/ToscaExportHandler.java @@ -557,12 +557,12 @@ public class ToscaExportHandler { } } - private Map<String, String> convertMetadata(Component component) { + private Map<String, Object> convertMetadata(Component component) { return convertMetadata(component, false, null); } - private Map<String, String> convertMetadata(Component component, boolean isInstance, ComponentInstance componentInstance) { - Map<String, String> toscaMetadata = new LinkedHashMap<>(); + private Map<String, Object> convertMetadata(Component component, boolean isInstance, ComponentInstance componentInstance) { + Map<String, Object> toscaMetadata = new LinkedHashMap<>(); toscaMetadata.put(convertMetadataKey(JsonPresentationFields.INVARIANT_UUID), component.getInvariantUUID()); toscaMetadata.put(JsonPresentationFields.UUID.getPresentation(), component.getUUID()); toscaMetadata @@ -619,9 +619,7 @@ public class ToscaExportHandler { toscaMetadata.put(JsonPresentationFields.INSTANTIATION_TYPE.getPresentation(), service.getEnvironmentContext() == null ? StringUtils.EMPTY : service.getInstantiationType()); if (!isInstance) { - // DE268546 - toscaMetadata.put(JsonPresentationFields.ECOMP_GENERATED_NAMING.getPresentation(), service.isEcompGeneratedNaming().toString()); - toscaMetadata.put(JsonPresentationFields.ECOMP_GENERATED_NAMING.getPresentation(), service.isEcompGeneratedNaming().toString()); + toscaMetadata.put(JsonPresentationFields.ECOMP_GENERATED_NAMING.getPresentation(), service.isEcompGeneratedNaming()); toscaMetadata.put(JsonPresentationFields.NAMING_POLICY.getPresentation(), service.getNamingPolicy()); } break; diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/model/ToscaNodeTemplate.java b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/model/ToscaNodeTemplate.java index 6fd660e2aa..eb34732db9 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/model/ToscaNodeTemplate.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/model/ToscaNodeTemplate.java @@ -37,7 +37,7 @@ public class ToscaNodeTemplate { private List<Object> occurrences; private Map<String, String> instance_count; private List<String> directives; - private Map<String, String> metadata; + private Map<String, Object> metadata; private String description; private Map<String, Object> properties; private Map<String, Object> attributes; diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/model/ToscaTemplate.java b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/model/ToscaTemplate.java index f60b22cd69..56db48e489 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/model/ToscaTemplate.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/model/ToscaTemplate.java @@ -31,7 +31,7 @@ import org.openecomp.sdc.be.model.Component; public class ToscaTemplate { private String tosca_definitions_version; - private Map<String, String> metadata; + private Map<String, Object> metadata; private List<Map<String, Map<String, String>>> imports; private Map<String, Object> interface_types; private Map<String, ToscaDataType> data_types; diff --git a/catalog-be/src/main/resources/config/error-configuration.yaml b/catalog-be/src/main/resources/config/error-configuration.yaml index d77f98ed28..ad8adce5fc 100644 --- a/catalog-be/src/main/resources/config/error-configuration.yaml +++ b/catalog-be/src/main/resources/config/error-configuration.yaml @@ -2895,3 +2895,18 @@ errors: message: "Error: Uploaded YAML file is invalid.\n%1", messageId: "SVC4010" } + + #---------SVC4019----------------------------- + # %1 - metadata property name + UNCHANGEABLE_PROPERTY_ERROR: { + code: 402, + message: "Error: '%1' cannot change", + messageId: "SVC4019" + } + + #---------SVC4020----------------------------- + MISSING_SERVICE_METADATA: { + code: 402, + message: "Error: Missing metadata in Service", + messageId: "SVC4020" + } |