diff options
43 files changed, 823 insertions, 121 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 b277aeef2f..c87e1e394b 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 @@ -2495,3 +2495,27 @@ errors: message: "Could not read imports zip.", messageId: "SVC4147" } + + #---------SVC4148------------------------------ + # %1 - "Model name" + MODEL_NOT_FOUND: { + code: 404, + message: "Error: Model name '%1' not found. Please, make sure the model is created.", + messageId: "SVC4148" + } + + #---------SVC4149------------------------------ + MODEL_NAME_CANNOT_BE_EMPTY: { + code: 409, + message: "Error: Model name cannot be empty.", + messageId: "SVC4149" + } + + #-----------SVC4150--------------------------- + # %1 - "Component name" + # %2 - "Model name" + COMPONENT_WITH_MODEL_ALREADY_EXIST: { + code: 409, + message: "Error: Component %1 with Model %2 already exist.", + messageId: "SVC4150" + } diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ComponentInstanceBusinessLogic.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ComponentInstanceBusinessLogic.java index 2e54ff7adb..bce343efaf 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ComponentInstanceBusinessLogic.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ComponentInstanceBusinessLogic.java @@ -425,7 +425,7 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic { } private Component getOrigComponentForServiceProxy(org.openecomp.sdc.be.model.Component containerComponent, ComponentInstance resourceInstance) { - Either<Component, StorageOperationStatus> serviceProxyOrigin = toscaOperationFacade.getLatestByName(SERVICE_PROXY); + Either<Component, StorageOperationStatus> serviceProxyOrigin = toscaOperationFacade.getLatestByName(SERVICE_PROXY, null); if (isServiceProxyOrigin(serviceProxyOrigin)) { throw new ByActionStatusComponentException(componentsUtils.convertFromStorageResponse(serviceProxyOrigin.right().value())); } @@ -527,7 +527,7 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic { validateInstanceName(resourceInstance); if (originType == OriginTypeEnum.ServiceProxy) { log.debug("enter createRealComponentInstance,originType equals ServiceProxy"); - Either<Component, StorageOperationStatus> serviceProxyOrigin = toscaOperationFacade.getLatestByName(SERVICE_PROXY); + Either<Component, StorageOperationStatus> serviceProxyOrigin = toscaOperationFacade.getLatestByName(SERVICE_PROXY, null); if (isServiceProxyOrigin(serviceProxyOrigin)) { throw new ByActionStatusComponentException(componentsUtils.convertFromStorageResponse(serviceProxyOrigin.right().value())); } @@ -2839,7 +2839,7 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic { newComponentInstance.setOriginType(originType); if (originType == OriginTypeEnum.ServiceProxy) { Either<Component, StorageOperationStatus> serviceProxyOrigin = toscaOperationFacade - .getLatestByName(SERVICE_PROXY); + .getLatestByName(SERVICE_PROXY, null); if (isServiceProxyOrigin(serviceProxyOrigin)) { throw new ByActionStatusComponentException( componentsUtils.convertFromStorageResponse(serviceProxyOrigin.right().value())); diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ModelBusinessLogic.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ModelBusinessLogic.java index a048af4ac8..6eb806d3d1 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ModelBusinessLogic.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ModelBusinessLogic.java @@ -34,6 +34,10 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; + +/** + * This class is responsible for handling the business logic of a Model. + */ @Component("modelBusinessLogic") public class ModelBusinessLogic { 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 99ceb2158e..f5b890e438 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 @@ -19,7 +19,6 @@ */ 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 java.util.stream.Collectors.toSet; @@ -44,6 +43,7 @@ import java.util.List; import java.util.ListIterator; import java.util.Map; import java.util.Map.Entry; +import java.util.Objects; import java.util.Optional; import java.util.Set; import java.util.function.Function; @@ -1314,6 +1314,7 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { resourceMetaData.setContactId(user.getUserId()); resourceMetaData.setVendorName(resourceVf.getVendorName()); resourceMetaData.setVendorRelease(resourceVf.getVendorRelease()); + resourceMetaData.setModel(resourceVf.getModel()); // Setting tag final List<String> tags = new ArrayList<>(); tags.add(resourceMetaData.getName()); @@ -1346,6 +1347,7 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { cvfc.setCreatorUserId(csarInfo.getModifier().getUserId()); cvfc.setVendorName(resourceVf.getVendorName()); cvfc.setVendorRelease(resourceVf.getVendorRelease()); + cvfc.setModel(resourceVf.getModel()); cvfc.setResourceVendorModelNumber(resourceVf.getResourceVendorModelNumber()); cvfc.setToscaResourceName(buildNestedToscaResourceName(ResourceTypeEnum.CVFC.name(), csarInfo.getVfResourceName(), nodeName).getLeft()); cvfc.setInvariantUUID(UniqueIdBuilder.buildInvariantUUID()); @@ -1892,7 +1894,7 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { throw e; } } - + private boolean nodeTypeAlreadyExists(final String toscaResourceName) { return toscaOperationFacade.getLatestByToscaResourceName(toscaResourceName).isLeft(); } @@ -3277,10 +3279,11 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { ImmutablePair<Resource, ActionStatus> result = null; // check if resource already exists (search by tosca name = type) final boolean isNestedResource = isNestedResourceUpdate(csarInfo, nodeName); + final String resourceName = resource.getToscaResourceName(); final Either<Resource, StorageOperationStatus> latestByToscaName = toscaOperationFacade - .getLatestByToscaResourceName(resource.getToscaResourceName()); - if (latestByToscaName.isLeft()) { - Resource foundResource = latestByToscaName.left().value(); + .getLatestByToscaResourceNameAndModel(resourceName, resource.getModel()); + if (latestByToscaName.isLeft() && Objects.nonNull(latestByToscaName.left().value())) { + final Resource foundResource = latestByToscaName.left().value(); // we don't allow updating names of top level types if (!isNestedResource && !StringUtils.equals(resource.getName(), foundResource.getName())) { BeEcompErrorManager.getInstance() @@ -3349,7 +3352,7 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { } public boolean isResourceExist(String resourceName) { - Either<Resource, StorageOperationStatus> latestByName = toscaOperationFacade.getLatestByName(resourceName); + Either<Resource, StorageOperationStatus> latestByName = toscaOperationFacade.getLatestByName(resourceName, null); return latestByName.isLeft(); } @@ -3464,6 +3467,9 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { if (newResource.getResourceVendorModelNumber() == null) { newResource.setResourceVendorModelNumber(oldResource.getResourceVendorModelNumber()); } + if (newResource.getModel() == null) { + newResource.setModel(oldResource.getModel()); + } if (newResource.getContactId() == null) { newResource.setContactId(oldResource.getContactId()); } @@ -3749,10 +3755,12 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { } private Resource createResourceTransaction(Resource resource, User user, boolean isNormative) { - // validate resource name uniqueness - log.debug("validate resource name"); - Either<Boolean, StorageOperationStatus> eitherValidation = toscaOperationFacade - .validateComponentNameExists(resource.getName(), resource.getResourceType(), resource.getComponentType()); + final String resourceName = resource.getName(); + final String modelName = resource.getModel(); + final ResourceTypeEnum resourceType = resource.getResourceType(); + final ComponentTypeEnum componentType = resource.getComponentType(); + final Either<Boolean, StorageOperationStatus> eitherValidation = toscaOperationFacade + .validateComponentNameAndModelExists(resourceName, modelName, resourceType, componentType); if (eitherValidation.isRight()) { loggerSupportability.log(LoggerSupportabilityActions.VALIDATE_NAME, resource.getComponentMetadataForSupportLog(), StatusCode.ERROR, "ERROR while validate component name {} Status is: {}", resource.getName(), eitherValidation.right().value()); 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 b1841e55d8..77d8f897e7 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 @@ -171,19 +171,7 @@ public class ResourceImportManager { setMetaDataFromJson(resourceMetaData, resource); populateResourceFromYaml(resourceYml, resource); validationFunction.apply(resource); - if (!createNewVersion) { - Either<Resource, StorageOperationStatus> latestByName = toscaOperationFacade.getLatestByName(resource.getName()); - if (latestByName.isLeft()) { - throw new ByActionStatusComponentException(ActionStatus.COMPONENT_NAME_ALREADY_EXIST, resource.getName()); - } - } else if (!isCsarPresent(csarInfo)) { - final Either<Resource, StorageOperationStatus> component = toscaOperationFacade - .getComponentByNameAndVendorRelease(resource.getComponentType(), resource.getName(), resource.getVendorRelease(), - JsonParseFlagEnum.ParseAll); - if (component.isLeft()) { - throw new ByActionStatusComponentException(ActionStatus.COMPONENT_VERSION_ALREADY_EXIST, resource.getName()); - } - } + checkResourceExistsBeforeCreate(createNewVersion, csarInfo, resource); resource = resourceBusinessLogic .createOrUpdateResourceByImport(resource, creator, true, isInTransaction, needLock, csarInfo, nodeName, isNested).left; Resource changeStateResponse; @@ -210,6 +198,35 @@ public class ResourceImportManager { return responsePair; } + private void checkResourceExistsBeforeCreate(final boolean createNewVersion, final CsarInfo csarInfo, final Resource resource) { + final String resourceName = resource.getName(); + final String model = resource.getModel(); + final Either<Resource, StorageOperationStatus> latestByToscaName = toscaOperationFacade + .getLatestByToscaResourceNameAndModel(resourceName, model); + if (latestByToscaName.isLeft()) { + final Resource foundResource = latestByToscaName.left().value(); + validateComponentWithModelExist(resourceName, model, foundResource); + if (!createNewVersion) { + throw new ByActionStatusComponentException(ActionStatus.COMPONENT_NAME_ALREADY_EXIST, resourceName); + } + if (!isCsarPresent(csarInfo)) { + final Either<Resource, StorageOperationStatus> component = toscaOperationFacade + .getComponentByNameAndVendorRelease(resource.getComponentType(), resource.getName(), resource.getVendorRelease(), + JsonParseFlagEnum.ParseAll); + if (component.isLeft()) { + validateComponentWithModelExist(resourceName, model, foundResource); + throw new ByActionStatusComponentException(ActionStatus.COMPONENT_VERSION_ALREADY_EXIST, resource.getName()); + } + } + } + } + + private void validateComponentWithModelExist(final String resourceName, final String model, final Resource foundResource) { + if (model != null && toscaOperationFacade.isNodeAssociatedToModel(model, foundResource).isPresent()) { + throw new ByActionStatusComponentException(ActionStatus.COMPONENT_WITH_MODEL_ALREADY_EXIST, resourceName, model); + } + } + private boolean isCsarPresent(final CsarInfo csarInfo) { return csarInfo != null && StringUtils.isNotEmpty(csarInfo.getCsarUUID()); } @@ -246,6 +263,9 @@ public class ResourceImportManager { if (resourceMetaData.getVendorRelease() != null) { resource.setVendorRelease(resourceMetaData.getVendorRelease()); } + if (resourceMetaData.getModel() != null) { + resource.setModel(resourceMetaData.getModel()); + } } } 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 a87fdb6ca7..ccaadbad76 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 @@ -994,7 +994,7 @@ public class ServiceBusinessLogic extends ComponentBusinessLogic { private Component getForwardingPathOriginComponent() { Either<Component, StorageOperationStatus> forwardingPathOrigin = toscaOperationFacade - .getLatestByName(ForwardingPathUtils.FORWARDING_PATH_NODE_NAME); + .getLatestByName(ForwardingPathUtils.FORWARDING_PATH_NODE_NAME, null); if (forwardingPathOrigin.isRight()) { StorageOperationStatus errorStatus = forwardingPathOrigin.right().value(); log.debug("Failed to fetch normative forwarding path resource by tosca name, error {}", errorStatus); diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/exceptions/UploadResourceException.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/exceptions/UploadResourceException.java new file mode 100644 index 0000000000..de7a47c85c --- /dev/null +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/exceptions/UploadResourceException.java @@ -0,0 +1,30 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2021 Nordix Foundation + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package org.openecomp.sdc.be.components.impl.exceptions; + +import lombok.Data; +import org.openecomp.sdc.be.exception.BusinessException; +import org.openecomp.sdc.exception.ResponseFormat; + +@Data +public class UploadResourceException extends BusinessException { + + private final ResponseFormat responseFormat; + +} diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ResourceUploadServlet.java b/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ResourceUploadServlet.java index 9cf8f67089..bdc9ffce43 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ResourceUploadServlet.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ResourceUploadServlet.java @@ -27,11 +27,8 @@ import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.servers.Server; -import io.swagger.v3.oas.annotations.servers.Servers; import io.swagger.v3.oas.annotations.tags.Tag; -import io.swagger.v3.oas.annotations.tags.Tags; import java.io.File; -import java.io.FileNotFoundException; import javax.inject.Inject; import javax.servlet.http.HttpServletRequest; import javax.ws.rs.Consumes; @@ -48,19 +45,23 @@ import javax.ws.rs.core.Response; import org.glassfish.jersey.media.multipart.FormDataContentDisposition; import org.glassfish.jersey.media.multipart.FormDataParam; import org.openecomp.sdc.be.components.impl.ComponentInstanceBusinessLogic; +import org.openecomp.sdc.be.components.impl.ModelBusinessLogic; import org.openecomp.sdc.be.components.impl.ResourceImportManager; import org.openecomp.sdc.be.components.impl.aaf.AafPermission; import org.openecomp.sdc.be.components.impl.aaf.PermissionAllowed; import org.openecomp.sdc.be.config.BeEcompErrorManager; +import org.openecomp.sdc.be.dao.api.ActionStatus; +import org.openecomp.sdc.be.exception.BusinessException; import org.openecomp.sdc.be.impl.ComponentsUtils; import org.openecomp.sdc.be.impl.ServletUtils; import org.openecomp.sdc.be.model.UploadResourceInfo; import org.openecomp.sdc.be.model.User; +import org.openecomp.sdc.be.model.jsonjanusgraph.operations.exception.ModelOperationExceptionSupplier; import org.openecomp.sdc.be.user.UserBusinessLogic; import org.openecomp.sdc.common.api.Constants; import org.openecomp.sdc.common.datastructure.Wrapper; -import org.openecomp.sdc.common.log.wrappers.Logger; -import org.openecomp.sdc.common.zip.exception.ZipException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.stereotype.Controller; /** @@ -68,8 +69,8 @@ import org.springframework.stereotype.Controller; */ @Loggable(prepend = true, value = Loggable.DEBUG, trim = false) @Path("/v1/catalog/upload") -@Tags({@Tag(name = "SDCE-2 APIs")}) -@Servers({@Server(url = "/sdc2/rest")}) +@Tag(name = "SDCE-2 APIs") +@Server(url = "/sdc2/rest") @Controller public class ResourceUploadServlet extends AbstractValidationsServlet { @@ -77,12 +78,16 @@ public class ResourceUploadServlet extends AbstractValidationsServlet { public static final String CSAR_TYPE_RESOURCE = "csar"; public static final String USER_TYPE_RESOURCE = "user-resource"; public static final String USER_TYPE_RESOURCE_UI_IMPORT = "user-resource-ui-import"; - private static final Logger log = Logger.getLogger(ResourceUploadServlet.class); + private static final Logger log = LoggerFactory.getLogger(ResourceUploadServlet.class); + + private ModelBusinessLogic modelBusinessLogic; @Inject public ResourceUploadServlet(UserBusinessLogic userBusinessLogic, ComponentInstanceBusinessLogic componentInstanceBL, - ComponentsUtils componentsUtils, ServletUtils servletUtils, ResourceImportManager resourceImportManager) { + ComponentsUtils componentsUtils, ServletUtils servletUtils, ResourceImportManager resourceImportManager, + ModelBusinessLogic modelBusinessLogic) { super(userBusinessLogic, componentInstanceBL, componentsUtils, servletUtils, resourceImportManager); + this.modelBusinessLogic = modelBusinessLogic; } @POST @@ -103,8 +108,8 @@ public class ResourceUploadServlet extends AbstractValidationsServlet { @Parameter(description = "ContentDisposition") @FormDataParam("resourceZip") FormDataContentDisposition contentDispositionHeader, @Parameter(description = "resourceMetadata") @FormDataParam("resourceMetadata") String resourceInfoJsonString, @Context final HttpServletRequest request, @HeaderParam(value = Constants.USER_ID_HEADER) String userId, - // updateResourse Query Parameter if false checks if already exist - @DefaultValue("true") @QueryParam("createNewVersion") boolean createNewVersion) throws FileNotFoundException, ZipException { + // updateResource Query Parameter if false checks if already exist + @DefaultValue("true") @QueryParam("createNewVersion") boolean createNewVersion) { try { Wrapper<Response> responseWrapper = new Wrapper<>(); Wrapper<User> userWrapper = new Wrapper<>(); @@ -112,12 +117,14 @@ public class ResourceUploadServlet extends AbstractValidationsServlet { Wrapper<String> yamlStringWrapper = new Wrapper<>(); String url = request.getMethod() + " " + request.getRequestURI(); log.debug("Start handle request of {}", url); - // When we get an errorResponse it will be filled into the - - // responseWrapper + // When we get an errorResponse it will be filled into the responseWrapper validateAuthorityType(responseWrapper, resourceAuthority); ResourceAuthorityTypeEnum resourceAuthorityEnum = ResourceAuthorityTypeEnum.findByUrlPath(resourceAuthority); commonGeneralValidations(responseWrapper, userWrapper, uploadResourceInfoWrapper, resourceAuthorityEnum, userId, resourceInfoJsonString); + final String modelNameToBeAssociated = uploadResourceInfoWrapper.getInnerElement().getModel(); + if (modelNameToBeAssociated != null) { + validateModel(modelNameToBeAssociated); + } fillPayload(responseWrapper, uploadResourceInfoWrapper, yamlStringWrapper, userWrapper.getInnerElement(), resourceInfoJsonString, resourceAuthorityEnum, file); // PayLoad Validations @@ -132,10 +139,23 @@ public class ResourceUploadServlet extends AbstractValidationsServlet { yamlStringWrapper.getInnerElement(), resourceAuthorityEnum, createNewVersion, null); } return responseWrapper.getInnerElement(); - } catch (Exception e) { - BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Upload Resource"); - log.debug("upload resource failed with exception", e); + } catch (final BusinessException e) { throw e; + } catch (final Exception e) { + var errorMsg = String.format("Unexpected error while uploading Resource '%s'", resourceInfoJsonString); + BeEcompErrorManager.getInstance().logBeRestApiGeneralError(errorMsg); + log.error(errorMsg, e); + return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR)); + } + } + + /** + * The Model field is an optional entry when uploading a resource. If the field is present, it validates if the Model name exists. + * @param modelName Model names declared on the resource json representation + */ + private void validateModel(final String modelName) { + if (modelBusinessLogic.findModel(modelName).isEmpty()) { + throw ModelOperationExceptionSupplier.invalidModel(modelName).get(); } } @@ -148,7 +168,8 @@ public class ResourceUploadServlet extends AbstractValidationsServlet { // @formatter:on private String urlPath; - private boolean isBackEndImport, isUserTypeResource; + private boolean isBackEndImport; + private boolean isUserTypeResource; public static ResourceAuthorityTypeEnum findByUrlPath(String urlPath) { ResourceAuthorityTypeEnum found = null; @@ -161,7 +182,7 @@ public class ResourceUploadServlet extends AbstractValidationsServlet { return found; } - private ResourceAuthorityTypeEnum(String urlPath, boolean isBackEndImport, boolean isUserTypeResource) { + ResourceAuthorityTypeEnum(String urlPath, boolean isBackEndImport, boolean isUserTypeResource) { this.urlPath = urlPath; this.isBackEndImport = isBackEndImport; this.isUserTypeResource = isUserTypeResource; 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 f193510485..52ced65996 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 @@ -472,6 +472,7 @@ public class ToscaExportHandler { toscaMetadata.put(JsonPresentationFields.RESOURCE_VENDOR.getPresentation(), resource.getVendorName()); toscaMetadata.put(JsonPresentationFields.RESOURCE_VENDOR_RELEASE.getPresentation(), resource.getVendorRelease()); toscaMetadata.put(JsonPresentationFields.RESOURCE_VENDOR_MODEL_NUMBER.getPresentation(), resource.getResourceVendorModelNumber()); + toscaMetadata.put(JsonPresentationFields.MODEL.getPresentation(), resource.getModel()); break; case SERVICE: Service service = (Service) component; @@ -1122,7 +1123,7 @@ public class ToscaExportHandler { return res; } Either<Resource, StorageOperationStatus> serviceProxyOrigin = toscaOperationFacade - .getLatestByName("serviceProxy"); + .getLatestByName("serviceProxy", null); if (serviceProxyOrigin.isRight()) { log.debug("Failed to fetch normative service proxy resource by tosca name, error {}", serviceProxyOrigin.right().value()); diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/model/ToscaMetadata.java b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/model/ToscaMetadata.java index 97dab3649e..54d382ff82 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/model/ToscaMetadata.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/model/ToscaMetadata.java @@ -44,6 +44,7 @@ public class ToscaMetadata implements IToscaMetadata { private String sourceModelName; private String sourceModelUuid; private String serviceFunction; + private String model; public String getName() { return name; @@ -232,4 +233,12 @@ public class ToscaMetadata implements IToscaMetadata { public void setEnvironmentContext(String environmentContext) { this.environmentContext = environmentContext; } + + public String getModel() { + return model; + } + + public void setModel(String model) { + this.model = model; + } } diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/components/ResourceImportManagerTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/components/ResourceImportManagerTest.java index 622027df30..f56ff2e5b9 100644 --- a/catalog-be/src/test/java/org/openecomp/sdc/be/components/ResourceImportManagerTest.java +++ b/catalog-be/src/test/java/org/openecomp/sdc/be/components/ResourceImportManagerTest.java @@ -28,9 +28,9 @@ import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; -import static org.mockito.Mockito.when; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.when; import fj.data.Either; import java.io.IOException; @@ -38,6 +38,7 @@ import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; +import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.tuple.ImmutablePair; import org.junit.Before; import org.junit.BeforeClass; @@ -57,7 +58,6 @@ import org.openecomp.sdc.be.components.lifecycle.LifecycleChangeInfoWithAction; import org.openecomp.sdc.be.config.Configuration; import org.openecomp.sdc.be.config.ConfigurationManager; import org.openecomp.sdc.be.dao.api.ActionStatus; -import org.openecomp.sdc.be.dao.janusgraph.JanusGraphOperationStatus; import org.openecomp.sdc.be.dao.jsongraph.types.JsonParseFlagEnum; import org.openecomp.sdc.be.datatypes.elements.OperationDataDefinition; import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum; @@ -106,6 +106,7 @@ public class ResourceImportManagerTest { importManager = new ResourceImportManager(componentsUtils, capabilityTypeOperation, interfaceDefinitionHandler); importManager.setAuditingManager(auditingManager); when(toscaOperationFacade.getLatestByToscaResourceName(Mockito.anyString())).thenReturn(Either.left(null)); + when(toscaOperationFacade.getLatestByToscaResourceNameAndModel(Mockito.anyString(), Mockito.any())).thenReturn(Either.left(null)); importManager.setResponseFormatManager(responseFormatManager); importManager.setResourceBusinessLogic(resourceBusinessLogic); importManager.setToscaOperationFacade(toscaOperationFacade); @@ -123,7 +124,8 @@ public class ResourceImportManagerTest { public void beforeTest() { Mockito.reset(auditingManager, responseFormatManager, resourceBusinessLogic, userAdmin); Either<Component, StorageOperationStatus> notFound = Either.right(StorageOperationStatus.NOT_FOUND); - when(toscaOperationFacade.getComponentByNameAndVendorRelease(any(ComponentTypeEnum.class), anyString(), anyString(), any(JsonParseFlagEnum.class))).thenReturn(notFound); + when(toscaOperationFacade.getComponentByNameAndVendorRelease(any(ComponentTypeEnum.class), anyString(), anyString(), + any(JsonParseFlagEnum.class))).thenReturn(notFound); } @Test @@ -301,12 +303,15 @@ public class ResourceImportManagerTest { setResourceBusinessLogicMock(); Either<Component, StorageOperationStatus> notFound = Either.left(Mockito.mock(Resource.class)); - when(toscaOperationFacade.getComponentByNameAndVendorRelease(any(ComponentTypeEnum.class), anyString(), anyString(), any(JsonParseFlagEnum.class))).thenReturn(notFound); + when(toscaOperationFacade.getComponentByNameAndVendorRelease(any(ComponentTypeEnum.class), anyString(), anyString(), + any(JsonParseFlagEnum.class))).thenReturn(notFound); String jsonContent = ImportUtilsTest.loadFileNameToJsonString("normative-types-new-blockStorage.yml"); ComponentException errorInfoFromTest = null; try { + when(toscaOperationFacade + .getLatestByToscaResourceNameAndModel(resourceMD.getName(), StringUtils.EMPTY)).thenReturn(Either.left(new Resource())); importManager.importNormativeResource(jsonContent, resourceMD, user, true, true); }catch (ComponentException e){ errorInfoFromTest = e; diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ResourceBusinessLogicTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ResourceBusinessLogicTest.java index 17078bcb75..fe2f3ba983 100644 --- a/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ResourceBusinessLogicTest.java +++ b/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ResourceBusinessLogicTest.java @@ -45,7 +45,6 @@ import java.util.Optional; import java.util.stream.Collectors; import java.util.stream.Stream; import javax.servlet.ServletContext; - import org.apache.commons.lang3.tuple.ImmutablePair; import org.junit.Assert; import org.junit.Before; @@ -90,7 +89,18 @@ import org.openecomp.sdc.be.datatypes.enums.ResourceTypeEnum; import org.openecomp.sdc.be.facade.operations.CatalogOperation; import org.openecomp.sdc.be.impl.ComponentsUtils; import org.openecomp.sdc.be.impl.WebAppContextWrapper; -import org.openecomp.sdc.be.model.*; +import org.openecomp.sdc.be.model.ArtifactDefinition; +import org.openecomp.sdc.be.model.Component; +import org.openecomp.sdc.be.model.ComponentParametersView; +import org.openecomp.sdc.be.model.DataTypeDefinition; +import org.openecomp.sdc.be.model.GroupDefinition; +import org.openecomp.sdc.be.model.InputDefinition; +import org.openecomp.sdc.be.model.LifeCycleTransitionEnum; +import org.openecomp.sdc.be.model.LifecycleStateEnum; +import org.openecomp.sdc.be.model.NodeTypeInfo; +import org.openecomp.sdc.be.model.PropertyDefinition; +import org.openecomp.sdc.be.model.Resource; +import org.openecomp.sdc.be.model.User; import org.openecomp.sdc.be.model.cache.ApplicationDataTypeCache; import org.openecomp.sdc.be.model.jsonjanusgraph.operations.ArtifactsOperations; import org.openecomp.sdc.be.model.jsonjanusgraph.operations.InterfaceOperation; @@ -455,6 +465,9 @@ public class ResourceBusinessLogicTest { Resource resource = createResourceObject(false); Resource createdResource = null; try { + when(toscaOperationFacade + .validateComponentNameAndModelExists(resource.getName(), null, ResourceTypeEnum.VFC, ComponentTypeEnum.RESOURCE)) + .thenReturn(Either.left(false)); createdResource = bl.createResource(resource, AuditingActionEnum.CREATE_RESOURCE, user, null, null); assertThat(createResourceObject(true)).isEqualTo(createdResource); } catch (ComponentException e) { @@ -561,6 +574,9 @@ public class ResourceBusinessLogicTest { resourceExist.getTags() .add(resourceName); validateUserRoles(Role.ADMIN, Role.DESIGNER); + when(toscaOperationFacade + .validateComponentNameAndModelExists(resourceName, null, ResourceTypeEnum.VFC, ComponentTypeEnum.RESOURCE)) + .thenReturn(Either.left(true)); try { bl.createResource(resourceExist, AuditingActionEnum.CREATE_RESOURCE, user, null, null); } catch (ComponentException e) { @@ -673,7 +689,9 @@ public class ResourceBusinessLogicTest { private void testResourceIconMissing() { Resource resourceExist = createResourceObject(false); resourceExist.setIcon(null); - + when(toscaOperationFacade + .validateComponentNameAndModelExists(resourceExist.getName(), null, ResourceTypeEnum.VFC, ComponentTypeEnum.RESOURCE)) + .thenReturn(Either.left(false)); try { bl.createResource(resourceExist, AuditingActionEnum.CREATE_RESOURCE, user, null, null); } catch (ComponentException e) { @@ -1541,6 +1559,9 @@ public class ResourceBusinessLogicTest { createRoot(); Resource resourceExist = createResourceObject(false); validateUserRoles(Role.ADMIN, Role.DESIGNER); + when(toscaOperationFacade + .validateComponentNameAndModelExists(resourceExist.getName(), null, ResourceTypeEnum.VFC, ComponentTypeEnum.RESOURCE)) + .thenReturn(Either.left(false)); Resource createdResource = bl.createResource(resourceExist, AuditingActionEnum.CREATE_RESOURCE, user, null, null); createdResource.setLastUpdaterUserId(user.getUserId()); @@ -1549,6 +1570,8 @@ public class ResourceBusinessLogicTest { Either<Component, StorageOperationStatus> getCompLatestResult = Either.left(createdResource); when(toscaOperationFacade.getLatestByToscaResourceName(resourceExist.getToscaResourceName())) .thenReturn(getCompLatestResult); + when(toscaOperationFacade.getLatestByToscaResourceNameAndModel(resourceExist.getToscaResourceName(), null)) + .thenReturn(getCompLatestResult); when(toscaOperationFacade.overrideComponent(any(Resource.class), any(Resource.class))) .thenReturn(getLatestResult); @@ -1570,6 +1593,9 @@ public class ResourceBusinessLogicTest { public void createOrUpdateResourceCertified() { createRoot(); Resource resourceExist = createResourceObject(false); + when(toscaOperationFacade + .validateComponentNameAndModelExists(resourceExist.getName(), null, ResourceTypeEnum.VFC, ComponentTypeEnum.RESOURCE)) + .thenReturn(Either.left(false)); validateUserRoles(Role.ADMIN, Role.DESIGNER); Resource createdResource = bl.createResource(resourceExist, AuditingActionEnum.CREATE_RESOURCE, user, null, null); @@ -1580,8 +1606,8 @@ public class ResourceBusinessLogicTest { Either<Resource, StorageOperationStatus> getLatestResult = Either.left(createdResource); Either<Component, StorageOperationStatus> getCompLatestResult = Either.left(createdResource); - when(toscaOperationFacade.getLatestByToscaResourceName(resourceExist.getToscaResourceName())) - .thenReturn(getCompLatestResult); + when(toscaOperationFacade.getLatestByToscaResourceNameAndModel(resourceExist.getToscaResourceName(), null)) + .thenReturn(getCompLatestResult); when(toscaOperationFacade.overrideComponent(any(Resource.class), any(Resource.class))) .thenReturn(getLatestResult); @@ -1608,12 +1634,12 @@ public class ResourceBusinessLogicTest { Resource resourceToUpdtae = createResourceObject(false); Either<Component, StorageOperationStatus> getLatestResult = Either.right(StorageOperationStatus.NOT_FOUND); - when(toscaOperationFacade.getLatestByName(resourceToUpdtae.getName())).thenReturn(getLatestResult); - - Either<Component, StorageOperationStatus> getLatestToscaNameResult = Either - .right(StorageOperationStatus.NOT_FOUND); - when(toscaOperationFacade.getLatestByToscaResourceName(resourceToUpdtae.getToscaResourceName())) - .thenReturn(getLatestToscaNameResult); + when(toscaOperationFacade.getLatestByName(resourceToUpdtae.getName(), null)).thenReturn(getLatestResult); + when(toscaOperationFacade.getLatestByToscaResourceNameAndModel(resourceToUpdtae.getToscaResourceName(), null)) + .thenReturn(Either.right(StorageOperationStatus.NOT_FOUND)); + when(toscaOperationFacade + .validateComponentNameAndModelExists(resourceToUpdtae.getName(), null, ResourceTypeEnum.VFC, ComponentTypeEnum.RESOURCE)) + .thenReturn(Either.left(false)); ImmutablePair<Resource, ActionStatus> createOrUpdateResource = bl .createOrUpdateResourceByImport(resourceToUpdtae, user, false, false, false, null, null, false); @@ -1651,13 +1677,19 @@ public class ResourceBusinessLogicTest { String nestedResourceName = bl.buildNestedToscaResourceName(resourceToUpdate.getResourceType() .name(), csarInfo.getVfResourceName(), nodeName) .getRight(); - when(toscaOperationFacade.getLatestByName(resourceToUpdate.getName())) + when(toscaOperationFacade.getLatestByName(resourceToUpdate.getName(), null)) .thenReturn(Either.right(StorageOperationStatus.NOT_FOUND)); when(toscaOperationFacade.getLatestByToscaResourceName(resourceToUpdate.getToscaResourceName())) .thenReturn(Either.right(StorageOperationStatus.NOT_FOUND)); when(toscaOperationFacade.getLatestByToscaResourceName(nestedResourceName)) .thenReturn(Either.right(StorageOperationStatus.NOT_FOUND)); + when(toscaOperationFacade.getLatestByToscaResourceNameAndModel(resourceToUpdate.getToscaResourceName(), null)) + .thenReturn(Either.right(StorageOperationStatus.NOT_FOUND)); + when(toscaOperationFacade + .validateComponentNameAndModelExists(resourceToUpdate.getName(), null, ResourceTypeEnum.VFC, ComponentTypeEnum.RESOURCE)) + .thenReturn(Either.left(false)); + ImmutablePair<Resource, ActionStatus> createOrUpdateResource = bl .createOrUpdateResourceByImport(resourceToUpdate, user, false, false, false, csarInfo, nodeName, false); assertThat(createOrUpdateResource).isNotNull(); @@ -1683,10 +1715,12 @@ public class ResourceBusinessLogicTest { String nestedResourceName = bl.buildNestedToscaResourceName(resourceToUpdate.getResourceType() .name(), csarInfo.getVfResourceName(), nodeName) .getRight(); - when(toscaOperationFacade.getLatestByName(resourceToUpdate.getName())) + when(toscaOperationFacade.getLatestByName(resourceToUpdate.getName(), null)) .thenReturn(Either.right(StorageOperationStatus.NOT_FOUND)); when(toscaOperationFacade.getLatestByToscaResourceName(resourceToUpdate.getToscaResourceName())) .thenReturn(Either.right(StorageOperationStatus.NOT_FOUND)); + when(toscaOperationFacade.getLatestByToscaResourceNameAndModel(resourceToUpdate.getToscaResourceName(), null)) + .thenReturn(Either.right(StorageOperationStatus.NOT_FOUND)); when(toscaOperationFacade.getLatestByToscaResourceName(nestedResourceName)) .thenReturn(Either.left(resourceResponse)); when(toscaOperationFacade.overrideComponent(any(Resource.class), any(Resource.class))) @@ -2067,6 +2101,9 @@ public class ResourceBusinessLogicTest { when(genericTypeBusinessLogic.generateInputsFromGenericTypeProperties(genericVF)).thenCallRealMethod(); when(genericTypeBusinessLogic.convertGenericTypePropertiesToInputsDefintion(genericVF.getProperties(), resource.getUniqueId())).thenCallRealMethod(); + when(toscaOperationFacade + .validateComponentNameAndModelExists(resource.getName(), null, ResourceTypeEnum.VF, ComponentTypeEnum.RESOURCE)) + .thenReturn(Either.left(false)); Resource createdResource = bl.createResource(resource, AuditingActionEnum.CREATE_RESOURCE, user, null, null); assertThat(createdResource).isNotNull(); return createdResource; @@ -2092,6 +2129,9 @@ public class ResourceBusinessLogicTest { when(genericTypeBusinessLogic.generateInputsFromGenericTypeProperties(genericCR)).thenCallRealMethod(); when(genericTypeBusinessLogic.convertGenericTypePropertiesToInputsDefintion(genericCR.getProperties(), resource.getUniqueId())).thenCallRealMethod(); + when(toscaOperationFacade + .validateComponentNameAndModelExists(resource.getName(), null, ResourceTypeEnum.CR, ComponentTypeEnum.RESOURCE)) + .thenReturn(Either.left(false)); Resource createdResource = bl.createResource(resource, AuditingActionEnum.CREATE_RESOURCE, user, null, null); assertThat(createdResource).isNotNull(); return createdResource; @@ -2110,6 +2150,9 @@ public class ResourceBusinessLogicTest { when(genericTypeBusinessLogic.generateInputsFromGenericTypeProperties(genericPNF)).thenCallRealMethod(); when(genericTypeBusinessLogic.convertGenericTypePropertiesToInputsDefintion(genericPNF.getProperties(), resource.getUniqueId())).thenCallRealMethod(); + when(toscaOperationFacade + .validateComponentNameAndModelExists(resource.getName(), null, ResourceTypeEnum.PNF, ComponentTypeEnum.RESOURCE)) + .thenReturn(Either.left(false)); Resource createdResource = bl.createResource(resource, AuditingActionEnum.CREATE_RESOURCE, user, null, null); assertThat(createdResource).isNotNull(); return createdResource; diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/components/path/beans/ForwardingPathToscaOperationFacade.java b/catalog-be/src/test/java/org/openecomp/sdc/be/components/path/beans/ForwardingPathToscaOperationFacade.java index 7102ed2d2b..3774332b23 100644 --- a/catalog-be/src/test/java/org/openecomp/sdc/be/components/path/beans/ForwardingPathToscaOperationFacade.java +++ b/catalog-be/src/test/java/org/openecomp/sdc/be/components/path/beans/ForwardingPathToscaOperationFacade.java @@ -21,6 +21,7 @@ package org.openecomp.sdc.be.components.path.beans; import fj.data.Either; +import org.apache.commons.lang3.StringUtils; import org.openecomp.sdc.be.impl.ForwardingPathUtils; import org.openecomp.sdc.be.model.Component; import org.openecomp.sdc.be.model.Resource; @@ -44,13 +45,13 @@ public class ForwardingPathToscaOperationFacade extends ToscaOperationFacade { } @Override - public <T extends Component> Either<T, StorageOperationStatus> getLatestByName(String resourceName) { + public <T extends Component> Either<T, StorageOperationStatus> getLatestByName(String resourceName, String model) { if(resourceName.equals(ForwardingPathUtils.FORWARDING_PATH_NODE_NAME) || resourceName.equals(ForwardingPathUtils.FORWARDER_CAPABILITY)){ Resource component = new Resource(); component.setToscaResourceName(GENERIC_SERVICE_NAME); return Either.left((T)component); } - return super.getLatestByName(resourceName); + return super.getLatestByName(resourceName, null); } @Override diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/components/path/utils/GraphTestUtils.java b/catalog-be/src/test/java/org/openecomp/sdc/be/components/path/utils/GraphTestUtils.java index be20beb595..0456988beb 100644 --- a/catalog-be/src/test/java/org/openecomp/sdc/be/components/path/utils/GraphTestUtils.java +++ b/catalog-be/src/test/java/org/openecomp/sdc/be/components/path/utils/GraphTestUtils.java @@ -73,6 +73,7 @@ public final class GraphTestUtils { vertex.addMetadataProperty(GraphPropertyEnum.UNIQUE_ID, uuid); vertex.addMetadataProperty(GraphPropertyEnum.COMPONENT_TYPE, ComponentTypeEnum.RESOURCE.name()); vertex.addMetadataProperty(GraphPropertyEnum.RESOURCE_TYPE, type.name()); + vertex.addMetadataProperty(GraphPropertyEnum.MODEL, type.name()); vertex.addMetadataProperty(GraphPropertyEnum.IS_ABSTRACT, false); for (Map.Entry<GraphPropertyEnum, Object> prop : metadataProps.entrySet()) { vertex.addMetadataProperty(prop.getKey(), prop.getValue()); diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/servlets/ArchiveEndpointTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/servlets/ArchiveEndpointTest.java index 4359270d53..faede3d9c5 100644 --- a/catalog-be/src/test/java/org/openecomp/sdc/be/servlets/ArchiveEndpointTest.java +++ b/catalog-be/src/test/java/org/openecomp/sdc/be/servlets/ArchiveEndpointTest.java @@ -92,6 +92,7 @@ import org.openecomp.sdc.be.model.jsonjanusgraph.operations.TopologyTemplateOper import org.openecomp.sdc.be.model.jsonjanusgraph.operations.ToscaOperationFacade; import org.openecomp.sdc.be.model.operations.api.IGraphLockOperation; import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus; +import org.openecomp.sdc.be.model.operations.impl.ModelOperation; import org.openecomp.sdc.be.servlets.exception.ComponentExceptionMapper; import org.openecomp.sdc.be.servlets.exception.DefaultExceptionMapper; import org.openecomp.sdc.be.servlets.exception.StorageExceptionMapper; @@ -261,6 +262,11 @@ class ArchiveEndpointTest extends JerseyTest { return new ContainerInstanceTypesData(); } + @Bean + ModelOperation modelOperation() { + return new ModelOperation(null, null, null); + } + private void initGraphForTest() { //Create Catalog Root catalogVertex = GraphTestUtils.createRootCatalogVertex(janusGraphDao); diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/servlets/ResourceUploadServletTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/servlets/ResourceUploadServletTest.java new file mode 100644 index 0000000000..31152c63e7 --- /dev/null +++ b/catalog-be/src/test/java/org/openecomp/sdc/be/servlets/ResourceUploadServletTest.java @@ -0,0 +1,289 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2021 Nordix Foundation + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package org.openecomp.sdc.be.servlets; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyBoolean; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.when; + +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import java.net.URISyntaxException; +import java.net.URL; +import java.util.Optional; +import javax.servlet.ServletContext; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpSession; +import javax.ws.rs.client.Entity; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.eclipse.jetty.http.HttpStatus; +import org.glassfish.hk2.utilities.binding.AbstractBinder; +import org.glassfish.jersey.client.ClientConfig; +import org.glassfish.jersey.media.multipart.FormDataMultiPart; +import org.glassfish.jersey.media.multipart.MultiPartFeature; +import org.glassfish.jersey.media.multipart.file.FileDataBodyPart; +import org.glassfish.jersey.server.ResourceConfig; +import org.glassfish.jersey.test.JerseyTest; +import org.glassfish.jersey.test.TestProperties; +import org.json.simple.JSONObject; +import org.json.simple.parser.JSONParser; +import org.json.simple.parser.ParseException; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.api.TestInstance.Lifecycle; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.openecomp.sdc.be.components.impl.ComponentInstanceBusinessLogic; +import org.openecomp.sdc.be.components.impl.ModelBusinessLogic; +import org.openecomp.sdc.be.components.impl.ResourceBusinessLogic; +import org.openecomp.sdc.be.components.impl.ResourceImportManager; +import org.openecomp.sdc.be.components.impl.ResponseFormatManager; +import org.openecomp.sdc.be.components.validation.UserValidations; +import org.openecomp.sdc.be.config.ConfigurationManager; +import org.openecomp.sdc.be.config.SpringConfig; +import org.openecomp.sdc.be.dao.api.ActionStatus; +import org.openecomp.sdc.be.impl.ComponentsUtils; +import org.openecomp.sdc.be.impl.ServletUtils; +import org.openecomp.sdc.be.impl.WebAppContextWrapper; +import org.openecomp.sdc.be.model.Model; +import org.openecomp.sdc.be.model.Resource; +import org.openecomp.sdc.be.model.User; +import org.openecomp.sdc.be.servlets.builder.ServletResponseBuilder; +import org.openecomp.sdc.be.servlets.exception.OperationExceptionMapper; +import org.openecomp.sdc.be.user.Role; +import org.openecomp.sdc.be.user.UserBusinessLogic; +import org.openecomp.sdc.common.api.ConfigurationSource; +import org.openecomp.sdc.common.api.Constants; +import org.openecomp.sdc.common.impl.ExternalConfiguration; +import org.openecomp.sdc.common.impl.FSConfigurationSource; +import org.openecomp.sdc.exception.ResponseFormat; +import org.springframework.context.ApplicationContext; +import org.springframework.context.annotation.AnnotationConfigApplicationContext; +import org.springframework.web.context.WebApplicationContext; + +@TestInstance(Lifecycle.PER_CLASS) +class ResourceUploadServletTest extends JerseyTest { + private static final String USER_ID = "cs0008"; + + @Mock + private HttpServletRequest request; + @Mock + private HttpSession session; + @Mock + private ServletContext servletContext; + @Mock + private WebAppContextWrapper webAppContextWrapper; + @Mock + private WebApplicationContext webApplicationContext; + @Mock + private UserBusinessLogic userBusinessLogic; + @Mock + private ComponentInstanceBusinessLogic componentInstanceBusinessLogic; + @Mock + private ComponentsUtils componentsUtils; + @Mock + private ServletUtils servletUtils; + @Mock + private ResourceImportManager resourceImportManager; + @Mock + private ResourceBusinessLogic resourceBusinessLogic; + @Mock + private ResponseFormat responseFormat; + @Mock + private UserValidations userValidations; + @Mock + private ModelBusinessLogic modelBusinessLogic; + @Mock + private ResponseFormatManager responseFormatManager; + private final String modelName = "ETSI-SOL001-331"; + + private final String rootPath = "/v1/catalog/upload/multipart"; + private Response response; + private User user; + + @BeforeAll + public void initClass() { + when(request.getSession()).thenReturn(session); + when(session.getServletContext()).thenReturn(servletContext); + when(servletContext.getAttribute(Constants.WEB_APPLICATION_CONTEXT_WRAPPER_ATTR)) + .thenReturn(webAppContextWrapper); + when(webAppContextWrapper.getWebAppContext(servletContext)).thenReturn(webApplicationContext); + when(webApplicationContext.getBean(ModelBusinessLogic.class)).thenReturn(modelBusinessLogic); + when(request.getHeader(Constants.USER_ID_HEADER)).thenReturn(USER_ID); + when(webApplicationContext.getBean(ServletUtils.class)).thenReturn(servletUtils); + when(servletUtils.getComponentsUtils()).thenReturn(componentsUtils); + final String appConfigDir = "src/test/resources/config/catalog-be"; + final ConfigurationSource configurationSource = new FSConfigurationSource(ExternalConfiguration.getChangeListener(), appConfigDir); + final ConfigurationManager configurationManager = new ConfigurationManager(configurationSource); + final org.openecomp.sdc.be.config.Configuration configuration = new org.openecomp.sdc.be.config.Configuration(); + configuration.setJanusGraphInMemoryGraph(true); + configurationManager.setConfiguration(configuration); + ExternalConfiguration.setAppName("catalog-be"); + } + + @BeforeEach + void resetMock() throws Exception { + super.setUp(); + initTestData(); + } + + @AfterEach + void after() throws Exception { + super.tearDown(); + } + + private void initTestData() { + user = new User(); + user.setUserId(USER_ID); + user.setRole(Role.ADMIN.name()); + when(userBusinessLogic.getUser(USER_ID)).thenReturn(user); + } + + @Override + protected ResourceConfig configure() { + MockitoAnnotations.openMocks(this); + forceSet(TestProperties.CONTAINER_PORT, "0"); + final ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class); + return new ResourceConfig(ResourceUploadServlet.class) + .register(new AbstractBinder() { + @Override + protected void configure() { + bind(request).to(HttpServletRequest.class); + bind(userBusinessLogic).to(UserBusinessLogic.class); + bind(componentInstanceBusinessLogic).to(ComponentInstanceBusinessLogic.class); + bind(componentsUtils).to(ComponentsUtils.class); + bind(servletUtils).to(ServletUtils.class); + bind(resourceImportManager).to(ResourceImportManager.class); + bind(resourceBusinessLogic).to(ResourceBusinessLogic.class); + bind(modelBusinessLogic).to(ModelBusinessLogic.class); + bind(userValidations).to(UserValidations.class); + } + }) + .register(new OperationExceptionMapper(new ServletResponseBuilder(), responseFormatManager)) + .register(MultiPartFeature.class) + .property("contextConfig", context); + } + + @Override + protected void configureClient(final ClientConfig config) { + config.register(MultiPartFeature.class); + } + + @Test + void uploadMultipartWithModelSuccessTest() throws IOException, ParseException, URISyntaxException { + when(responseFormat.getStatus()).thenReturn(HttpStatus.OK_200); + when(componentsUtils.getResponseFormat(ActionStatus.CREATED)).thenReturn(responseFormat); + when(servletUtils.getUserAdmin()).thenReturn(userBusinessLogic); + when(userBusinessLogic.getUser(anyString())).thenReturn(user); + when(resourceBusinessLogic.validatePropertiesDefaultValues(any())).thenReturn(true); + when(resourceImportManager.importNormativeResource(anyString(), any(), any(), anyBoolean(), anyBoolean())) + .thenReturn(new ImmutablePair<>(new Resource(), ActionStatus.CREATED)); + when(modelBusinessLogic.findModel(modelName)).thenReturn(Optional.of(new Model(modelName))); + response = target().path(rootPath).request(MediaType.APPLICATION_JSON) + .header(Constants.USER_ID_HEADER, USER_ID) + .post(Entity.entity(buildFormDataMultiPart("node-types/TestNodeType001.zip", + "src/test/resources/node-types/nodeTypeWithModelsField.json"), MediaType.MULTIPART_FORM_DATA), Response.class); + assertThat(response.getStatus()).isEqualTo(HttpStatus.OK_200); + } + + @Test + void uploadMultipartWithoutModelsFieldSuccessTest() throws IOException, ParseException, URISyntaxException { + when(responseFormat.getStatus()).thenReturn(HttpStatus.OK_200); + when(componentsUtils.getResponseFormat(ActionStatus.CREATED)).thenReturn(responseFormat); + when(servletUtils.getUserAdmin()).thenReturn(userBusinessLogic); + when(userBusinessLogic.getUser(anyString())).thenReturn(user); + when(resourceBusinessLogic.validatePropertiesDefaultValues(any())).thenReturn(true); + when(resourceImportManager.importNormativeResource(anyString(), any(), any(), anyBoolean(), anyBoolean())) + .thenReturn(new ImmutablePair<>(new Resource(), ActionStatus.CREATED)); + response = target().path(rootPath).request(MediaType.APPLICATION_JSON) + .header(Constants.USER_ID_HEADER, USER_ID) + .post(Entity.entity(buildFormDataMultiPart("node-types/TestNodeType002.zip", + "src/test/resources/node-types/nodeTypeWithoutModelsField.json"), MediaType.MULTIPART_FORM_DATA), Response.class); + assertThat(response.getStatus()).isEqualTo(HttpStatus.OK_200); + } + + @Test + void uploadMultipartFailWithEmptyModelsTest() throws IOException, ParseException, URISyntaxException { + when(servletUtils.getUserAdmin()).thenReturn(userBusinessLogic); + when(userBusinessLogic.getUser(anyString())).thenReturn(user); + when(resourceBusinessLogic.validatePropertiesDefaultValues(any())).thenReturn(true); + when(modelBusinessLogic.findModel("")).thenReturn(Optional.empty()); + response = target().path(rootPath).request(MediaType.APPLICATION_JSON) + .header(Constants.USER_ID_HEADER, USER_ID) + .post(Entity.entity(buildFormDataMultiPart("node-types/TestNodeType002.zip", + "src/test/resources/node-types/nodeTypeWithEmptyModels.json"), MediaType.MULTIPART_FORM_DATA), Response.class); + assertThat(response.getStatus()).isEqualTo(HttpStatus.INTERNAL_SERVER_ERROR_500); + } + + @Test + void uploadMultipartFailWithModelNotFoundTest() throws IOException, ParseException, URISyntaxException { + when(servletUtils.getUserAdmin()).thenReturn(userBusinessLogic); + when(userBusinessLogic.getUser(anyString())).thenReturn(user); + when(resourceBusinessLogic.validatePropertiesDefaultValues(any())).thenReturn(true); + when(modelBusinessLogic.findModel(modelName)).thenReturn(Optional.empty()); + response = target().path(rootPath).request(MediaType.APPLICATION_JSON) + .header(Constants.USER_ID_HEADER, USER_ID) + .post(Entity.entity(buildFormDataMultiPart("node-types/TestNodeType001.zip", + "src/test/resources/node-types/nodeTypeWithModelsField.json"), MediaType.MULTIPART_FORM_DATA), Response.class); + assertThat(response.getStatus()).isEqualTo(HttpStatus.INTERNAL_SERVER_ERROR_500); + } + + @Test + void uploadMultipartThrowsBusinessExceptionTest() throws IOException, ParseException, URISyntaxException { + when(servletUtils.getUserAdmin()).thenReturn(userBusinessLogic); + when(userBusinessLogic.getUser(anyString())).thenReturn(user); + when(resourceBusinessLogic.validatePropertiesDefaultValues(any())).thenReturn(true); + response = target().path(rootPath).request(MediaType.APPLICATION_JSON) + .header(Constants.USER_ID_HEADER, USER_ID) + .post(Entity.entity(buildFormDataMultiPart("node-types/TestNodeType001.zip", + "src/test/resources/node-types/invalid.json"), MediaType.MULTIPART_FORM_DATA), Response.class); + assertThat(response.getStatus()).isEqualTo(HttpStatus.INTERNAL_SERVER_ERROR_500); + } + + private String getInputData(final String jsonFilename) throws IOException, ParseException { + final JSONObject inputData = (JSONObject) new JSONParser().parse( + new FileReader(jsonFilename)); + return inputData.toJSONString(); + } + + private File getFile(final String fileName) throws URISyntaxException { + final URL resource = this.getClass().getClassLoader().getResource(fileName); + if (resource == null) { + throw new IllegalArgumentException("file not found! " + fileName); + } + return new File(resource.toURI()); + } + + private FormDataMultiPart buildFormDataMultiPart(final String zipFilePath, final String inputJsonData) + throws IOException, ParseException, URISyntaxException { + final FileDataBodyPart filePart = new FileDataBodyPart("resourceZip", getFile(zipFilePath)); + final FormDataMultiPart multipartEntity = new FormDataMultiPart(); + multipartEntity.bodyPart(filePart); + multipartEntity.field("resourceMetadata", getInputData(inputJsonData)); + return multipartEntity; + } +} diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/tosca/ToscaExportHandlerTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/tosca/ToscaExportHandlerTest.java index 202cf014fd..acd4cb4128 100644 --- a/catalog-be/src/test/java/org/openecomp/sdc/be/tosca/ToscaExportHandlerTest.java +++ b/catalog-be/src/test/java/org/openecomp/sdc/be/tosca/ToscaExportHandlerTest.java @@ -735,7 +735,7 @@ public class ToscaExportHandlerTest extends BeConfDependentTest { .thenReturn(Either.left(new ToscaNodeType())); when(toscaOperationFacade.getToscaFullElement("uid")).thenReturn(Either.left(component)); when(toscaOperationFacade.getToscaFullElement("sourceModelUid")).thenReturn(Either.left(component)); - when(toscaOperationFacade.getLatestByName("serviceProxy")).thenReturn(Either.left(new Resource())); + when(toscaOperationFacade.getLatestByName("serviceProxy", null)).thenReturn(Either.left(new Resource())); when(toscaOperationFacade.getToscaElement(any(String.class), any(ComponentParametersView.class))).thenReturn(Either.left(new Resource())); final Map<String, String[]> substitutionMappingMap = new HashMap<>(); @@ -859,7 +859,7 @@ public class ToscaExportHandlerTest extends BeConfDependentTest { .thenReturn(Either.left(new ToscaNodeType())); when(toscaOperationFacade.getToscaFullElement("uid")).thenReturn(Either.left(component)); when(toscaOperationFacade.getToscaFullElement("sourceModelUid")).thenReturn(Either.left(component)); - when(toscaOperationFacade.getLatestByName("serviceProxy")).thenReturn(Either.left(new Resource())); + when(toscaOperationFacade.getLatestByName("serviceProxy", null)).thenReturn(Either.left(new Resource())); when(toscaOperationFacade.getToscaElement(any(String.class), any(ComponentParametersView.class))).thenReturn(Either.left(new Resource())); final Map<String, String[]> substitutionMappingMap = new HashMap<>(); @@ -1135,7 +1135,7 @@ public class ToscaExportHandlerTest extends BeConfDependentTest { componentInstances.add(instance); container.setComponentInstances(componentInstances); - when(toscaOperationFacade.getLatestByName("serviceProxy")) + when(toscaOperationFacade.getLatestByName("serviceProxy", null)) .thenReturn(Either.right(StorageOperationStatus.BAD_REQUEST)); // test when getLatestByName return is right @@ -1188,7 +1188,7 @@ public class ToscaExportHandlerTest extends BeConfDependentTest { componentInstances.add(instance); container.setComponentInstances(componentInstances); - when(toscaOperationFacade.getLatestByName("serviceProxy")).thenReturn(Either.left(new Resource())); + when(toscaOperationFacade.getLatestByName("serviceProxy", null)).thenReturn(Either.left(new Resource())); ComponentParametersView parameterView = new ComponentParametersView(); parameterView.disableAll(); diff --git a/catalog-be/src/test/resources/node-types/TestNodeType001.yml b/catalog-be/src/test/resources/node-types/TestNodeType001.yml new file mode 100644 index 0000000000..6a312579d8 --- /dev/null +++ b/catalog-be/src/test/resources/node-types/TestNodeType001.yml @@ -0,0 +1,18 @@ +tosca_definitions_version: tosca_simple_yaml_1_0_0 +node_types: + tosca.nodes.nfv.TestNodeType001: + derived_from: tosca.nodes.Root + description: The generic abstract type from which all VNF specific abstract node types shall be derived to form, together with other node types, the TOSCA service template(s) representing the VNFD + properties: + descriptor_id: # instead of vnfd_id + type: string # GUID + description: Globally unique identifier of the VNFD + required: true + descriptor_version: # instead of vnfd_version + type: string + description: Identifies the version of the VNFD + required: true + provider: # instead of vnf_provider + type: string + description: Provider of the VNF and of the VNFD + required: true diff --git a/catalog-be/src/test/resources/node-types/TestNodeType001.zip b/catalog-be/src/test/resources/node-types/TestNodeType001.zip Binary files differnew file mode 100644 index 0000000000..047088ca3f --- /dev/null +++ b/catalog-be/src/test/resources/node-types/TestNodeType001.zip diff --git a/catalog-be/src/test/resources/node-types/TestNodeType002.zip b/catalog-be/src/test/resources/node-types/TestNodeType002.zip Binary files differnew file mode 100644 index 0000000000..1185e3ffc1 --- /dev/null +++ b/catalog-be/src/test/resources/node-types/TestNodeType002.zip diff --git a/catalog-be/src/test/resources/node-types/invalid.json b/catalog-be/src/test/resources/node-types/invalid.json new file mode 100644 index 0000000000..0db3279e44 --- /dev/null +++ b/catalog-be/src/test/resources/node-types/invalid.json @@ -0,0 +1,3 @@ +{ + +} diff --git a/catalog-be/src/test/resources/node-types/nodeTypeWithEmptyModels.json b/catalog-be/src/test/resources/node-types/nodeTypeWithEmptyModels.json new file mode 100644 index 0000000000..535f7403eb --- /dev/null +++ b/catalog-be/src/test/resources/node-types/nodeTypeWithEmptyModels.json @@ -0,0 +1,16 @@ +{ + "payloadName": "TestNodeType002.yml", + "contactId": "jh0003", + "name": "TestNodeType002", + "description": "TestUploadNodeType002", + "resourceIconPath": "compute", + "resourceType": "VFC", + "categories": [{ + "name": "Generic", + "subcategories": [{ + "name": "Infrastructure" + }] + }], + "tags": ["TestUploadNodeType002"], + "model": "" +} diff --git a/catalog-be/src/test/resources/node-types/nodeTypeWithModelsField.json b/catalog-be/src/test/resources/node-types/nodeTypeWithModelsField.json new file mode 100644 index 0000000000..03e28e3399 --- /dev/null +++ b/catalog-be/src/test/resources/node-types/nodeTypeWithModelsField.json @@ -0,0 +1,16 @@ +{ + "payloadName": "TestNodeType001.yml", + "contactId": "jh0003", + "name": "TestNodeType001", + "description": "TestUploadNodeType001", + "resourceIconPath": "compute", + "resourceType": "VFC", + "categories": [{ + "name": "Generic", + "subcategories": [{ + "name": "Infrastructure" + }] + }], + "tags": ["TestUploadNodeType001"], + "model": "ETSI-SOL001-331" +} diff --git a/catalog-be/src/test/resources/node-types/nodeTypeWithoutModelsField.json b/catalog-be/src/test/resources/node-types/nodeTypeWithoutModelsField.json new file mode 100644 index 0000000000..3c0eb14bb3 --- /dev/null +++ b/catalog-be/src/test/resources/node-types/nodeTypeWithoutModelsField.json @@ -0,0 +1,15 @@ +{ + "payloadName": "TestNodeType002.yml", + "contactId": "jh0003", + "name": "TestNodeType002", + "description": "TestUploadNodeType002", + "resourceIconPath": "compute", + "resourceType": "VFC", + "categories": [{ + "name": "Generic", + "subcategories": [{ + "name": "Infrastructure" + }] + }], + "tags": ["TestUploadNodeType002"] +} 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 ed448c18d4..4728833ecc 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 @@ -52,7 +52,8 @@ public enum ActionStatus { // Category related COMPONENT_MISSING_CATEGORY, COMPONENT_INVALID_CATEGORY, COMPONENT_ELEMENT_INVALID_NAME_FORMAT, COMPONENT_ELEMENT_INVALID_NAME_LENGTH, COMPONENT_CATEGORY_ALREADY_EXISTS, COMPONENT_CATEGORY_NOT_FOUND, COMPONENT_SUB_CATEGORY_NOT_FOUND_FOR_CATEGORY, COMPONENT_SUB_CATEGORY_EXISTS_FOR_CATEGORY, COMPONENT_GROUPING_EXISTS_FOR_SUB_CATEGORY, // Model related - MODEL_ALREADY_EXISTS, INVALID_MODEL, MODEL_IMPORTS_IS_EMPTY, COULD_NOT_READ_MODEL_IMPORTS, + MODEL_ALREADY_EXISTS, INVALID_MODEL, MODEL_IMPORTS_IS_EMPTY, COULD_NOT_READ_MODEL_IMPORTS, MODEL_NOT_FOUND, MODEL_NAME_CANNOT_BE_EMPTY, + COMPONENT_WITH_MODEL_ALREADY_EXIST, // Service API URL INVALID_SERVICE_API_URL, // Property related diff --git a/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/neo4j/GraphPropertiesDictionary.java b/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/neo4j/GraphPropertiesDictionary.java index a940c8d3f0..cbfee5e799 100644 --- a/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/neo4j/GraphPropertiesDictionary.java +++ b/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/neo4j/GraphPropertiesDictionary.java @@ -50,6 +50,7 @@ public enum GraphPropertiesDictionary { CONTACT_ID ("contactId", String.class, false, false), VENDOR_NAME ("vendorName", String.class, false, false), VENDOR_RELEASE ("vendorRelease", String.class, false, false), + MODEL ("model", String.class, false, false), CONFORMANCE_LEVEL ("conformanceLevel", String.class, false, false), ICON ("icon", String.class, false, false), TAGS ("tags", String.class, false, false), diff --git a/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/neo4j/GraphPropertiesDictionaryExtractor.java b/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/neo4j/GraphPropertiesDictionaryExtractor.java index 0701da5ad4..ed1dc29942 100644 --- a/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/neo4j/GraphPropertiesDictionaryExtractor.java +++ b/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/neo4j/GraphPropertiesDictionaryExtractor.java @@ -136,6 +136,10 @@ public class GraphPropertiesDictionaryExtractor { return (String) properties.get(GraphPropertiesDictionary.VENDOR_RELEASE.getProperty()); } + public String getModel() { + return (String) properties.get(GraphPropertiesDictionary.MODEL.getProperty()); + } + public Boolean isAbstract() { return (Boolean) properties.get(GraphPropertiesDictionary.IS_ABSTRACT.getProperty()); } diff --git a/catalog-dao/src/main/java/org/openecomp/sdc/be/resources/data/ComponentMetadataData.java b/catalog-dao/src/main/java/org/openecomp/sdc/be/resources/data/ComponentMetadataData.java index 0341be73f6..602d53ed26 100644 --- a/catalog-dao/src/main/java/org/openecomp/sdc/be/resources/data/ComponentMetadataData.java +++ b/catalog-dao/src/main/java/org/openecomp/sdc/be/resources/data/ComponentMetadataData.java @@ -62,6 +62,7 @@ public abstract class ComponentMetadataData extends GraphNode { metadataDataDefinition.setCsarVersion(extractor.getCsarVersion()); metadataDataDefinition.setImportedToscaChecksum(extractor.getImportedToscaChecksum()); metadataDataDefinition.setInvariantUUID(extractor.getInvariantUuid()); + metadataDataDefinition.setModel(extractor.getModel()); componentInstanceCounter = extractor.getInstanceCounter(); } @@ -90,6 +91,7 @@ public abstract class ComponentMetadataData extends GraphNode { addIfExists(map, GraphPropertiesDictionary.CSAR_VERSION, metadataDataDefinition.getCsarVersion()); addIfExists(map, GraphPropertiesDictionary.IMPORTED_TOSCA_CHECKSUM, metadataDataDefinition.getImportedToscaChecksum()); addIfExists(map, GraphPropertiesDictionary.INVARIANT_UUID, metadataDataDefinition.getInvariantUUID()); + addIfExists(map, GraphPropertiesDictionary.MODEL, metadataDataDefinition.getModel()); return map; } diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/Component.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/Component.java index dee4088d04..1b5038efde 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/Component.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/Component.java @@ -104,6 +104,14 @@ public abstract class Component implements PropertiesOwner { componentMetadataDefinition.getMetadataDataDefinition().setCategorySpecificMetadata(categorySpecificMetadata); } + public String getModel() { + return getComponentMetadataDefinition().getMetadataDataDefinition().getModel(); + } + + public void setModel(final String model) { + getComponentMetadataDefinition().getMetadataDataDefinition().setModel(model); + } + @JsonIgnore public ComponentMetadataDefinition getComponentMetadataDefinition() { return componentMetadataDefinition; diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/UploadResourceInfo.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/UploadResourceInfo.java index d6151c3d78..752fad2278 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/UploadResourceInfo.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/UploadResourceInfo.java @@ -35,15 +35,17 @@ public class UploadResourceInfo { private List<UploadArtifactInfo> artifactList; private String contactId, name, resourceIconPath, icon, vendorName, vendorRelease, resourceVendorModelNumber; private String resourceType = "VFC"; + private String model; public UploadResourceInfo(String payload, String payloadName, String description, String category, List<String> tags, - List<UploadArtifactInfo> artifactsList) { + List<UploadArtifactInfo> artifactsList, String modelName) { super(); this.payloadData = payload; this.payloadName = payloadName; this.description = description; this.tags = tags; this.artifactList = artifactsList; + this.model = modelName; if (category != null) { String[] arr = category.split("/"); if (arr.length >= 2) { @@ -101,6 +103,14 @@ public class UploadResourceInfo { this.artifactList = artifactsList; } + public String getModel() { + return model; + } + + public void setModel(final String model) { + this.model = model; + } + @Override public int hashCode() { final int prime = 31; @@ -116,6 +126,7 @@ public class UploadResourceInfo { result = prime * result + ((tags == null) ? 0 : tags.hashCode()); result = prime * result + ((vendorName == null) ? 0 : vendorName.hashCode()); result = prime * result + ((vendorRelease == null) ? 0 : vendorRelease.hashCode()); + result = prime * result + ((model == null) ? 0 : model.hashCode()); result = prime * result + ((resourceVendorModelNumber == null) ? 0 : resourceVendorModelNumber.hashCode()); return result; } @@ -195,6 +206,13 @@ public class UploadResourceInfo { } else if (!tags.equals(other.tags)) { return false; } + if (model == null) { + if (other.model != null) { + return false; + } + } else if (!model.equals(other.model)) { + return false; + } if (vendorName == null) { if (other.vendorName != null) { return false; diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/datamodel/ToscaElement.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/datamodel/ToscaElement.java index c176ec812b..38fb83bcf2 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/datamodel/ToscaElement.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/datamodel/ToscaElement.java @@ -59,6 +59,7 @@ public abstract class ToscaElement { private Map<String, MapPropertiesDataDefinition> capabilitiesProperties; private Map<String, ListRequirementDataDefinition> requirements; private Map<String, DataTypeDataDefinition> dataTypes; + private String model; // User private String creatorUserId; private String creatorFullName; diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/operations/NodeTypeOperation.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/operations/NodeTypeOperation.java index 3369d65f76..21c25a2289 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/operations/NodeTypeOperation.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/operations/NodeTypeOperation.java @@ -137,6 +137,11 @@ public class NodeTypeOperation extends ToscaElementOperation { if (addAdditionalInformation != StorageOperationStatus.OK) { return Either.right(addAdditionalInformation); } + final StorageOperationStatus associateNodeTypeToModel = associateResourceMetadataToModel(nodeTypeVertex, nodeType); + if (associateNodeTypeToModel != StorageOperationStatus.OK) { + return Either.right(associateNodeTypeToModel); + } + return Either.left(nodeType); } diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/operations/ToscaElementOperation.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/operations/ToscaElementOperation.java index 884f040d07..eb85090755 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/operations/ToscaElementOperation.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/operations/ToscaElementOperation.java @@ -73,8 +73,10 @@ import org.openecomp.sdc.be.model.jsonjanusgraph.datamodel.NodeType; import org.openecomp.sdc.be.model.jsonjanusgraph.datamodel.TopologyTemplate; import org.openecomp.sdc.be.model.jsonjanusgraph.datamodel.ToscaElement; import org.openecomp.sdc.be.model.jsonjanusgraph.datamodel.ToscaElementTypeEnum; +import org.openecomp.sdc.be.model.jsonjanusgraph.operations.exception.ModelOperationExceptionSupplier; 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.ModelOperation; import org.openecomp.sdc.be.model.operations.impl.UniqueIdBuilder; import org.openecomp.sdc.be.utils.TypeUtils; import org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum; @@ -95,6 +97,8 @@ public abstract class ToscaElementOperation extends BaseOperation { private static Logger log = Logger.getLogger(ToscaElementOperation.class.getName()); @Autowired protected CategoryOperation categoryOperation; + @Autowired + protected ModelOperation modelOperation; public static DataTypeDefinition createDataType(final String dataTypeName) { final DataTypeDefinition dataType = new DataTypeDefinition(); @@ -339,6 +343,7 @@ public abstract class ToscaElementOperation extends BaseOperation { nodeTypeVertex.addMetadataProperty(GraphPropertyEnum.IS_ARCHIVED, toscaElement.getMetadataValue(JsonPresentationFields.IS_ARCHIVED)); nodeTypeVertex.addMetadataProperty(GraphPropertyEnum.ARCHIVE_TIME, toscaElement.getMetadataValue(JsonPresentationFields.ARCHIVE_TIME)); nodeTypeVertex.addMetadataProperty(GraphPropertyEnum.IS_VSP_ARCHIVED, toscaElement.getMetadataValue(JsonPresentationFields.IS_VSP_ARCHIVED)); + nodeTypeVertex.addMetadataProperty(GraphPropertyEnum.MODEL, toscaElement.getMetadataValue(JsonPresentationFields.MODEL)); toscaElement.getMetadata().entrySet().stream().filter(e -> e.getValue() != null) .forEach(e -> nodeTypeVertex.setJsonMetadataField(e.getKey(), e.getValue())); nodeTypeVertex.setUniqueId(toscaElement.getUniqueId()); @@ -420,6 +425,29 @@ public abstract class ToscaElementOperation extends BaseOperation { return StorageOperationStatus.OK; } + protected StorageOperationStatus associateResourceMetadataToModel(final GraphVertex nodeTypeVertex, final ToscaElement nodeType) { + if (nodeType.getMetadataValue(JsonPresentationFields.MODEL) == null) { + return StorageOperationStatus.OK; + } + final String model = ((String) nodeType.getMetadataValue(JsonPresentationFields.MODEL)); + final JanusGraphOperationStatus createEdge = janusGraphDao + .createEdge(getModelVertex(model), nodeTypeVertex, EdgeLabelEnum.MODEL_ELEMENT, new HashMap<>()); + if (createEdge != JanusGraphOperationStatus.OK) { + log.trace("Failed to associate resource {} to model {}", nodeType.getUniqueId(), model); + return DaoStatusConverter.convertJanusGraphStatusToStorageStatus(createEdge); + } + return StorageOperationStatus.OK; + } + + private GraphVertex getModelVertex(final String modelName) { + log.debug("getModelVertex: fetching model {}", modelName); + final Optional<GraphVertex> modelVertexByNameOptional = modelOperation.findModelVertexByName(modelName); + if (modelVertexByNameOptional.isEmpty()) { + throw ModelOperationExceptionSupplier.invalidModel(modelName).get(); + } + return modelVertexByNameOptional.get(); + } + protected Either<GraphVertex, StorageOperationStatus> getResourceCategoryVertex(String elementId, String subcategoryName, String categoryName) { Either<GraphVertex, StorageOperationStatus> category = categoryOperation.getCategory(categoryName, VertexTypeEnum.RESOURCE_CATEGORY); if (category.isRight()) { 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 205a48e9b2..814ac01eac 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 @@ -39,6 +39,7 @@ import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Map.Entry; +import java.util.Objects; import java.util.Optional; import java.util.Set; import java.util.function.BiPredicate; @@ -112,7 +113,6 @@ import org.openecomp.sdc.be.model.catalog.CatalogComponent; import org.openecomp.sdc.be.model.jsonjanusgraph.config.ContainerInstanceTypesData; import org.openecomp.sdc.be.model.jsonjanusgraph.datamodel.TopologyTemplate; import org.openecomp.sdc.be.model.jsonjanusgraph.datamodel.ToscaElement; -import org.openecomp.sdc.be.model.jsonjanusgraph.operations.exception.OperationException; import org.openecomp.sdc.be.model.jsonjanusgraph.utils.ModelConverter; import org.openecomp.sdc.be.model.operations.StorageException; import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus; @@ -348,19 +348,57 @@ public class ToscaOperationFacade { return ModelConverter.isAtomicComponent(component) ? nodeTypeOperation : topologyTemplateOperation; } + public <T extends Component> Either<T, StorageOperationStatus> getLatestByToscaResourceNameAndModel(final String toscaResourceName, + final String model) { + return getLatestByNameAndModel(toscaResourceName, JsonParseFlagEnum.ParseMetadata, new ComponentParametersView(), model); + } + + private <T extends Component> Either<T, StorageOperationStatus> getLatestByNameAndModel(final String nodeName, + final JsonParseFlagEnum parseFlag, + final ComponentParametersView filter, + final String model) { + Either<T, StorageOperationStatus> result; + final Map<GraphPropertyEnum, Object> propertiesToMatch = new EnumMap<>(GraphPropertyEnum.class); + final Map<GraphPropertyEnum, Object> propertiesNotToMatch = new EnumMap<>(GraphPropertyEnum.class); + propertiesToMatch.put(GraphPropertyEnum.TOSCA_RESOURCE_NAME, nodeName); + propertiesToMatch.put(GraphPropertyEnum.IS_HIGHEST_VERSION, true); + propertiesToMatch.put(GraphPropertyEnum.MODEL, model); + propertiesNotToMatch.put(GraphPropertyEnum.IS_DELETED, true); + final Either<List<GraphVertex>, JanusGraphOperationStatus> highestResources = janusGraphDao + .getByCriteria(null, propertiesToMatch, propertiesNotToMatch, parseFlag); + if (highestResources.isRight()) { + final JanusGraphOperationStatus status = highestResources.right().value(); + log.debug("failed to find resource with name {}. status={} ", nodeName, status); + result = Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(status)); + return result; + } + final List<GraphVertex> resources = highestResources.left().value(); + double version = 0.0; + GraphVertex highestResource = null; + for (final GraphVertex vertex : resources) { + final Object versionObj = vertex.getMetadataProperty(GraphPropertyEnum.VERSION); + double resourceVersion = Double.parseDouble((String) versionObj); + if (resourceVersion > version) { + version = resourceVersion; + highestResource = vertex; + } + } + return getToscaElementByOperation(highestResource, filter); + } + public <T extends Component> Either<T, StorageOperationStatus> getLatestByToscaResourceName(String toscaResourceName) { - return getLatestByName(GraphPropertyEnum.TOSCA_RESOURCE_NAME, toscaResourceName); + return getLatestByName(GraphPropertyEnum.TOSCA_RESOURCE_NAME, toscaResourceName, null); } public <T extends Component> Either<T, StorageOperationStatus> getFullLatestComponentByToscaResourceName(String toscaResourceName) { ComponentParametersView fetchAllFilter = new ComponentParametersView(); fetchAllFilter.setIgnoreServicePath(true); fetchAllFilter.setIgnoreCapabiltyProperties(false); - return getLatestByName(GraphPropertyEnum.TOSCA_RESOURCE_NAME, toscaResourceName, JsonParseFlagEnum.ParseAll, fetchAllFilter); + return getLatestByName(GraphPropertyEnum.TOSCA_RESOURCE_NAME, toscaResourceName, JsonParseFlagEnum.ParseAll, fetchAllFilter, null); } - public <T extends Component> Either<T, StorageOperationStatus> getLatestByName(String resourceName) { - return getLatestByName(GraphPropertyEnum.NAME, resourceName); + public <T extends Component> Either<T, StorageOperationStatus> getLatestByName(String resourceName, String modelName) { + return getLatestByName(GraphPropertyEnum.NAME, resourceName, modelName); } public StorageOperationStatus validateCsarUuidUniqueness(String csarUUID) { @@ -483,6 +521,25 @@ public class ToscaOperationFacade { return predicateCriteria; } + public Optional<GraphVertex> isNodeAssociatedToModel(final String model, Resource resource) { + return getNodeModelVertices(resource, model); + } + + public Optional<GraphVertex> getNodeModelVertices(final Resource resource, final String model) { + final Either<GraphVertex, JanusGraphOperationStatus> vertex = janusGraphDao + .getVertexById(resource.getUniqueId(), JsonParseFlagEnum.NoParse); + if (vertex.isRight() || Objects.isNull(vertex.left().value())) { + return Optional.empty(); + } + final Either<List<GraphVertex>, JanusGraphOperationStatus> nodeModelVertices = janusGraphDao + .getParentVertices(vertex.left().value(), EdgeLabelEnum.MODEL_ELEMENT, JsonParseFlagEnum.NoParse); + if (nodeModelVertices.isRight() || Objects.isNull(nodeModelVertices.left().value())) { + return Optional.empty(); + } + return nodeModelVertices.left().value().stream().filter(graphVertex -> graphVertex.getMetadataProperty(GraphPropertyEnum.NAME).equals(model)) + .findFirst(); + } + private boolean isValidForVendorRelease(final GraphVertex resource, final String vendorRelease) { if (!vendorRelease.equals("1.0")) { try { @@ -733,18 +790,19 @@ public class ToscaOperationFacade { } private <T extends Component> Either<T, StorageOperationStatus> getLatestByName(GraphPropertyEnum property, String nodeName, - JsonParseFlagEnum parseFlag) { - return getLatestByName(property, nodeName, parseFlag, new ComponentParametersView()); + JsonParseFlagEnum parseFlag, String modelName) { + return getLatestByName(property, nodeName, parseFlag, new ComponentParametersView(), modelName); } - // endregion private <T extends Component> Either<T, StorageOperationStatus> getLatestByName(GraphPropertyEnum property, String nodeName, - JsonParseFlagEnum parseFlag, ComponentParametersView filter) { + JsonParseFlagEnum parseFlag, ComponentParametersView filter, + String model) { Either<T, StorageOperationStatus> result; Map<GraphPropertyEnum, Object> propertiesToMatch = new EnumMap<>(GraphPropertyEnum.class); Map<GraphPropertyEnum, Object> propertiesNotToMatch = new EnumMap<>(GraphPropertyEnum.class); propertiesToMatch.put(property, nodeName); propertiesToMatch.put(GraphPropertyEnum.IS_HIGHEST_VERSION, true); + propertiesToMatch.put(GraphPropertyEnum.MODEL, model); propertiesNotToMatch.put(GraphPropertyEnum.IS_DELETED, true); Either<List<GraphVertex>, JanusGraphOperationStatus> highestResources = janusGraphDao .getByCriteria(null, propertiesToMatch, propertiesNotToMatch, parseFlag); @@ -769,8 +827,8 @@ public class ToscaOperationFacade { } // region - Component Get By .. - private <T extends Component> Either<T, StorageOperationStatus> getLatestByName(GraphPropertyEnum property, String nodeName) { - return getLatestByName(property, nodeName, JsonParseFlagEnum.ParseMetadata); + private <T extends Component> Either<T, StorageOperationStatus> getLatestByName(GraphPropertyEnum property, String nodeName, String modelName) { + return getLatestByName(property, nodeName, JsonParseFlagEnum.ParseMetadata, modelName); } public <T extends Component> Either<List<T>, StorageOperationStatus> getBySystemName(ComponentTypeEnum componentType, String systemName) { @@ -841,8 +899,8 @@ public class ToscaOperationFacade { } public <T extends Component> Either<T, StorageOperationStatus> getComponentByNameAndVendorRelease(final ComponentTypeEnum componentType, - final String name, final String vendorRelease, - final JsonParseFlagEnum parseFlag) { + final String name, final String vendorRelease, + final JsonParseFlagEnum parseFlag) { Map<GraphPropertyEnum, Object> hasProperties = new EnumMap<>(GraphPropertyEnum.class); Map<GraphPropertyEnum, Object> hasNotProperties = new EnumMap<>(GraphPropertyEnum.class); hasProperties.put(GraphPropertyEnum.NAME, name); @@ -851,8 +909,8 @@ public class ToscaOperationFacade { hasProperties.put(GraphPropertyEnum.COMPONENT_TYPE, componentType.name()); } Map<String, Entry<JanusGraphPredicate, Object>> predicateCriteria = getVendorVersionPredicate(vendorRelease); - Either<List<GraphVertex>, JanusGraphOperationStatus> getResourceRes = janusGraphDao - .getByCriteria(null, hasProperties, hasNotProperties, predicateCriteria, parseFlag); + Either<List<GraphVertex>, JanusGraphOperationStatus> getResourceRes = janusGraphDao.getByCriteria(null, hasProperties, hasNotProperties, + predicateCriteria, parseFlag); if (getResourceRes.isRight()) { JanusGraphOperationStatus status = getResourceRes.right().value(); log.debug("failed to find resource with name {}, version {}. Status is {} ", name, predicateCriteria, status); @@ -2006,16 +2064,11 @@ public class ToscaOperationFacade { } return result; } - public Either<Boolean, StorageOperationStatus> validateComponentNameUniqueness(String name, ResourceTypeEnum resourceType, ComponentTypeEnum componentType) { - VertexTypeEnum vertexType = ModelConverter.isAtomicComponent(resourceType) ? VertexTypeEnum.NODE_TYPE : VertexTypeEnum.TOPOLOGY_TEMPLATE; String normalizedName = ValidationUtils.normaliseComponentName(name); - Map<GraphPropertyEnum, Object> properties = new EnumMap<>(GraphPropertyEnum.class); - properties.put(GraphPropertyEnum.NORMALIZED_NAME, normalizedName); - properties.put(GraphPropertyEnum.COMPONENT_TYPE, componentType.name()); Either<List<GraphVertex>, JanusGraphOperationStatus> vertexEither = janusGraphDao - .getByCriteria(vertexType, properties, JsonParseFlagEnum.NoParse); + .getByCriteria(getVertexTypeEnum(resourceType), propertiesToMatch(normalizedName, componentType), JsonParseFlagEnum.NoParse); if (vertexEither.isRight() && vertexEither.right().value() != JanusGraphOperationStatus.NOT_FOUND) { log.debug("failed to get vertex from graph with property normalizedName: {}", normalizedName); return Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(vertexEither.right().value())); @@ -2023,6 +2076,41 @@ public class ToscaOperationFacade { return Either.left(CollectionUtils.isEmpty(vertexEither.isLeft() ? vertexEither.left().value() : null)); } + public Either<Boolean, StorageOperationStatus> validateComponentNameAndModelExists(final String resourceName, final String model, + final ResourceTypeEnum resourceType, + final ComponentTypeEnum componentType) { + Either<Boolean, StorageOperationStatus> result = validateComponentNameAndModelUniqueness(resourceName, model, resourceType, componentType); + if (result.isLeft()) { + result = Either.left(!result.left().value()); + } + return result; + } + + private Either<Boolean, StorageOperationStatus> validateComponentNameAndModelUniqueness(final String resourceName, final String modelName, + final ResourceTypeEnum resourceType, + final ComponentTypeEnum componentType) { + final String normalizedName = ValidationUtils.normaliseComponentName(resourceName); + final Either<List<GraphVertex>, JanusGraphOperationStatus> vertexEither = janusGraphDao + .getByCriteria(getVertexTypeEnum(resourceType), propertiesToMatch(normalizedName, componentType), null, null, JsonParseFlagEnum.NoParse); + if (vertexEither.isRight() && vertexEither.right().value() != JanusGraphOperationStatus.NOT_FOUND) { + log.debug("failed to get vertex from graph with property normalizedName: {} and model: {}", normalizedName, modelName); + return Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(vertexEither.right().value())); + } + return Either.left(CollectionUtils.isEmpty(vertexEither.isLeft() ? vertexEither.left().value().stream() + .filter(graphVertex -> graphVertex.getMetadataProperty(GraphPropertyEnum.NAME).equals(modelName)).collect(Collectors.toList()) : null)); + } + + private VertexTypeEnum getVertexTypeEnum(final ResourceTypeEnum resourceType) { + return ModelConverter.isAtomicComponent(resourceType) ? VertexTypeEnum.NODE_TYPE : VertexTypeEnum.TOPOLOGY_TEMPLATE; + } + + private Map<GraphPropertyEnum, Object> propertiesToMatch(final String normalizedName, final ComponentTypeEnum componentType) { + final Map<GraphPropertyEnum, Object> properties = new EnumMap<>(GraphPropertyEnum.class); + properties.put(GraphPropertyEnum.NORMALIZED_NAME, normalizedName); + properties.put(GraphPropertyEnum.COMPONENT_TYPE, componentType.name()); + return properties; + } + private void fillNodeTypePropsMap(final Map<GraphPropertyEnum, Object> hasProps, final Map<GraphPropertyEnum, Object> hasNotProps, final String internalComponentType) { final Configuration configuration = ConfigurationManager.getConfigurationManager().getConfiguration(); @@ -3242,6 +3330,6 @@ public class ToscaOperationFacade { } public <T extends Component> Either<T, StorageOperationStatus> getLatestByServiceName(String serviceName) { - return getLatestByName(GraphPropertyEnum.NAME, serviceName); + return getLatestByName(GraphPropertyEnum.NAME, serviceName, null); } } diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/utils/ModelConverter.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/utils/ModelConverter.java index 225a068aaf..193270974e 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/utils/ModelConverter.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/utils/ModelConverter.java @@ -718,6 +718,9 @@ public class ModelConverter { component.setSystemName((String) toscaElement.getMetadataValue(JsonPresentationFields.SYSTEM_NAME)); component.setDerivedFromGenericType(toscaElement.getDerivedFromGenericType()); component.setDerivedFromGenericVersion(toscaElement.getDerivedFromGenericVersion()); + if(toscaElement.getModel() != null) { + component.setModel(toscaElement.getModel()); + } Map<String, PropertyDataDefinition> properties = toscaElement.getProperties(); if (MapUtils.isNotEmpty(properties)) { List<PropertyDefinition> propertiesMap = properties.values().stream().map(x -> new PropertyDefinition(x)).collect(Collectors.toList()); @@ -733,6 +736,7 @@ public class ModelConverter { resource.setToscaResourceName((String) toscaElement.getMetadataValue(JsonPresentationFields.TOSCA_RESOURCE_NAME)); resource.setVendorName((String) toscaElement.getMetadataValue(JsonPresentationFields.VENDOR_NAME)); resource.setVendorRelease((String) toscaElement.getMetadataValue(JsonPresentationFields.VENDOR_RELEASE)); + resource.setModel((String) toscaElement.getMetadataValue(JsonPresentationFields.MODEL)); // field isn't mandatory , but shouldn't be null(should be an empty string instead) if (((String) toscaElement.getMetadataValue(JsonPresentationFields.RESOURCE_VENDOR_MODEL_NUMBER)) != null) { resource.setResourceVendorModelNumber((String) toscaElement.getMetadataValue(JsonPresentationFields.RESOURCE_VENDOR_MODEL_NUMBER)); @@ -1294,6 +1298,7 @@ public class ModelConverter { toscaElement.setMetadataValue(JsonPresentationFields.TOSCA_RESOURCE_NAME, ((Resource) component).getToscaResourceName()); toscaElement.setMetadataValue(JsonPresentationFields.VENDOR_NAME, ((Resource) component).getVendorName()); toscaElement.setMetadataValue(JsonPresentationFields.VENDOR_RELEASE, ((Resource) component).getVendorRelease()); + toscaElement.setMetadataValue(JsonPresentationFields.MODEL, component.getModel()); // field isn't mandatory , but shouldn't be null(should be an empty string instead) if (((Resource) component).getResourceVendorModelNumber() != null) { toscaElement diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/api/StorageOperationStatus.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/api/StorageOperationStatus.java index 3c8521ae79..4fbb5fbef3 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/api/StorageOperationStatus.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/api/StorageOperationStatus.java @@ -41,6 +41,7 @@ public enum StorageOperationStatus { OPERATION_NOT_SUPPORTED, CATEGORY_NOT_FOUND, PARENT_RESOURCE_NOT_FOUND, + MODEL_NOT_FOUND, MULTIPLE_PARENT_RESOURCE_FOUND, INCONSISTENCY, GRAPH_IS_NOT_AVAILABLE, diff --git a/catalog-model/src/test/java/org/openecomp/sdc/be/model/UploadResourceInfoTest.java b/catalog-model/src/test/java/org/openecomp/sdc/be/model/UploadResourceInfoTest.java index 46743565de..7af24fce92 100644 --- a/catalog-model/src/test/java/org/openecomp/sdc/be/model/UploadResourceInfoTest.java +++ b/catalog-model/src/test/java/org/openecomp/sdc/be/model/UploadResourceInfoTest.java @@ -36,8 +36,8 @@ public class UploadResourceInfoTest { @Test public void testCtor() throws Exception { - new UploadResourceInfo("mock", "mock", "mock", "mock/mock/mock", new LinkedList<>(), new LinkedList<>()); - + new UploadResourceInfo("mock", "mock", "mock", "mock/mock/mock", new LinkedList<>(), new LinkedList<>(), + "modelName"); } @Test diff --git a/catalog-model/src/test/java/org/openecomp/sdc/be/model/jsonjanusgraph/operations/ToscaOperationFacadeTest.java b/catalog-model/src/test/java/org/openecomp/sdc/be/model/jsonjanusgraph/operations/ToscaOperationFacadeTest.java index b0f2fa5010..a19e7c431f 100644 --- a/catalog-model/src/test/java/org/openecomp/sdc/be/model/jsonjanusgraph/operations/ToscaOperationFacadeTest.java +++ b/catalog-model/src/test/java/org/openecomp/sdc/be/model/jsonjanusgraph/operations/ToscaOperationFacadeTest.java @@ -263,6 +263,7 @@ public class ToscaOperationFacadeTest { Map<GraphPropertyEnum, Object> propertiesNotToMatch = new EnumMap<>(GraphPropertyEnum.class); propertiesToMatch.put(GraphPropertyEnum.TOSCA_RESOURCE_NAME, "toscaResourceName"); propertiesToMatch.put(GraphPropertyEnum.IS_HIGHEST_VERSION, true); + propertiesToMatch.put(GraphPropertyEnum.MODEL, null); propertiesNotToMatch.put(GraphPropertyEnum.IS_DELETED, true); when(janusGraphDaoMock.getByCriteria(null, propertiesToMatch, propertiesNotToMatch, JsonParseFlagEnum.ParseAll)) @@ -441,6 +442,7 @@ public class ToscaOperationFacadeTest { Map<GraphPropertyEnum, Object> propertiesToMatch = new EnumMap<>(GraphPropertyEnum.class); propertiesToMatch.put(GraphPropertyEnum.TOSCA_RESOURCE_NAME, toscaResourceName); propertiesToMatch.put(GraphPropertyEnum.IS_HIGHEST_VERSION, true); + propertiesToMatch.put(GraphPropertyEnum.MODEL, null); Map<GraphPropertyEnum, Object> propertiesNotToMatch = new EnumMap<>(GraphPropertyEnum.class); propertiesNotToMatch.put(GraphPropertyEnum.IS_DELETED, true); diff --git a/catalog-model/src/test/java/org/openecomp/sdc/be/model/operations/JsonObjectTest.java b/catalog-model/src/test/java/org/openecomp/sdc/be/model/operations/JsonObjectTest.java index a201b30fd9..787aca1caa 100644 --- a/catalog-model/src/test/java/org/openecomp/sdc/be/model/operations/JsonObjectTest.java +++ b/catalog-model/src/test/java/org/openecomp/sdc/be/model/operations/JsonObjectTest.java @@ -7,9 +7,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -20,46 +20,44 @@ package org.openecomp.sdc.be.model.operations; +import static org.junit.Assert.assertEquals; + import com.fasterxml.jackson.core.JsonParseException; import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.ObjectMapper; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; import org.junit.Before; import org.junit.Test; import org.openecomp.sdc.be.model.UploadResourceInfo; import org.openecomp.sdc.common.api.ArtifactTypeEnum; import org.openecomp.sdc.common.api.UploadArtifactInfo; -import java.io.IOException; -import java.util.ArrayList; - -import static org.junit.Assert.assertEquals; - public class JsonObjectTest { private ObjectMapper mapper; UploadResourceInfo inputObjectRef; private final String INPUT_RESOURCE_STRING = "{ \"payloadData\" : \"My Test Object\", \"payloadName\" : \"TestName\", " + " \"description\":\"my_description\",\"tags\":[\"tag1\"], " - + "\"artifactList\" : [ { \"artifactName\" : \"myArtifact0\", \"artifactPath\" : \"scripts/\", \"artifactType\" : \"PUPPET\", " + " \"artifactDescription\" : \"This is Description\", \"artifactData\" : null }, " - + "{ \"artifactName\" : \"myArtifact1\", \"artifactPath\" : \"scripts/\", \"artifactType\" : \"PUPPET\", \"artifactDescription\" : \"This is Description\", " - + " \"artifactData\" : null } ], \"contactId\" : null, \"name\" : null, \"resourceIconPath\" : null, \"vendorName\" : null, \"vendorRelease\" : null , \"resourceType\" : \"VFC\" }"; + + "\"artifactList\" : [ { \"artifactName\" : \"myArtifact0\", \"artifactPath\" : \"scripts/\", \"artifactType\" : \"PUPPET\", " + " \"artifactDescription\" : \"This is Description\", \"artifactData\" : null }, " + + "{ \"artifactName\" : \"myArtifact1\", \"artifactPath\" : \"scripts/\", \"artifactType\" : \"PUPPET\", \"artifactDescription\" : \"This is Description\", " + + " \"artifactData\" : null } ], \"contactId\" : null, \"name\" : null, \"resourceIconPath\" : null, \"vendorName\" : null, \"vendorRelease\" : null , \"resourceType\" : \"VFC\", \"model\":\"model1\"}"; @Before public void setup() { mapper = new ObjectMapper(); - ArrayList<UploadArtifactInfo> artifactList = new ArrayList<>(); + final ArrayList<UploadArtifactInfo> artifactList = new ArrayList<>(); for (int i = 0; i < 2; i++) { UploadArtifactInfo artifactInfo = new UploadArtifactInfo("myArtifact" + i, "scripts/", ArtifactTypeEnum.PUPPET, "This is Description"); artifactList.add(artifactInfo); } - ArrayList<String> tags = new ArrayList<>(); - tags.add("tag1"); - inputObjectRef = new UploadResourceInfo("My Test Object", "TestName", "my_description", null, tags, artifactList); - + inputObjectRef = new UploadResourceInfo("My Test Object", "TestName", "my_description", null, + Arrays.asList("tag1"), artifactList, "model1"); } @Test - public void testStringToUploadResourceInfo() throws JsonParseException, JsonMappingException, IOException { - UploadResourceInfo resourceObjectTest = mapper.readValue(INPUT_RESOURCE_STRING, UploadResourceInfo.class); + public void testStringToUploadResourceInfo() throws IOException { + final UploadResourceInfo resourceObjectTest = mapper.readValue(INPUT_RESOURCE_STRING, UploadResourceInfo.class); assertEquals(inputObjectRef, resourceObjectTest); } @@ -72,4 +70,4 @@ public class JsonObjectTest { assertEquals(unFormattedString, INPUT_RESOURCE_STRING.replace("\n", "").replace("\t", "").replace(" ", "")); } -} +}
\ No newline at end of file diff --git a/common-be/src/main/java/org/openecomp/sdc/be/datatypes/components/ComponentMetadataDataDefinition.java b/common-be/src/main/java/org/openecomp/sdc/be/datatypes/components/ComponentMetadataDataDefinition.java index ebccc6c2b8..849153b1ac 100644 --- a/common-be/src/main/java/org/openecomp/sdc/be/datatypes/components/ComponentMetadataDataDefinition.java +++ b/common-be/src/main/java/org/openecomp/sdc/be/datatypes/components/ComponentMetadataDataDefinition.java @@ -132,6 +132,9 @@ public abstract class ComponentMetadataDataDefinition extends ToscaDataDefinitio @Getter @Setter private Map<String, String> categorySpecificMetadata; + @Getter + @Setter + private String model; public ComponentMetadataDataDefinition(ComponentMetadataDataDefinition other) { this.uniqueId = other.getUniqueId(); @@ -159,6 +162,7 @@ public abstract class ComponentMetadataDataDefinition extends ToscaDataDefinitio this.isVspArchived = other.isVspArchived; this.archiveTime = other.getArchiveTime(); this.categorySpecificMetadata = other.getCategorySpecificMetadata(); + this.model = other.getModel(); } public ComponentMetadataDataDefinition(JsonPresentationFieldsExtractor extractor) { @@ -185,6 +189,7 @@ public abstract class ComponentMetadataDataDefinition extends ToscaDataDefinitio this.isArchived = extractor.isArchived(); this.isVspArchived = extractor.isVspArchived(); this.archiveTime = extractor.getArchiveTime(); + this.model = extractor.getModel(); } public void setUniqueId(String uniqueId) { diff --git a/common-be/src/main/java/org/openecomp/sdc/be/datatypes/enums/GraphPropertyEnum.java b/common-be/src/main/java/org/openecomp/sdc/be/datatypes/enums/GraphPropertyEnum.java index 0ed0bd21fa..8f547cf7d2 100644 --- a/common-be/src/main/java/org/openecomp/sdc/be/datatypes/enums/GraphPropertyEnum.java +++ b/common-be/src/main/java/org/openecomp/sdc/be/datatypes/enums/GraphPropertyEnum.java @@ -55,15 +55,16 @@ public enum GraphPropertyEnum { ICONS("icons", String.class, false, false), METADATA_KEYS("metadataKeys", String.class, false, false), USE_SUBSTITUTION_FOR_NESTED_SERVICES("useServiceSubstitutionForNestedServices", Boolean.class, false, false), - DATA_TYPES("data_types", Map.class, false, false), - //Archive/Restore - IS_ARCHIVED("isArchived", Boolean.class, false, true), IS_VSP_ARCHIVED("isVspArchived", Boolean.class, false, true), ARCHIVE_TIME("archiveTime", - Long.class, false, true), PREV_CATALOG_UPDATE_TIME("previousUpdateTime", Long.class, false, true), CURRENT_CATALOG_UPDATE_TIME( - "currentUpdateTime", Long.class, false, true), + IS_ARCHIVED("isArchived", Boolean.class, false, true), + IS_VSP_ARCHIVED("isVspArchived", Boolean.class, false, true), + ARCHIVE_TIME("archiveTime", Long.class, false, true), + PREV_CATALOG_UPDATE_TIME("previousUpdateTime", Long.class, false, true), + CURRENT_CATALOG_UPDATE_TIME("currentUpdateTime", Long.class, false, true), //Healing - HEALING_VERSION("healVersion", Integer.class, false, true); + HEALING_VERSION("healVersion", Integer.class, false, true), + MODEL("model", String.class, false, false); // @formatter:on private final String property; diff --git a/common-be/src/main/java/org/openecomp/sdc/be/datatypes/enums/JsonPresentationFields.java b/common-be/src/main/java/org/openecomp/sdc/be/datatypes/enums/JsonPresentationFields.java index 185d9538ff..1e8e842656 100644 --- a/common-be/src/main/java/org/openecomp/sdc/be/datatypes/enums/JsonPresentationFields.java +++ b/common-be/src/main/java/org/openecomp/sdc/be/datatypes/enums/JsonPresentationFields.java @@ -68,7 +68,7 @@ public enum JsonPresentationFields { DERIVED_FROM_GENERIC_TYPE("derivedFromGenericType", null), DERIVED_FROM_GENERIC_VERSION("derivedFromGenericVersion", null), SERVICE_FUNCTION("serviceFunction", null), - MODELS("models", null), + MODEL("model", null), DATA_TYPES("data_types", GraphPropertyEnum.DATA_TYPES), ////Inputs diff --git a/common-be/src/main/java/org/openecomp/sdc/be/datatypes/enums/JsonPresentationFieldsExtractor.java b/common-be/src/main/java/org/openecomp/sdc/be/datatypes/enums/JsonPresentationFieldsExtractor.java index c5eb86559e..2fc2c52404 100644 --- a/common-be/src/main/java/org/openecomp/sdc/be/datatypes/enums/JsonPresentationFieldsExtractor.java +++ b/common-be/src/main/java/org/openecomp/sdc/be/datatypes/enums/JsonPresentationFieldsExtractor.java @@ -165,4 +165,8 @@ public class JsonPresentationFieldsExtractor { public String getServiceFunction() { return (String) properties.get(JsonPresentationFields.SERVICE_FUNCTION.getPresentation()); } + + public String getModel() { + return (String) properties.get(JsonPresentationFields.MODEL.getPresentation()); + } } |