Error re-importing VSP
Issue-ID: SDC-3728
Signed-off-by: KrupaNagabhushan <krupa.nagabhushan@est.tech>
Signed-off-by: André Schmid <andre.schmid@est.tech>
Change-Id: I22d6186b8e6922511a7ede584d009cfae041fabd
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 4f5374f..9d3204b 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
@@ -2595,4 +2595,20 @@
code: 400,
message: "Invalid label name. Only the following characters are allowed in label name: '%1'",
messageId: "SVC4158"
+ }
+
+ #---------SVC4159-----------------------------
+ # %1 - The model name
+ COULD_NOT_DELETE_MODEL: {
+ code: 500,
+ message: "Could not delete the model '%1'.",
+ messageId: "SVC4159"
+ }
+
+ #---------SVC4160-----------------------------
+ # %1 - The model name
+ COULD_NOT_DELETE_MODEL_ELEMENTS: {
+ code: 500,
+ message: "Could not delete the model '%1' elements.",
+ messageId: "SVC4160"
}
\ No newline at end of file
diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/lifecycle/UndoCheckoutTransition.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/lifecycle/UndoCheckoutTransition.java
index c8b50d2..f1ea1ee 100644
--- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/lifecycle/UndoCheckoutTransition.java
+++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/lifecycle/UndoCheckoutTransition.java
@@ -106,7 +106,7 @@
Either<? extends Component, ResponseFormat> result = null;
log.debug("start performing undo-checkout for resource {}", component.getUniqueId());
try {
- Either<ToscaElement, StorageOperationStatus> undoCheckoutResourceResult = lifeCycleOperation.undoCheckout(component.getUniqueId());
+ Either<ToscaElement, StorageOperationStatus> undoCheckoutResourceResult = lifeCycleOperation.undoCheckout(component.getUniqueId(), component.getModel());
if (undoCheckoutResourceResult.isRight()) {
log.debug("checkout failed on graph");
StorageOperationStatus response = undoCheckoutResourceResult.right().value();
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 18cdb42..2de9000 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.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.ModelElementOperation;
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;
@@ -267,6 +268,11 @@
return new ModelOperation(null, null, null, null);
}
+ @Bean
+ ModelElementOperation modelElementOperation() {
+ return new ModelElementOperation(null, null, null);
+ }
+
private void initGraphForTest() {
//Create Catalog Root
catalogVertex = GraphTestUtils.createRootCatalogVertex(janusGraphDao);
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 30fcfac..2a71089 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
@@ -54,7 +54,7 @@
// Model related
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, COMPONENT_WITH_VENDOR_RELEASE_ALREADY_EXISTS, COMPONENT_WITH_VENDOR_RELEASE_ALREADY_EXISTS_IN_MODEL,
- UNKNOWN_MODEL_TYPE,
+ UNKNOWN_MODEL_TYPE, COULD_NOT_DELETE_MODEL, COULD_NOT_DELETE_MODEL_ELEMENTS,
// Service API URL
INVALID_SERVICE_API_URL,
// Property related
diff --git a/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/api/exception/JanusGraphException.java b/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/api/exception/JanusGraphException.java
new file mode 100644
index 0000000..fb37b54
--- /dev/null
+++ b/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/api/exception/JanusGraphException.java
@@ -0,0 +1,36 @@
+/*
+ * -
+ * ============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.dao.api.exception;
+
+import lombok.Getter;
+import org.openecomp.sdc.be.dao.janusgraph.JanusGraphOperationStatus;
+
+@Getter
+public class JanusGraphException extends RuntimeException {
+
+ private final JanusGraphOperationStatus status;
+
+ public JanusGraphException(final JanusGraphOperationStatus status, final String message) {
+ super(message);
+ this.status = status;
+ }
+}
diff --git a/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/cassandra/ToscaModelImportCassandraDao.java b/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/cassandra/ToscaModelImportCassandraDao.java
index c250aec..d21b561 100644
--- a/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/cassandra/ToscaModelImportCassandraDao.java
+++ b/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/cassandra/ToscaModelImportCassandraDao.java
@@ -122,4 +122,9 @@
return toscaImportByModelAccessor.findAllByModel(modelId).all();
}
+ public void deleteAllByModel(final String modelId) {
+ final List<ToscaImportByModel> allByModel = findAllByModel(modelId);
+ allByModel.forEach(toscaImportByModelMapper::delete);
+ }
+
}
diff --git a/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/janusgraph/JanusGraphGenericDao.java b/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/janusgraph/JanusGraphGenericDao.java
index 2116dcc..8382af5 100644
--- a/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/janusgraph/JanusGraphGenericDao.java
+++ b/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/janusgraph/JanusGraphGenericDao.java
@@ -48,6 +48,7 @@
import org.janusgraph.core.PropertyKey;
import org.janusgraph.graphdb.query.JanusGraphPredicate;
import org.openecomp.sdc.be.config.ConfigurationManager;
+import org.openecomp.sdc.be.dao.api.exception.JanusGraphException;
import org.openecomp.sdc.be.dao.graph.GraphElementFactory;
import org.openecomp.sdc.be.dao.graph.datatype.GraphEdge;
import org.openecomp.sdc.be.dao.graph.datatype.GraphElementTypeEnum;
@@ -59,6 +60,7 @@
import org.openecomp.sdc.be.dao.neo4j.GraphPropertiesDictionary;
import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum;
import org.openecomp.sdc.be.resources.data.GraphNodeLock;
+import org.openecomp.sdc.common.log.enums.EcompLoggerErrorCode;
import org.openecomp.sdc.common.log.wrappers.Logger;
import org.springframework.beans.factory.annotation.Qualifier;
@@ -1318,6 +1320,58 @@
return Either.left(immutablePairs);
}
+ public <T extends GraphNode> JanusGraphOperationStatus deleteAllChildrenNodes(String key, String uniqueId, GraphEdgeLabels edgeType) {
+ final JanusGraph janusGraph = getJanusGraph();
+ final Iterable<JanusGraphVertex> vertices = janusGraph.query().has(key, uniqueId).vertices();
+ if (vertices == null || !vertices.iterator().hasNext()) {
+ return JanusGraphOperationStatus.NOT_FOUND;
+ }
+ final Vertex rootVertex = vertices.iterator().next();
+ final Iterator<Edge> outEdges = rootVertex.edges(Direction.OUT, edgeType.getProperty());
+ while (outEdges.hasNext()) {
+ final Edge edge = outEdges.next();
+ final Vertex vertexIn = edge.inVertex();
+ final Iterator<Edge> outSubEdges = vertexIn.edges(Direction.OUT);
+ while (outSubEdges.hasNext()) {
+ Edge subEdge = outSubEdges.next();
+ Vertex vertex = subEdge.inVertex();
+ Map<String, Object> properties = getProperties(vertex);
+ if (properties != null) {
+ String label = (String) properties.get(GraphPropertiesDictionary.LABEL.getProperty());
+ if (label.equals("property")) {
+ vertex.remove();
+ }
+ }
+ }
+ Map<String, Object> properties = getProperties(vertexIn);
+ if (properties != null) {
+ String label = (String) properties.get(GraphPropertiesDictionary.LABEL.getProperty());
+ GraphNode node = GraphElementFactory
+ .createElement(label, GraphElementTypeEnum.Node, properties, GraphNode.class);
+ if (node != null) {
+ vertexIn.remove();
+ }
+ }
+ }
+ return JanusGraphOperationStatus.OK;
+ }
+
+ /**
+ * Gets the JanusGraph instance.
+ *
+ * @return the JanusGraph instance
+ * @throws JanusGraphException when the graph was not created
+ */
+ public JanusGraph getJanusGraph() {
+ final Either<JanusGraph, JanusGraphOperationStatus> graphRes = janusGraphClient.getGraph();
+ if (graphRes.isRight()) {
+ final var errorMsg = String.format("Failed to retrieve graph. Status was '%s'", graphRes.right().value());
+ log.error(EcompLoggerErrorCode.SCHEMA_ERROR, JanusGraphGenericDao.class.getName(), errorMsg);
+ throw new JanusGraphException(graphRes.right().value(), errorMsg);
+ }
+ return graphRes.left().value();
+ }
+
public Either<List<ImmutablePair<JanusGraphVertex, Edge>>, JanusGraphOperationStatus> getChildrenVertecies(String key, String uniqueId,
GraphEdgeLabels edgeType) {
List<ImmutablePair<JanusGraphVertex, Edge>> immutablePairs = new ArrayList<>();
diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/operations/ToscaElementLifecycleOperation.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/operations/ToscaElementLifecycleOperation.java
index 963458b..d46d4a5 100644
--- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/operations/ToscaElementLifecycleOperation.java
+++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/operations/ToscaElementLifecycleOperation.java
@@ -60,10 +60,12 @@
import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
import org.openecomp.sdc.be.datatypes.enums.GraphPropertyEnum;
import org.openecomp.sdc.be.datatypes.enums.JsonPresentationFields;
+import org.openecomp.sdc.be.datatypes.enums.ModelTypeEnum;
import org.openecomp.sdc.be.datatypes.enums.OriginTypeEnum;
import org.openecomp.sdc.be.datatypes.tosca.ToscaDataDefinition;
import org.openecomp.sdc.be.model.DistributionStatusEnum;
import org.openecomp.sdc.be.model.LifecycleStateEnum;
+import org.openecomp.sdc.be.model.Model;
import org.openecomp.sdc.be.model.User;
import org.openecomp.sdc.be.model.jsonjanusgraph.datamodel.TopologyTemplate;
import org.openecomp.sdc.be.model.jsonjanusgraph.datamodel.ToscaElement;
@@ -71,10 +73,12 @@
import org.openecomp.sdc.be.model.jsonjanusgraph.enums.JsonConstantKeysEnum;
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.common.jsongraph.util.CommonUtility;
import org.openecomp.sdc.common.jsongraph.util.CommonUtility.LogLevelEnum;
import org.openecomp.sdc.common.log.wrappers.Logger;
+import org.springframework.beans.factory.annotation.Autowired;
@org.springframework.stereotype.Component("tosca-element-lifecycle-operation")
/**
@@ -87,6 +91,12 @@
private static final String FAILED_TO_DELETE_LAST_STATE_EDGE_STATUS_IS = "Failed to delete last state edge. Status is {}. ";
private static final String FAILED_TO_GET_VERTICES = "Failed to get vertices by id {}. Status is {}. ";
private static final Logger log = Logger.getLogger(ToscaElementLifecycleOperation.class);
+ private final ModelOperation modelOperation;
+
+ @Autowired
+ public ToscaElementLifecycleOperation(ModelOperation modelOperation) {
+ this.modelOperation = modelOperation;
+ }
static StorageOperationStatus handleFailureToPrepareParameters(final JanusGraphOperationStatus status, final String toscaElementId) {
CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, FAILED_TO_GET_VERTICES, toscaElementId);
@@ -223,12 +233,12 @@
* @param toscaElementId
* @return
*/
- public Either<ToscaElement, StorageOperationStatus> undoCheckout(String toscaElementId) {
+ public Either<ToscaElement, StorageOperationStatus> undoCheckout(String toscaElementId, String model) {
try {
return janusGraphDao.getVertexById(toscaElementId, JsonParseFlagEnum.ParseMetadata).right().map(errorStatus -> {
CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, FAILED_TO_GET_VERTICES, toscaElementId);
return DaoStatusConverter.convertJanusGraphStatusToStorageStatus(errorStatus);
- }).left().bind(this::retrieveAndUpdatePreviousVersion).left().bind(this::updateEdgeToCatalogRootAndReturnPreVersionElement);
+ }).left().bind(this::retrieveAndUpdatePreviousVersion).left().bind(tuple -> updateEdgeToCatalogRootAndReturnPreVersionElement(tuple, model));
} catch (Exception e) {
CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Exception occurred during undo checkout tosca element {}. {}", toscaElementId,
e.getMessage());
@@ -260,13 +270,17 @@
}
private Either<ToscaElement, StorageOperationStatus> updateEdgeToCatalogRootAndReturnPreVersionElement(
- final P2<GraphVertex, JanusGraphVertex> tuple) {
+ final P2<GraphVertex, JanusGraphVertex> tuple, final String model) {
final GraphVertex currVersionV = tuple._1();
final JanusGraphVertex preVersionVertex = tuple._2();
StorageOperationStatus updateCatalogRes = updateEdgeToCatalogRootByUndoCheckout(preVersionVertex, currVersionV);
if (updateCatalogRes != StorageOperationStatus.OK) {
return Either.right(updateCatalogRes);
} else {
+ final Optional<Model> modelOptional = modelOperation.findModelByName(model);
+ if (modelOptional.isPresent() && modelOptional.get().getModelType() == ModelTypeEnum.NORMATIVE_EXTENSION) {
+ modelOperation.deleteModel(modelOptional.get(), false);
+ }
final ToscaElementOperation operation = getToscaElementOperation(currVersionV.getLabel());
return operation.deleteToscaElement(currVersionV).left().bind(discarded -> getUpdatedPreVersionElement(operation, preVersionVertex));
}
diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/operations/exception/OperationException.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/operations/exception/OperationException.java
index 30323af..7631516 100644
--- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/operations/exception/OperationException.java
+++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/operations/exception/OperationException.java
@@ -35,7 +35,13 @@
params = new String[0];
}
- public OperationException(final ActionStatus actionStatus, String... params) {
+ public OperationException(final ActionStatus actionStatus, final String... params) {
+ this.actionStatus = actionStatus;
+ this.params = params;
+ }
+
+ public OperationException(final Throwable cause, final ActionStatus actionStatus, final String... params) {
+ super(cause);
this.actionStatus = actionStatus;
this.params = params;
}
diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/DataTypeOperation.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/DataTypeOperation.java
index d6cca3f..a0963c9 100644
--- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/DataTypeOperation.java
+++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/DataTypeOperation.java
@@ -24,15 +24,17 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
-import java.util.stream.Collectors;
import org.apache.commons.collections.CollectionUtils;
-import org.apache.commons.collections4.MapUtils;
+import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
+import org.apache.tinkerpop.gremlin.structure.Vertex;
+import org.janusgraph.core.JanusGraph;
import org.openecomp.sdc.be.config.BeEcompErrorManager;
import org.openecomp.sdc.be.config.BeEcompErrorManager.ErrorSeverity;
import org.openecomp.sdc.be.dao.janusgraph.HealingJanusGraphGenericDao;
import org.openecomp.sdc.be.dao.janusgraph.JanusGraphOperationStatus;
+import org.openecomp.sdc.be.dao.neo4j.GraphEdgeLabels;
+import org.openecomp.sdc.be.dao.neo4j.GraphPropertiesDictionary;
import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum;
-import org.openecomp.sdc.be.model.DataTypeDefinition;
import org.openecomp.sdc.be.resources.data.DataTypeData;
import org.openecomp.sdc.common.log.enums.EcompLoggerErrorCode;
import org.slf4j.Logger;
@@ -45,12 +47,16 @@
private static final Logger LOGGER = LoggerFactory.getLogger(DataTypeOperation.class);
- private final ModelOperation modelOperation;
+ private ModelOperation modelOperation;
@Autowired
- public DataTypeOperation(final HealingJanusGraphGenericDao janusGraphGenericDao,
- final ModelOperation modelOperation) {
+ public DataTypeOperation(final HealingJanusGraphGenericDao janusGraphGenericDao) {
this.janusGraphGenericDao = janusGraphGenericDao;
+ }
+
+ //circular dependency ModelOperation->ModelElementOperation->DataTypeOperation
+ @Autowired
+ public void setModelOperation(final ModelOperation modelOperation) {
this.modelOperation = modelOperation;
}
@@ -132,4 +138,18 @@
return getDataTypes.left().value();
}
+ public void deleteDataTypesByModelId(final String modelId) {
+ final JanusGraph janusGraph = janusGraphGenericDao.getJanusGraph();
+ final GraphTraversalSource traversal = janusGraph.traversal();
+ final List<Vertex> dataTypeList = traversal.V()
+ .has(GraphPropertiesDictionary.UNIQUE_ID.getProperty(), modelId)
+ .out(GraphEdgeLabels.MODEL_ELEMENT.getProperty())
+ .has(GraphPropertiesDictionary.LABEL.getProperty(), NodeTypeEnum.DataType.getName())
+ .toList();
+ dataTypeList.forEach(dataTypeVertex -> {
+ traversal.V(dataTypeVertex).out(GraphEdgeLabels.PROPERTY.getProperty()).drop().iterate();
+ dataTypeVertex.remove();
+ });
+ }
+
}
diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/ModelElementOperation.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/ModelElementOperation.java
new file mode 100644
index 0000000..048fbfd
--- /dev/null
+++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/ModelElementOperation.java
@@ -0,0 +1,74 @@
+/*
+ * -
+ * ============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.model.operations.impl;
+
+import org.openecomp.sdc.be.dao.api.ActionStatus;
+import org.openecomp.sdc.be.dao.janusgraph.JanusGraphGenericDao;
+import org.openecomp.sdc.be.model.Model;
+import org.openecomp.sdc.be.model.jsonjanusgraph.operations.exception.OperationException;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+@Component("model-element-operation")
+public class ModelElementOperation {
+
+ private final JanusGraphGenericDao janusGraphGenericDao;
+ private final DataTypeOperation dataTypeOperation;
+ private final PolicyTypeOperation policyTypeOperation;
+
+ @Autowired
+ public ModelElementOperation(final JanusGraphGenericDao janusGraphGenericDao,
+ final DataTypeOperation dataTypeOperation,
+ final PolicyTypeOperation policyTypeOperation) {
+ this.janusGraphGenericDao = janusGraphGenericDao;
+ this.dataTypeOperation = dataTypeOperation;
+ this.policyTypeOperation = policyTypeOperation;
+ }
+
+ /**
+ * Deletes the given model if it exists, along with its MODEL_ELEMENT edges and import files.
+ *
+ * @param model the model
+ * @param inTransaction if the operation is called in the middle of a janusgraph transaction
+ */
+ public void deleteModelElements(final Model model, final boolean inTransaction) {
+ boolean rollback = false;
+
+ try {
+ final String modelId = UniqueIdBuilder.buildModelUid(model.getName());
+ dataTypeOperation.deleteDataTypesByModelId(modelId);
+ policyTypeOperation.deletePolicyTypesByModelId(modelId);
+ } catch (final Exception e) {
+ rollback = true;
+ throw new OperationException(e, ActionStatus.COULD_NOT_DELETE_MODEL_ELEMENTS, model.getName());
+ } finally {
+ if (!inTransaction) {
+ if (rollback) {
+ janusGraphGenericDao.rollback();
+ } else {
+ janusGraphGenericDao.commit();
+ }
+ }
+ }
+ }
+
+}
diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/ModelOperation.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/ModelOperation.java
index 095b4e1..b5cb9d9 100644
--- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/ModelOperation.java
+++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/ModelOperation.java
@@ -38,10 +38,10 @@
import org.openecomp.sdc.be.dao.cassandra.ToscaModelImportCassandraDao;
import org.openecomp.sdc.be.dao.graph.datatype.GraphEdge;
import org.openecomp.sdc.be.dao.graph.datatype.GraphRelation;
+import org.openecomp.sdc.be.dao.janusgraph.JanusGraphDao;
import org.openecomp.sdc.be.dao.janusgraph.JanusGraphGenericDao;
import org.openecomp.sdc.be.dao.janusgraph.JanusGraphOperationStatus;
import org.openecomp.sdc.be.dao.jsongraph.GraphVertex;
-import org.openecomp.sdc.be.dao.janusgraph.JanusGraphDao;
import org.openecomp.sdc.be.dao.jsongraph.types.VertexTypeEnum;
import org.openecomp.sdc.be.dao.neo4j.GraphEdgeLabels;
import org.openecomp.sdc.be.data.model.ToscaImportByModel;
@@ -71,6 +71,7 @@
private final JanusGraphDao janusGraphDao;
private final ToscaModelImportCassandraDao toscaModelImportCassandraDao;
private final DerivedFromOperation derivedFromOperation;
+ private ModelElementOperation modelElementOperation;
@Autowired
public ModelOperation(final JanusGraphGenericDao janusGraphGenericDao,
@@ -322,4 +323,54 @@
+ "description: Auto-generated file that contains package custom types or types added after system installation." + "\n";
}
+ /**
+ * Deletes the given model if it exists, along with its MODEL_ELEMENT edges and import files.
+ *
+ * @param model the model
+ * @param inTransaction if the operation is called in the middle of a janusgraph transaction
+ */
+ public void deleteModel(final Model model, final boolean inTransaction) {
+ boolean rollback = false;
+
+ try {
+ final GraphVertex modelVertexByName = findModelVertexByName(model.getName()).orElse(null);
+ if (modelVertexByName == null) {
+ return;
+ }
+ toscaModelImportCassandraDao.deleteAllByModel(model.getName());
+ modelElementOperation.deleteModelElements(model, inTransaction);
+ deleteModel(model);
+ } catch (final OperationException e) {
+ rollback = true;
+ throw e;
+ } catch (final Exception e) {
+ rollback = true;
+ throw new OperationException(e, ActionStatus.COULD_NOT_DELETE_MODEL, model.getName());
+ } finally {
+ if (!inTransaction) {
+ if (rollback) {
+ janusGraphGenericDao.rollback();
+ } else {
+ janusGraphGenericDao.commit();
+ }
+ }
+ }
+ }
+
+ private void deleteModel(final Model model) {
+ final var modelData = new ModelData(model.getName(), UniqueIdBuilder.buildModelUid(model.getName()), model.getModelType());
+ final Either<ModelData, JanusGraphOperationStatus> deleteParentNodeByModel = janusGraphGenericDao.deleteNode(modelData, ModelData.class);
+ if (deleteParentNodeByModel.isRight()) {
+ final var janusGraphOperationStatus = deleteParentNodeByModel.right().value();
+ log.error(EcompLoggerErrorCode.DATA_ERROR, ModelOperation.class.getName(),
+ "Failed to delete model {} on JanusGraph with status {}", new Object[] {model.getName(), janusGraphOperationStatus});
+ throw new OperationException(ActionStatus.COULD_NOT_DELETE_MODEL, model.getName());
+ }
+ }
+
+ @Autowired
+ public void setModelElementOperation(final ModelElementOperation modelElementOperation) {
+ this.modelElementOperation = modelElementOperation;
+ }
+
}
diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/PolicyTypeOperation.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/PolicyTypeOperation.java
index 99a2841..db3c557 100644
--- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/PolicyTypeOperation.java
+++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/PolicyTypeOperation.java
@@ -18,8 +18,8 @@
* ============LICENSE_END=========================================================
*/
package org.openecomp.sdc.be.model.operations.impl;
+
import static org.openecomp.sdc.be.dao.janusgraph.JanusGraphUtils.buildNotInPredicate;
-import static org.openecomp.sdc.common.log.enums.EcompLoggerErrorCode.BUSINESS_PROCESS_ERROR;
import fj.data.Either;
import java.util.ArrayList;
@@ -31,6 +31,9 @@
import java.util.Set;
import java.util.stream.Collectors;
import org.apache.commons.lang3.tuple.ImmutablePair;
+import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
+import org.apache.tinkerpop.gremlin.structure.Vertex;
+import org.janusgraph.core.JanusGraph;
import org.janusgraph.graphdb.query.JanusGraphPredicate;
import org.openecomp.sdc.be.config.BeEcompErrorManager;
import org.openecomp.sdc.be.dao.graph.datatype.GraphEdge;
@@ -60,13 +63,17 @@
private static final Logger log = Logger.getLogger(PolicyTypeOperation.class.getName());
private static final String CREATE_FLOW_CONTEXT = "CreatePolicyType";
private static final String GET_FLOW_CONTEXT = "GetPolicyType";
- @Autowired
- private PropertyOperation propertyOperation;
- @Autowired
- private DerivedFromOperation derivedFromOperation;
- @Autowired
- private OperationUtils operationUtils;
+ private final PropertyOperation propertyOperation;
+ private final DerivedFromOperation derivedFromOperation;
+ private final OperationUtils operationUtils;
+ @Autowired
+ public PolicyTypeOperation(final PropertyOperation propertyOperation, final DerivedFromOperation derivedFromOperation,
+ final OperationUtils operationUtils) {
+ this.propertyOperation = propertyOperation;
+ this.derivedFromOperation = derivedFromOperation;
+ this.operationUtils = operationUtils;
+ }
@Override
public Either<PolicyTypeDefinition, StorageOperationStatus> getLatestPolicyTypeByType(String type, String model) {
@@ -328,4 +335,18 @@
updatedTypeDefinition.setCreationTime(currTypeDefinition.getCreationTime());
updatedTypeDefinition.setModificationTime(System.currentTimeMillis());
}
+
+ public void deletePolicyTypesByModelId(final String modelId) {
+ final JanusGraph janusGraph = janusGraphGenericDao.getJanusGraph();
+ final GraphTraversalSource traversal = janusGraph.traversal();
+ final List<Vertex> policyTypeList = traversal.V()
+ .has(GraphPropertiesDictionary.UNIQUE_ID.getProperty(), modelId)
+ .out(GraphEdgeLabels.MODEL_ELEMENT.getProperty())
+ .has(GraphPropertiesDictionary.LABEL.getProperty(), NodeTypeEnum.PolicyType.getName())
+ .toList();
+ policyTypeList.forEach(policyTypeVertex -> {
+ traversal.V(policyTypeVertex).out(GraphEdgeLabels.PROPERTY.getProperty()).drop().iterate();
+ policyTypeVertex.remove();
+ });
+ }
}
diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/PropertyOperation.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/PropertyOperation.java
index 01dbb07..bf8d6ae 100644
--- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/PropertyOperation.java
+++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/PropertyOperation.java
@@ -119,15 +119,19 @@
private static final String THE_VALUE_OF_PROPERTY_FROM_TYPE_IS_INVALID = "The value {} of property from type {} is invalid";
private static final String PROPERTY = "Property";
private static final String UPDATE_DATA_TYPE = "UpdateDataType";
- private static Logger log = Logger.getLogger(PropertyOperation.class.getName());
- private DerivedFromOperation derivedFromOperation;
+ private static final Logger log = Logger.getLogger(PropertyOperation.class.getName());
+ private final DerivedFromOperation derivedFromOperation;
private DataTypeOperation dataTypeOperation;
@Autowired
- public PropertyOperation(HealingJanusGraphGenericDao janusGraphGenericDao, DerivedFromOperation derivedFromOperation,
- DataTypeOperation dataTypeOperation) {
+ public PropertyOperation(final HealingJanusGraphGenericDao janusGraphGenericDao, final DerivedFromOperation derivedFromOperation) {
this.janusGraphGenericDao = janusGraphGenericDao;
this.derivedFromOperation = derivedFromOperation;
+ }
+
+ //circular dependency DataTypeOperation->ModelOperation->ModelElementOperation->PropertyOperation
+ @Autowired
+ public void setDataTypeOperation(DataTypeOperation dataTypeOperation) {
this.dataTypeOperation = dataTypeOperation;
}
@@ -2264,4 +2268,5 @@
return null;
}
}
+
}
diff --git a/catalog-model/src/test/java/org/openecomp/sdc/be/model/operations/impl/DataTypeOperationTest.java b/catalog-model/src/test/java/org/openecomp/sdc/be/model/operations/impl/DataTypeOperationTest.java
index d93b798..1580fd3 100644
--- a/catalog-model/src/test/java/org/openecomp/sdc/be/model/operations/impl/DataTypeOperationTest.java
+++ b/catalog-model/src/test/java/org/openecomp/sdc/be/model/operations/impl/DataTypeOperationTest.java
@@ -38,7 +38,6 @@
import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum;
import org.openecomp.sdc.be.model.DataTypeDefinition;
import org.openecomp.sdc.be.model.Model;
-import org.openecomp.sdc.be.model.cache.ApplicationDataTypeCache;
import org.openecomp.sdc.be.resources.data.DataTypeData;
import org.springframework.test.context.ContextConfiguration;
@@ -51,8 +50,6 @@
private ModelOperation modelOperation;
@Mock
private HealingJanusGraphGenericDao janusGraphGenericDao;
- @Mock
- private ApplicationDataTypeCache applicationDataTypeCache;
private final String modelName = "ETSI-SDC-MODEL-TEST";
private final List<DataTypeData> dataTypesWithoutModel = new ArrayList<>();
@@ -61,10 +58,10 @@
final Map<String, DataTypeDefinition> allDataTypesFoundDefinitionMap = new HashMap<>();
private Model model;
-
@BeforeEach
void beforeEachInit() {
MockitoAnnotations.openMocks(this);
+ dataTypeOperation.setModelOperation(modelOperation);
initTestData();
}
diff --git a/catalog-model/src/test/java/org/openecomp/sdc/be/model/operations/impl/ModelElementOperationTest.java b/catalog-model/src/test/java/org/openecomp/sdc/be/model/operations/impl/ModelElementOperationTest.java
new file mode 100644
index 0000000..3de1369
--- /dev/null
+++ b/catalog-model/src/test/java/org/openecomp/sdc/be/model/operations/impl/ModelElementOperationTest.java
@@ -0,0 +1,96 @@
+/*
+ * -
+ * ============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.model.operations.impl;
+
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.openecomp.sdc.be.dao.janusgraph.JanusGraphGenericDao;
+import org.openecomp.sdc.be.model.Model;
+
+class ModelElementOperationTest {
+
+ @Mock
+ private JanusGraphGenericDao janusGraphGenericDao;
+ @Mock
+ private DataTypeOperation dataTypeOperation;
+ @Mock
+ private PolicyTypeOperation policyTypeOperation;
+ @InjectMocks
+ private ModelElementOperation modelElementOperation;
+
+ @BeforeEach
+ void setUp() {
+ MockitoAnnotations.openMocks(this);
+ }
+
+ @Test
+ void deleteModelElements_noTransactionSuccessTest() {
+ var model = new Model("name");
+ final String modelId = UniqueIdBuilder.buildModelUid(model.getName());
+ modelElementOperation.deleteModelElements(model, false);
+ verify(dataTypeOperation).deleteDataTypesByModelId(modelId);
+ verify(policyTypeOperation).deletePolicyTypesByModelId(modelId);
+ verify(janusGraphGenericDao).commit();
+ verify(janusGraphGenericDao, times(0)).rollback();
+ }
+
+ @Test
+ void deleteModelElements_inTransactionSuccessTest() {
+ var model = new Model("name");
+ final String modelId = UniqueIdBuilder.buildModelUid(model.getName());
+ modelElementOperation.deleteModelElements(model, true);
+ verify(dataTypeOperation).deleteDataTypesByModelId(modelId);
+ verify(policyTypeOperation).deletePolicyTypesByModelId(modelId);
+ verify(janusGraphGenericDao, times(0)).commit();
+ verify(janusGraphGenericDao, times(0)).rollback();
+ }
+
+ @Test
+ void deleteModelElements_noTransactionErrorTest() {
+ var model = new Model("name");
+ final String modelId = UniqueIdBuilder.buildModelUid(model.getName());
+ doThrow(new RuntimeException()).when(dataTypeOperation).deleteDataTypesByModelId(modelId);
+ assertThrows(RuntimeException.class, () -> modelElementOperation.deleteModelElements(model, false));
+ verify(dataTypeOperation).deleteDataTypesByModelId(modelId);
+ verify(janusGraphGenericDao).rollback();
+ verify(janusGraphGenericDao, times(0)).commit();
+ }
+
+ @Test
+ void deleteModelElements_inTransactionErrorTest() {
+ var model = new Model("name");
+ final String modelId = UniqueIdBuilder.buildModelUid(model.getName());
+ doThrow(new RuntimeException()).when(dataTypeOperation).deleteDataTypesByModelId(modelId);
+ assertThrows(RuntimeException.class, () -> modelElementOperation.deleteModelElements(model, true));
+ verify(dataTypeOperation).deleteDataTypesByModelId(modelId);
+ verify(janusGraphGenericDao, times(0)).commit();
+ verify(janusGraphGenericDao, times(0)).rollback();
+ }
+}
\ No newline at end of file
diff --git a/catalog-model/src/test/java/org/openecomp/sdc/be/model/operations/impl/PropertyOperationTest.java b/catalog-model/src/test/java/org/openecomp/sdc/be/model/operations/impl/PropertyOperationTest.java
index 793af71..a3c9bca 100644
--- a/catalog-model/src/test/java/org/openecomp/sdc/be/model/operations/impl/PropertyOperationTest.java
+++ b/catalog-model/src/test/java/org/openecomp/sdc/be/model/operations/impl/PropertyOperationTest.java
@@ -73,12 +73,12 @@
final DataTypeOperation dataTypeOperation = mock(DataTypeOperation.class);
- PropertyOperation propertyOperation = new PropertyOperation(janusGraphGenericDao, null, dataTypeOperation);
+ PropertyOperation propertyOperation = new PropertyOperation(janusGraphGenericDao, null);
@Before
public void setup() {
+ propertyOperation.setDataTypeOperation(dataTypeOperation);
propertyOperation.setJanusGraphGenericDao(janusGraphGenericDao);
-
}
private PropertyDefinition buildPropertyDefinition() {
@@ -456,9 +456,11 @@
}
- private PropertyOperation createTestSubject() {
- return new PropertyOperation(new HealingJanusGraphGenericDao(new JanusGraphClient()), null, dataTypeOperation);
- }
+ private PropertyOperation createTestSubject() {
+ final var propertyOperation = new PropertyOperation(new HealingJanusGraphGenericDao(new JanusGraphClient()), null);
+ propertyOperation.setDataTypeOperation(dataTypeOperation);
+ return propertyOperation;
+ }
@Test
public void testConvertPropertyDataToPropertyDefinition() throws Exception {
diff --git a/catalog-model/src/test/java/org/openecomp/sdc/be/model/operations/impl/ToscaElementLifecycleOperationTest.java b/catalog-model/src/test/java/org/openecomp/sdc/be/model/operations/impl/ToscaElementLifecycleOperationTest.java
index a80e44e..b4f6156 100644
--- a/catalog-model/src/test/java/org/openecomp/sdc/be/model/operations/impl/ToscaElementLifecycleOperationTest.java
+++ b/catalog-model/src/test/java/org/openecomp/sdc/be/model/operations/impl/ToscaElementLifecycleOperationTest.java
@@ -262,7 +262,7 @@
expectedIds.add(vertex4.getUniqueId());
verifyInCatalogData(4, expectedIds);
- lifecycleOperation.undoCheckout(vertex4.getUniqueId());
+ lifecycleOperation.undoCheckout(vertex4.getUniqueId(), null);
expectedIds.remove(vertex4.getUniqueId());
verifyInCatalogData(3, expectedIds);
diff --git a/common-be/src/main/java/org/openecomp/sdc/be/exception/BusinessException.java b/common-be/src/main/java/org/openecomp/sdc/be/exception/BusinessException.java
index 69fb00f..0b1224a 100644
--- a/common-be/src/main/java/org/openecomp/sdc/be/exception/BusinessException.java
+++ b/common-be/src/main/java/org/openecomp/sdc/be/exception/BusinessException.java
@@ -28,6 +28,10 @@
super(message);
}
+ protected BusinessException(final Throwable cause) {
+ super(cause);
+ }
+
protected BusinessException(final String message, final Throwable cause) {
super(message, cause);
}