Commit d003ddb3 by Madhan Neethiraj

ATLAS-2774: enhancement to support parameterized delete-type (hard or soft) per API call

parent 62cdbdc6
......@@ -33,6 +33,8 @@ public enum AtlasConfiguration {
QUERY_PARAM_MAX_LENGTH("atlas.query.param.max.length", 4*1024),
REST_API_ENABLE_DELETE_TYPE_OVERRIDE("atlas.rest.enable.delete.type.override", false),
NOTIFICATION_HOOK_TOPIC_NAME("atlas.notification.hook.topic.name", "ATLAS_HOOK"),
NOTIFICATION_ENTITIES_TOPIC_NAME("atlas.notification.entities.topic.name", "ATLAS_ENTITIES"),
......
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/
package org.apache.atlas.store;
import org.apache.commons.lang.StringUtils;
public enum DeleteType {
DEFAULT,
SOFT,
HARD;
public static DeleteType from(String s) {
if(StringUtils.isEmpty(s)) {
return DEFAULT;
}
switch (s.toLowerCase()) {
case "soft":
return SOFT;
case "hard":
return HARD;
default:
return DEFAULT;
}
}
}
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/
package org.apache.atlas.repository.store.graph.v1;
import org.apache.atlas.RequestContext;
import org.apache.atlas.store.DeleteType;
import org.apache.atlas.type.AtlasTypeRegistry;
import org.apache.atlas.util.AtlasRepositoryConfiguration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import javax.inject.Inject;
import javax.inject.Singleton;
@Singleton
@Component
public class DeleteHandlerDelegate {
private static final Logger LOG = LoggerFactory.getLogger(DeleteHandlerDelegate.class);
private final SoftDeleteHandlerV1 softDeleteHandler;
private final HardDeleteHandlerV1 hardDeleteHandler;
private final DeleteHandlerV1 defaultHandler;
@Inject
public DeleteHandlerDelegate(AtlasTypeRegistry typeRegistry) {
this.softDeleteHandler = new SoftDeleteHandlerV1(typeRegistry);
this.hardDeleteHandler = new HardDeleteHandlerV1(typeRegistry);
this.defaultHandler = getDefaultConfiguredHandler(typeRegistry);
}
public DeleteHandlerV1 getHandler() {
return getHandler(RequestContext.get().getDeleteType());
}
public DeleteHandlerV1 getHandler(DeleteType deleteType) {
if (deleteType == null) {
deleteType = DeleteType.DEFAULT;
}
switch (deleteType) {
case SOFT:
return softDeleteHandler;
case HARD:
return hardDeleteHandler;
default:
return defaultHandler;
}
}
private DeleteHandlerV1 getDefaultConfiguredHandler(AtlasTypeRegistry typeRegistry) {
DeleteHandlerV1 ret = null;
try {
Class handlerFromProperties = AtlasRepositoryConfiguration.getDeleteHandlerV1Impl();
LOG.info("Default delete handler set to: {}", handlerFromProperties.getName());
ret = (DeleteHandlerV1) handlerFromProperties.getConstructor(AtlasTypeRegistry.class).newInstance(typeRegistry);
} catch (Exception ex) {
LOG.error("Error instantiating default delete handler. Defaulting to: {}", softDeleteHandler.getClass().getName(), ex);
ret = softDeleteHandler;
}
return ret;
}
}
\ No newline at end of file
......@@ -19,14 +19,12 @@
package org.apache.atlas.repository.store.graph.v1;
import org.apache.atlas.RequestContext;
import org.apache.atlas.annotation.ConditionalOnAtlasProperty;
import org.apache.atlas.model.instance.AtlasEntity.Status;
import org.apache.atlas.repository.graph.GraphHelper;
import org.apache.atlas.repository.graphdb.AtlasEdge;
import org.apache.atlas.repository.graphdb.AtlasVertex;
import org.apache.atlas.repository.store.graph.v2.AtlasGraphUtilsV2;
import org.apache.atlas.type.AtlasTypeRegistry;
import org.springframework.stereotype.Component;
import javax.inject.Inject;
......@@ -35,8 +33,6 @@ import static org.apache.atlas.repository.Constants.MODIFICATION_TIMESTAMP_PROPE
import static org.apache.atlas.repository.Constants.MODIFIED_BY_KEY;
import static org.apache.atlas.repository.Constants.STATE_PROPERTY_KEY;
@Component
@ConditionalOnAtlasProperty(property = "atlas.DeleteHandlerV1.impl", isDefault = true)
public class SoftDeleteHandlerV1 extends DeleteHandlerV1 {
@Inject
......
......@@ -33,7 +33,7 @@ import org.apache.atlas.repository.graphdb.AtlasVertex;
import org.apache.atlas.repository.store.graph.AtlasEntityStore;
import org.apache.atlas.repository.store.graph.EntityGraphDiscovery;
import org.apache.atlas.repository.store.graph.EntityGraphDiscoveryContext;
import org.apache.atlas.repository.store.graph.v1.DeleteHandlerV1;
import org.apache.atlas.repository.store.graph.v1.DeleteHandlerDelegate;
import org.apache.atlas.type.AtlasClassificationType;
import org.apache.atlas.type.AtlasEntityType;
import org.apache.atlas.type.AtlasStructType.AtlasAttribute;
......@@ -62,16 +62,16 @@ public class AtlasEntityStoreV2 implements AtlasEntityStore {
private static final Logger PERF_LOG = AtlasPerfTracer.getPerfLogger("store.EntityStore");
private final DeleteHandlerV1 deleteHandler;
private final DeleteHandlerDelegate deleteDelegate;
private final AtlasTypeRegistry typeRegistry;
private final AtlasEntityChangeNotifier entityChangeNotifier;
private final EntityGraphMapper entityGraphMapper;
private final EntityGraphRetriever entityRetriever;
@Inject
public AtlasEntityStoreV2(DeleteHandlerV1 deleteHandler, AtlasTypeRegistry typeRegistry,
public AtlasEntityStoreV2(DeleteHandlerDelegate deleteDelegate, AtlasTypeRegistry typeRegistry,
AtlasEntityChangeNotifier entityChangeNotifier, EntityGraphMapper entityGraphMapper) {
this.deleteHandler = deleteHandler;
this.deleteDelegate = deleteDelegate;
this.typeRegistry = typeRegistry;
this.entityChangeNotifier = entityChangeNotifier;
this.entityGraphMapper = entityGraphMapper;
......@@ -802,7 +802,7 @@ public class AtlasEntityStoreV2 implements AtlasEntityStore {
EntityMutationResponse response = new EntityMutationResponse();
RequestContext req = RequestContext.get();
deleteHandler.deleteEntities(deletionCandidates); // this will update req with list of deleted/updated entities
deleteDelegate.getHandler().deleteEntities(deletionCandidates); // this will update req with list of deleted/updated entities
for (AtlasObjectId entity : req.getDeletedEntities()) {
response.addEntity(DELETE, entity);
......
......@@ -41,7 +41,7 @@ import org.apache.atlas.repository.graphdb.AtlasEdge;
import org.apache.atlas.repository.graphdb.AtlasEdgeDirection;
import org.apache.atlas.repository.graphdb.AtlasVertex;
import org.apache.atlas.repository.store.graph.AtlasRelationshipStore;
import org.apache.atlas.repository.store.graph.v1.DeleteHandlerV1;
import org.apache.atlas.repository.store.graph.v1.DeleteHandlerDelegate;
import org.apache.atlas.type.AtlasEntityType;
import org.apache.atlas.type.AtlasRelationshipType;
import org.apache.atlas.type.AtlasStructType.AtlasAttribute;
......@@ -95,15 +95,15 @@ public class AtlasRelationshipStoreV2 implements AtlasRelationshipStore {
private final AtlasTypeRegistry typeRegistry;
private final EntityGraphRetriever entityRetriever;
private final DeleteHandlerV1 deleteHandler;
private final DeleteHandlerDelegate deleteDelegate;
private final GraphHelper graphHelper = GraphHelper.getInstance();
private final AtlasEntityChangeNotifier entityChangeNotifier;
@Inject
public AtlasRelationshipStoreV2(AtlasTypeRegistry typeRegistry, DeleteHandlerV1 deleteHandler, AtlasEntityChangeNotifier entityChangeNotifier) {
public AtlasRelationshipStoreV2(AtlasTypeRegistry typeRegistry, DeleteHandlerDelegate deleteDelegate, AtlasEntityChangeNotifier entityChangeNotifier) {
this.typeRegistry = typeRegistry;
this.entityRetriever = new EntityGraphRetriever(typeRegistry);
this.deleteHandler = deleteHandler;
this.deleteDelegate = deleteDelegate;
this.entityChangeNotifier = entityChangeNotifier;
}
......@@ -277,7 +277,7 @@ public class AtlasRelationshipStoreV2 implements AtlasRelationshipStore {
AtlasAuthorizationUtils.verifyAccess(new AtlasRelationshipAccessRequest(typeRegistry,AtlasPrivilege.RELATIONSHIP_REMOVE, relationShipType, end1Entity, end2Entity ));
deleteHandler.deleteRelationships(Collections.singleton(edge), forceDelete);
deleteDelegate.getHandler().deleteRelationships(Collections.singleton(edge), forceDelete);
// notify entities for added/removed classification propagation
entityChangeNotifier.notifyPropagatedEntities();
......@@ -426,7 +426,7 @@ public class AtlasRelationshipStoreV2 implements AtlasRelationshipStore {
for (AtlasVertex classificationVertex : addedBlockedClassifications) {
List<AtlasVertex> removePropagationFromVertices = graphHelper.getPropagatedEntityVertices(classificationVertex);
deleteHandler.removeTagPropagation(classificationVertex, removePropagationFromVertices);
deleteDelegate.getHandler().removeTagPropagation(classificationVertex, removePropagationFromVertices);
}
// add propagated tag for removed entry
......@@ -435,7 +435,7 @@ public class AtlasRelationshipStoreV2 implements AtlasRelationshipStore {
for (AtlasVertex classificationVertex : removedBlockedClassifications) {
List<AtlasVertex> addPropagationToVertices = graphHelper.getPropagatedEntityVertices(classificationVertex);
deleteHandler.addTagPropagation(classificationVertex, addPropagationToVertices);
deleteDelegate.getHandler().addTagPropagation(classificationVertex, addPropagationToVertices);
}
}
}
......@@ -527,11 +527,11 @@ public class AtlasRelationshipStoreV2 implements AtlasRelationshipStore {
}
for (AtlasVertex classificationVertex : addPropagationsMap.keySet()) {
deleteHandler.addTagPropagation(classificationVertex, addPropagationsMap.get(classificationVertex));
deleteDelegate.getHandler().addTagPropagation(classificationVertex, addPropagationsMap.get(classificationVertex));
}
for (AtlasVertex classificationVertex : removePropagationsMap.keySet()) {
deleteHandler.removeTagPropagation(classificationVertex, removePropagationsMap.get(classificationVertex));
deleteDelegate.getHandler().removeTagPropagation(classificationVertex, removePropagationsMap.get(classificationVertex));
}
} else {
// update blocked propagated classifications only if there is no change is tag propagation (don't update both)
......@@ -758,7 +758,7 @@ public class AtlasRelationshipStoreV2 implements AtlasRelationshipStore {
handleBlockedClassifications(ret, relationship.getBlockedPropagatedClassifications());
// propagate tags
deleteHandler.addTagPropagation(ret, tagPropagation);
deleteDelegate.getHandler().addTagPropagation(ret, tagPropagation);
}
return ret;
......
......@@ -100,7 +100,7 @@ public class BulkImporterImpl implements BulkImporter {
throw abe;
}
} finally {
RequestContext.clear();
RequestContext.get().clearCache();
}
}
......
......@@ -26,7 +26,6 @@ import org.apache.atlas.model.TimeBoundary;
import org.apache.atlas.model.TypeCategory;
import org.apache.atlas.model.instance.AtlasClassification;
import org.apache.atlas.model.instance.AtlasEntity;
import org.apache.atlas.model.instance.AtlasEntity.AtlasEntityWithExtInfo;
import org.apache.atlas.model.instance.AtlasEntityHeader;
import org.apache.atlas.model.instance.AtlasObjectId;
import org.apache.atlas.model.instance.AtlasRelatedObjectId;
......@@ -43,7 +42,7 @@ import org.apache.atlas.repository.graphdb.AtlasEdge;
import org.apache.atlas.repository.graphdb.AtlasGraph;
import org.apache.atlas.repository.graphdb.AtlasVertex;
import org.apache.atlas.repository.store.graph.AtlasRelationshipStore;
import org.apache.atlas.repository.store.graph.v1.DeleteHandlerV1;
import org.apache.atlas.repository.store.graph.v1.DeleteHandlerDelegate;
import org.apache.atlas.type.AtlasArrayType;
import org.apache.atlas.type.AtlasBuiltInTypes;
import org.apache.atlas.type.AtlasClassificationType;
......@@ -93,7 +92,7 @@ public class EntityGraphMapper {
private final GraphHelper graphHelper = GraphHelper.getInstance();
private final AtlasGraph graph;
private final DeleteHandlerV1 deleteHandler;
private final DeleteHandlerDelegate deleteDelegate;
private final AtlasTypeRegistry typeRegistry;
private final AtlasRelationshipStore relationshipStore;
private final AtlasEntityChangeNotifier entityChangeNotifier;
......@@ -101,10 +100,10 @@ public class EntityGraphMapper {
private final EntityGraphRetriever entityRetriever;
@Inject
public EntityGraphMapper(DeleteHandlerV1 deleteHandler, AtlasTypeRegistry typeRegistry, AtlasGraph atlasGraph,
public EntityGraphMapper(DeleteHandlerDelegate deleteDelegate, AtlasTypeRegistry typeRegistry, AtlasGraph atlasGraph,
AtlasRelationshipStore relationshipStore, AtlasEntityChangeNotifier entityChangeNotifier,
AtlasInstanceConverter instanceConverter) {
this.deleteHandler = deleteHandler;
this.deleteDelegate = deleteDelegate;
this.typeRegistry = typeRegistry;
this.graph = atlasGraph;
this.relationshipStore = relationshipStore;
......@@ -394,7 +393,7 @@ public class EntityGraphMapper {
AtlasEdge newEdge = mapStructValue(ctx, context);
if (currentEdge != null && !currentEdge.equals(newEdge)) {
deleteHandler.deleteEdgeReference(currentEdge, ctx.getAttrType().getTypeCategory(), false, true, ctx.getReferringVertex());
deleteDelegate.getHandler().deleteEdgeReference(currentEdge, ctx.getAttrType().getTypeCategory(), false, true, ctx.getReferringVertex());
}
return newEdge;
......@@ -466,7 +465,7 @@ public class EntityGraphMapper {
}
//delete old reference
deleteHandler.deleteEdgeReference(currentEdge, ctx.getAttrType().getTypeCategory(), ctx.getAttribute().isOwnedRef(),
deleteDelegate.getHandler().deleteEdgeReference(currentEdge, ctx.getAttrType().getTypeCategory(), ctx.getAttribute().isOwnedRef(),
true, ctx.getAttribute().getRelationshipEdgeDirection(), ctx.getReferringVertex());
}
......@@ -527,7 +526,7 @@ public class EntityGraphMapper {
if (inverseEdge != null) {
if (!inverseEdge.equals(newEdge)) {
// Disconnect old reference
deleteHandler.deleteEdgeReference(inverseEdge, inverseAttribute.getAttributeType().getTypeCategory(),
deleteDelegate.getHandler().deleteEdgeReference(inverseEdge, inverseAttribute.getAttributeType().getTypeCategory(),
inverseAttribute.isOwnedRef(), true, inverseVertex);
}
else {
......@@ -1178,7 +1177,7 @@ public class EntityGraphMapper {
AtlasEdge currentEdge = (AtlasEdge) currentMap.get(currentKey);
if (!newMap.values().contains(currentEdge)) {
boolean deleted = deleteHandler.deleteEdgeReference(currentEdge, mapType.getValueType().getTypeCategory(), attribute.isOwnedRef(), true, vertex);
boolean deleted = deleteDelegate.getHandler().deleteEdgeReference(currentEdge, mapType.getValueType().getTypeCategory(), attribute.isOwnedRef(), true, vertex);
if (!deleted) {
additionalMap.put(currentKey, currentEdge);
......@@ -1308,7 +1307,7 @@ public class EntityGraphMapper {
List<AtlasEdge> additionalElements = new ArrayList<>();
for (AtlasEdge edge : edgesToRemove) {
boolean deleted = deleteHandler.deleteEdgeReference(edge, entryType.getTypeCategory(), attribute.isOwnedRef(),
boolean deleted = deleteDelegate.getHandler().deleteEdgeReference(edge, entryType.getTypeCategory(), attribute.isOwnedRef(),
true, attribute.getRelationshipEdgeDirection(), entityVertex);
if (!deleted) {
......@@ -1447,7 +1446,7 @@ public class EntityGraphMapper {
LOG.debug("Propagating tag: [{}][{}] to {}", classificationName, entityTypeName, getTypeNames(entitiesToPropagateTo));
}
List<AtlasVertex> entitiesPropagatedTo = deleteHandler.addTagPropagation(classificationVertex, entitiesToPropagateTo);
List<AtlasVertex> entitiesPropagatedTo = deleteDelegate.getHandler().addTagPropagation(classificationVertex, entitiesToPropagateTo);
if (entitiesPropagatedTo != null) {
for (AtlasVertex entityPropagatedTo : entitiesPropagatedTo) {
......@@ -1506,7 +1505,7 @@ public class EntityGraphMapper {
throw new AtlasBaseException(AtlasErrorCode.INSTANCE_GUID_NOT_FOUND, entityGuid);
}
deleteHandler.deletePropagatedClassification(entityVertex, classificationName, associatedEntityGuid);
deleteDelegate.getHandler().deletePropagatedClassification(entityVertex, classificationName, associatedEntityGuid);
}
public void deleteClassification(String entityGuid, String classificationName) throws AtlasBaseException {
......@@ -1535,7 +1534,7 @@ public class EntityGraphMapper {
// remove classification from propagated entities if propagation is turned on
if (isPropagationEnabled(classificationVertex)) {
List<AtlasVertex> propagatedEntityVertices = deleteHandler.removeTagPropagation(classificationVertex);
List<AtlasVertex> propagatedEntityVertices = deleteDelegate.getHandler().removeTagPropagation(classificationVertex);
// add propagated entities and deleted classification details to removeClassifications map
if (CollectionUtils.isNotEmpty(propagatedEntityVertices)) {
......@@ -1572,7 +1571,7 @@ public class EntityGraphMapper {
AtlasEdge edge = getClassificationEdge(entityVertex, classificationVertex);
deleteHandler.deleteEdgeReference(edge, CLASSIFICATION, false, true, entityVertex);
deleteDelegate.getHandler().deleteEdgeReference(edge, CLASSIFICATION, false, true, entityVertex);
traitNames.remove(classificationName);
......@@ -1701,7 +1700,7 @@ public class EntityGraphMapper {
}
}
List<AtlasVertex> entitiesPropagatedTo = deleteHandler.addTagPropagation(classificationVertex, entitiesToPropagateTo);
List<AtlasVertex> entitiesPropagatedTo = deleteDelegate.getHandler().addTagPropagation(classificationVertex, entitiesToPropagateTo);
if (entitiesPropagatedTo != null) {
for (AtlasVertex entityPropagatedTo : entitiesPropagatedTo) {
......@@ -1710,7 +1709,7 @@ public class EntityGraphMapper {
}
}
} else {
List<AtlasVertex> impactedVertices = deleteHandler.removeTagPropagation(classificationVertex);
List<AtlasVertex> impactedVertices = deleteDelegate.getHandler().removeTagPropagation(classificationVertex);
if (CollectionUtils.isNotEmpty(impactedVertices)) {
if (removedPropagations == null) {
......
......@@ -59,10 +59,7 @@ import org.apache.atlas.repository.store.graph.v2.AtlasEntityStoreV2;
import org.apache.atlas.repository.store.graph.v2.AtlasRelationshipStoreV2;
import org.apache.atlas.repository.store.graph.v2.AtlasTypeDefGraphStoreV2;
import org.apache.atlas.repository.store.graph.v2.BulkImporterImpl;
import org.apache.atlas.repository.store.graph.v1.DeleteHandlerV1;
import org.apache.atlas.repository.store.graph.v2.EntityGraphMapper;
import org.apache.atlas.repository.store.graph.v1.HardDeleteHandlerV1;
import org.apache.atlas.repository.store.graph.v1.SoftDeleteHandlerV1;
import org.apache.atlas.runner.LocalSolrRunner;
import org.apache.atlas.service.Service;
import org.apache.atlas.store.AtlasTypeDefStore;
......@@ -125,8 +122,6 @@ public class TestModules {
bindAuditRepository(binder());
bindDeleteHandler(binder());
bind(AtlasGraph.class).toProvider(AtlasGraphProvider.class);
// allow for dynamic binding of graph service
......@@ -186,10 +181,6 @@ public class TestModules {
bindInterceptor(Matchers.any(), Matchers.annotatedWith(GraphTransaction.class), graphTransactionInterceptor);
}
protected void bindDeleteHandler(Binder binder) {
binder.bind(DeleteHandlerV1.class).to(AtlasRepositoryConfiguration.getDeleteHandlerV1Impl()).asEagerSingleton();
}
protected void bindAuditRepository(Binder binder) {
Class<? extends EntityAuditRepository> auditRepoImpl = AtlasRepositoryConfiguration.getAuditRepositoryImpl();
......@@ -205,20 +196,4 @@ public class TestModules {
}
}
}
public static class SoftDeleteModule extends TestOnlyModule {
@Override
protected void bindDeleteHandler(Binder binder) {
bind(DeleteHandlerV1.class).to(SoftDeleteHandlerV1.class).asEagerSingleton();
bind(AtlasEntityChangeNotifier.class).toProvider(MockNotifier.class);
}
}
public static class HardDeleteModule extends TestOnlyModule {
@Override
protected void bindDeleteHandler(Binder binder) {
bind(DeleteHandlerV1.class).to(HardDeleteHandlerV1.class).asEagerSingleton();
bind(AtlasEntityChangeNotifier.class).toProvider(MockNotifier.class);
}
}
}
......@@ -18,14 +18,9 @@
package org.apache.atlas.repository.impexp;
import org.apache.atlas.ApplicationProperties;
import org.apache.atlas.AtlasConstants;
import org.apache.atlas.AtlasException;
import org.apache.atlas.exception.AtlasBaseException;
import org.apache.atlas.model.impexp.ExportImportAuditEntry;
import org.apache.atlas.model.instance.AtlasEntity;
import org.apache.atlas.repository.store.graph.v1.DeleteHandlerV1;
import org.apache.atlas.repository.store.graph.v1.SoftDeleteHandlerV1;
import org.apache.atlas.repository.store.graph.v2.AtlasEntityStoreV2;
import org.apache.atlas.store.AtlasTypeDefStore;
import org.apache.atlas.type.AtlasTypeRegistry;
......@@ -39,11 +34,9 @@ import static org.apache.atlas.repository.impexp.ZipFileResourceTestUtils.create
import static org.apache.atlas.repository.impexp.ZipFileResourceTestUtils.loadBaseModel;
import static org.apache.atlas.repository.impexp.ZipFileResourceTestUtils.loadEntity;
import static org.apache.atlas.repository.impexp.ZipFileResourceTestUtils.loadHiveModel;
import static org.mockito.Mockito.mock;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertTrue;
import static org.testng.Assert.fail;
public class ExportImportTestBase {
protected static final String ENTITIES_SUB_DIR = "stocksDB-Entities";
......@@ -53,7 +46,6 @@ public class ExportImportTestBase {
protected static final String TABLE_VIEW_GUID = "56415119-7cb0-40dd-ace8-1e50efd54991";
protected static final String COLUMN_GUID_HIGH = "f87a5320-1529-4369-8d63-b637ebdf2c1c";
protected DeleteHandlerV1 deleteHandler = mock(SoftDeleteHandlerV1.class);
protected void basicSetup(AtlasTypeDefStore typeDefStore, AtlasTypeRegistry typeRegistry) throws IOException, AtlasBaseException {
loadBaseModel(typeDefStore, typeRegistry);
......@@ -90,10 +82,6 @@ public class ExportImportTestBase {
assertTrue(result.size() > 0);
}
private String getCurrentCluster() throws AtlasException {
return ApplicationProperties.get().getString(AtlasConstants.CLUSTER_NAME_KEY, "default");
}
protected void pauseForIndexCreation() {
try {
Thread.sleep(5000);
......
......@@ -30,12 +30,8 @@ import org.apache.atlas.model.instance.EntityMutationResponse;
import org.apache.atlas.model.typedef.AtlasTypesDef;
import org.apache.atlas.repository.graph.AtlasGraphProvider;
import org.apache.atlas.repository.store.bootstrap.AtlasTypeDefStoreInitializer;
import org.apache.atlas.repository.store.graph.v2.AtlasEntityChangeNotifier;
import org.apache.atlas.repository.store.graph.v2.AtlasEntityStoreV2;
import org.apache.atlas.repository.store.graph.v2.AtlasEntityStream;
import org.apache.atlas.repository.store.graph.v1.DeleteHandlerV1;
import org.apache.atlas.repository.store.graph.v2.EntityGraphMapper;
import org.apache.atlas.repository.store.graph.v1.SoftDeleteHandlerV1;
import org.apache.atlas.runner.LocalSolrRunner;
import org.apache.atlas.store.AtlasTypeDefStore;
import org.apache.atlas.type.AtlasType;
......@@ -60,11 +56,9 @@ import java.util.List;
import java.util.Map;
import static org.apache.atlas.graph.GraphSandboxUtil.useLocalSolr;
import static org.mockito.Mockito.mock;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertTrue;
import static org.testng.Assert.fail;
@Guice(modules = TestModules.TestOnlyModule.class)
public class ExportServiceTest extends ExportImportTestBase {
......@@ -77,9 +71,6 @@ public class ExportServiceTest extends ExportImportTestBase {
private AtlasTypeDefStore typeDefStore;
@Inject
private EntityGraphMapper graphMapper;
@Inject
ExportService exportService;
@Inject
......@@ -88,9 +79,6 @@ public class ExportServiceTest extends ExportImportTestBase {
@Inject
private AtlasEntityStoreV2 entityStore;
private DeleteHandlerV1 deleteHandler = mock(SoftDeleteHandlerV1.class);;
private AtlasEntityChangeNotifier mockChangeNotifier = mock(AtlasEntityChangeNotifier.class);
@BeforeTest
public void setupTest() throws IOException, AtlasBaseException {
RequestContext.clear();
......
......@@ -25,8 +25,7 @@ import org.apache.atlas.TestUtilsV2;
import org.apache.atlas.exception.AtlasBaseException;
import org.apache.atlas.model.impexp.AtlasExportRequest;
import org.apache.atlas.model.instance.AtlasEntity;
import org.apache.atlas.repository.store.graph.v1.DeleteHandlerV1;
import org.apache.atlas.repository.store.graph.v1.SoftDeleteHandlerV1;
import org.apache.atlas.repository.store.graph.v1.DeleteHandlerDelegate;
import org.apache.atlas.repository.store.graph.v2.AtlasEntityChangeNotifier;
import org.apache.atlas.repository.store.graph.v2.AtlasEntityStoreV2;
import org.apache.atlas.repository.store.graph.v2.EntityGraphMapper;
......@@ -65,7 +64,7 @@ public class ExportSkipLineageTest extends ExportImportTestBase {
@Inject
ExportService exportService;
private DeleteHandlerV1 deleteHandler = mock(SoftDeleteHandlerV1.class);
private DeleteHandlerDelegate deleteDelegate = mock(DeleteHandlerDelegate.class);
private AtlasEntityChangeNotifier mockChangeNotifier = mock(AtlasEntityChangeNotifier.class);
private AtlasEntityStoreV2 entityStore;
......@@ -74,7 +73,7 @@ public class ExportSkipLineageTest extends ExportImportTestBase {
loadBaseModel(typeDefStore, typeRegistry);
loadHiveModel(typeDefStore, typeRegistry);
entityStore = new AtlasEntityStoreV2(deleteHandler, typeRegistry, mockChangeNotifier, graphMapper);
entityStore = new AtlasEntityStoreV2(deleteDelegate, typeRegistry, mockChangeNotifier, graphMapper);
createEntities(entityStore, ENTITIES_SUB_DIR, new String[]{"db", "table-columns", "table-view", "table-table-lineage"});
final String[] entityGuids = {DB_GUID, TABLE_GUID, TABLE_TABLE_GUID, TABLE_VIEW_GUID};
verifyCreatedEntities(entityStore, entityGuids, 4);
......
......@@ -18,7 +18,9 @@
package org.apache.atlas.repository.store.graph.v1;
import org.apache.atlas.RequestContext;
import org.apache.atlas.TestModules;
import org.apache.atlas.TestUtilsV2;
import org.apache.atlas.exception.AtlasBaseException;
import org.apache.atlas.model.instance.AtlasEntity;
import org.apache.atlas.model.instance.AtlasObjectId;
......@@ -32,10 +34,12 @@ import org.apache.atlas.repository.store.graph.AtlasEntityStore;
import org.apache.atlas.repository.store.graph.v2.AtlasEntityStream;
import org.apache.atlas.repository.store.graph.v2.AtlasGraphUtilsV2;
import org.apache.atlas.store.AtlasTypeDefStore;
import org.apache.atlas.store.DeleteType;
import org.apache.atlas.type.AtlasEntityType;
import org.apache.atlas.type.AtlasType;
import org.apache.atlas.type.AtlasTypeRegistry;
import org.apache.atlas.utils.TestResourceFileUtils;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Guice;
import org.testng.annotations.Test;
......@@ -50,7 +54,7 @@ import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertTrue;
@Guice(modules = TestModules.SoftDeleteModule.class)
@Guice(modules = TestModules.TestOnlyModule.class)
public class SoftReferenceTest {
private static final String TYPE_RDBMS_DB = "rdbms_db";
private static final String RDBMS_DB_FILE = "rdbms-db";
......@@ -75,6 +79,12 @@ public class SoftReferenceTest {
private String dbGuid;
private String storageGuid;
@BeforeMethod
public void init() throws Exception {
RequestContext.get().setUser(TestUtilsV2.TEST_USER, null);
RequestContext.get().setDeleteType(DeleteType.SOFT);
}
@Test
public void typeCreationFromFile() throws IOException, AtlasBaseException {
String typesDefJson = TestResourceFileUtils.getJson(TYPESDEF_FILE_NAME);
......
......@@ -109,7 +109,7 @@ public class AtlasEntityStoreV2Test extends AtlasEntityTestBase {
}
@BeforeTest
public void init() throws Exception {
entityStore = new AtlasEntityStoreV2(deleteHandler, typeRegistry, mockChangeNotifier, graphMapper);
entityStore = new AtlasEntityStoreV2(deleteDelegate, typeRegistry, mockChangeNotifier, graphMapper);
RequestContext.clear();
RequestContext.get().setUser(TestUtilsV2.TEST_USER, null);
......
......@@ -38,7 +38,7 @@ import org.apache.atlas.repository.graph.GraphBackedSearchIndexer;
import org.apache.atlas.repository.graphdb.AtlasGraph;
import org.apache.atlas.repository.store.bootstrap.AtlasTypeDefStoreInitializer;
import org.apache.atlas.repository.store.graph.AtlasEntityStore;
import org.apache.atlas.repository.store.graph.v1.DeleteHandlerV1;
import org.apache.atlas.repository.store.graph.v1.DeleteHandlerDelegate;
import org.apache.atlas.runner.LocalSolrRunner;
import org.apache.atlas.store.AtlasTypeDefStore;
import org.apache.atlas.type.AtlasArrayType;
......@@ -78,7 +78,7 @@ public class AtlasEntityTestBase {
AtlasEntityStore entityStore;
@Inject
DeleteHandlerV1 deleteHandler;
DeleteHandlerDelegate deleteDelegate;
@Inject
private EntityGraphMapper graphMapper;
......@@ -107,7 +107,7 @@ public class AtlasEntityTestBase {
@BeforeTest
public void init() throws Exception {
entityStore = new AtlasEntityStoreV2(deleteHandler, typeRegistry, mockChangeNotifier, graphMapper);
entityStore = new AtlasEntityStoreV2(deleteDelegate, typeRegistry, mockChangeNotifier, graphMapper);
RequestContext.clear();
RequestContext.get().setUser(TestUtilsV2.TEST_USER, null);
......
......@@ -18,11 +18,11 @@
package org.apache.atlas.repository.store.graph.v2;
import com.google.common.collect.ImmutableList;
import org.apache.atlas.TestModules;
import org.apache.atlas.RequestContext;
import org.apache.atlas.model.instance.AtlasEntity;
import org.apache.atlas.model.instance.AtlasObjectId;
import org.apache.atlas.repository.store.graph.v1.HardDeleteHandlerV1;
import org.testng.annotations.Guice;
import org.apache.atlas.store.DeleteType;
import org.testng.annotations.BeforeTest;
import java.util.List;
......@@ -32,11 +32,14 @@ import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertNull;
/**
* Inverse reference update test with {@link HardDeleteHandlerV1}
* Inverse reference update test with HardDeleteHandlerV1
*/
@Guice(modules = TestModules.HardDeleteModule.class)
public class AtlasRelationshipStoreHardDeleteV2Test extends AtlasRelationshipStoreV2Test {
public AtlasRelationshipStoreHardDeleteV2Test() {
super(DeleteType.HARD);
}
@Override
protected void verifyRelationshipAttributeUpdate_NonComposite_OneToMany(AtlasEntity jane) throws Exception {
// Max should have been removed from the subordinates list, leaving only John.
......
......@@ -18,11 +18,9 @@
package org.apache.atlas.repository.store.graph.v2;
import com.google.common.collect.ImmutableList;
import org.apache.atlas.TestModules;
import org.apache.atlas.model.instance.AtlasEntity;
import org.apache.atlas.model.instance.AtlasObjectId;
import org.apache.atlas.repository.store.graph.v1.SoftDeleteHandlerV1;
import org.testng.annotations.Guice;
import org.apache.atlas.store.DeleteType;
import java.util.List;
......@@ -32,11 +30,14 @@ import static org.testng.Assert.assertNotNull;
/**
* Inverse reference update test with {@link SoftDeleteHandlerV1}
* Inverse reference update test with SoftDeleteHandlerV1
*/
@Guice(modules = TestModules.SoftDeleteModule.class)
public class AtlasRelationshipStoreSoftDeleteV2Test extends AtlasRelationshipStoreV2Test {
public AtlasRelationshipStoreSoftDeleteV2Test() {
super(DeleteType.SOFT);
}
@Override
protected void verifyRelationshipAttributeUpdate_NonComposite_OneToMany(AtlasEntity jane) throws Exception {
// Max is still in the subordinates list, as the edge still exists with state DELETED
......
......@@ -35,9 +35,10 @@ import org.apache.atlas.repository.graph.GraphBackedSearchIndexer;
import org.apache.atlas.repository.store.bootstrap.AtlasTypeDefStoreInitializer;
import org.apache.atlas.repository.store.graph.AtlasEntityStore;
import org.apache.atlas.repository.store.graph.AtlasRelationshipStore;
import org.apache.atlas.repository.store.graph.v1.DeleteHandlerV1;
import org.apache.atlas.repository.store.graph.v1.DeleteHandlerDelegate;
import org.apache.atlas.runner.LocalSolrRunner;
import org.apache.atlas.store.AtlasTypeDefStore;
import org.apache.atlas.store.DeleteType;
import org.apache.atlas.type.AtlasEntityType;
import org.apache.atlas.type.AtlasTypeRegistry;
import org.apache.commons.collections.CollectionUtils;
......@@ -77,7 +78,7 @@ public abstract class AtlasRelationshipStoreV2Test {
AtlasTypeDefStore typeDefStore;
@Inject
DeleteHandlerV1 deleteHandler;
DeleteHandlerDelegate deleteDelegate;
@Inject
EntityGraphMapper graphMapper;
......@@ -88,9 +89,14 @@ public abstract class AtlasRelationshipStoreV2Test {
AtlasEntityStore entityStore;
AtlasRelationshipStore relationshipStore;
AtlasEntityChangeNotifier mockChangeNotifier = mock(AtlasEntityChangeNotifier.class);
private final DeleteType deleteType;
protected Map<String, AtlasObjectId> employeeNameIdMap = new HashMap<>();
protected AtlasRelationshipStoreV2Test(DeleteType delteType) {
this.deleteType = delteType;
}
@BeforeClass
public void setUp() throws Exception {
new GraphBackedSearchIndexer(typeRegistry);
......@@ -118,11 +124,12 @@ public abstract class AtlasRelationshipStoreV2Test {
@BeforeTest
public void init() throws Exception {
entityStore = new AtlasEntityStoreV2(deleteHandler, typeRegistry, mockChangeNotifier, graphMapper);
relationshipStore = new AtlasRelationshipStoreV2(typeRegistry, deleteHandler, entityNotifier);
entityStore = new AtlasEntityStoreV2(deleteDelegate, typeRegistry, mockChangeNotifier, graphMapper);
relationshipStore = new AtlasRelationshipStoreV2(typeRegistry, deleteDelegate, entityNotifier);
RequestContext.clear();
RequestContext.get().setUser(TestUtilsV2.TEST_USER, null);
RequestContext.get().setDeleteType(deleteType);
}
@AfterClass
......
......@@ -18,12 +18,10 @@
package org.apache.atlas.repository.store.graph.v2;
import com.google.common.collect.ImmutableList;
import org.apache.atlas.TestModules;
import org.apache.atlas.model.instance.AtlasEntity;
import org.apache.atlas.model.instance.AtlasObjectId;
import org.apache.atlas.repository.store.graph.v1.HardDeleteHandlerV1;
import org.apache.atlas.store.DeleteType;
import org.apache.atlas.type.AtlasTypeUtil;
import org.testng.annotations.Guice;
import java.util.Map;
......@@ -31,11 +29,14 @@ import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertTrue;
/**
* Inverse reference update test with {@link HardDeleteHandlerV1}
* Inverse reference update test with HardDeleteHandlerV1
*/
@Guice(modules = TestModules.HardDeleteModule.class)
public class InverseReferenceUpdateHardDeleteV2Test extends InverseReferenceUpdateV2Test {
public InverseReferenceUpdateHardDeleteV2Test() {
super(DeleteType.HARD);
}
@Override
protected void verify_testInverseReferenceAutoUpdate_NonComposite_OneToMany(AtlasEntity jane) throws Exception {
......
......@@ -18,12 +18,10 @@
package org.apache.atlas.repository.store.graph.v2;
import com.google.common.collect.ImmutableList;
import org.apache.atlas.TestModules;
import org.apache.atlas.model.instance.AtlasEntity;
import org.apache.atlas.model.instance.AtlasObjectId;
import org.apache.atlas.repository.store.graph.v1.SoftDeleteHandlerV1;
import org.apache.atlas.store.DeleteType;
import org.apache.atlas.type.AtlasTypeUtil;
import org.testng.annotations.Guice;
import java.util.Map;
......@@ -32,11 +30,14 @@ import static org.testng.Assert.assertTrue;
/**
* Inverse reference update test with {@link SoftDeleteHandlerV1}
* Inverse reference update test with SoftDeleteHandlerV1
*/
@Guice(modules = TestModules.SoftDeleteModule.class)
public class InverseReferenceUpdateSoftDeleteV2Test extends InverseReferenceUpdateV2Test {
public InverseReferenceUpdateSoftDeleteV2Test() {
super(DeleteType.SOFT);
}
@Override
protected void verify_testInverseReferenceAutoUpdate_NonComposite_OneToMany(AtlasEntity jane)
throws Exception {
......
......@@ -20,6 +20,7 @@ package org.apache.atlas.repository.store.graph.v2;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import org.apache.atlas.RequestContext;
import org.apache.atlas.TestModules;
import org.apache.atlas.TestUtilsV2;
import org.apache.atlas.model.instance.AtlasEntity;
import org.apache.atlas.model.instance.AtlasEntity.AtlasEntitiesWithExtInfo;
......@@ -33,12 +34,14 @@ import org.apache.atlas.repository.store.bootstrap.AtlasTypeDefStoreInitializer;
import org.apache.atlas.repository.store.graph.AtlasEntityStore;
import org.apache.atlas.runner.LocalSolrRunner;
import org.apache.atlas.store.AtlasTypeDefStore;
import org.apache.atlas.store.DeleteType;
import org.apache.atlas.type.AtlasEntityType;
import org.apache.atlas.type.AtlasTypeRegistry;
import org.apache.atlas.type.AtlasTypeUtil;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Guice;
import org.testng.annotations.Test;
import javax.inject.Inject;
......@@ -58,6 +61,7 @@ import static org.apache.atlas.TestUtilsV2.NAME;
* Test automatic inverse reference updating in V1 (V2?) code path.
*
*/
@Guice(modules = TestModules.TestOnlyModule.class)
public abstract class InverseReferenceUpdateV2Test {
@Inject
AtlasTypeRegistry typeRegistry;
......@@ -69,9 +73,14 @@ public abstract class InverseReferenceUpdateV2Test {
AtlasEntityStore entityStore;
private AtlasEntitiesWithExtInfo deptEntity;
private final DeleteType deleteType;
protected Map<String, AtlasObjectId> nameIdMap = new HashMap<>();
protected InverseReferenceUpdateV2Test(DeleteType deleteType) {
this.deleteType = deleteType;
}
@BeforeClass
public void setUp() throws Exception {
RequestContext.clear();
......@@ -110,6 +119,7 @@ public abstract class InverseReferenceUpdateV2Test {
public void init() throws Exception {
RequestContext.clear();
RequestContext.get().setUser(TestUtilsV2.TEST_USER, null);
RequestContext.get().setDeleteType(deleteType);
}
@Test
......
......@@ -22,6 +22,7 @@ import org.apache.atlas.model.instance.AtlasClassification;
import org.apache.atlas.model.instance.AtlasEntity;
import org.apache.atlas.model.instance.AtlasEntity.AtlasEntityWithExtInfo;
import org.apache.atlas.model.instance.AtlasObjectId;
import org.apache.atlas.store.DeleteType;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
......@@ -34,20 +35,21 @@ public class RequestContext {
private static final ThreadLocal<RequestContext> CURRENT_CONTEXT = new ThreadLocal<>();
private static final Set<RequestContext> ACTIVE_REQUESTS = new HashSet<>();
private final long requestTime = System.currentTimeMillis();
private final Map<String, AtlasObjectId> updatedEntities = new HashMap<>();
private final Map<String, AtlasObjectId> deletedEntities = new HashMap<>();
private final Map<String, AtlasEntity> entityCache = new HashMap<>();
private final Map<String, AtlasEntityWithExtInfo> entityExtInfoCache = new HashMap<>();
private final Map<String, List<AtlasClassification>> addedPropagations = new HashMap<>();
private final Map<String, List<AtlasClassification>> removedPropagations = new HashMap<>();
private final long requestTime = System.currentTimeMillis();
private List<EntityGuidPair> entityGuidInRequest = null;
private String user;
private Set<String> userGroups;
private String clientIPAddress;
private int maxAttempts = 1;
private int attemptCount = 1;
private String clientIPAddress;
private DeleteType deleteType = DeleteType.DEFAULT;
private int maxAttempts = 1;
private int attemptCount = 1;
private RequestContext() {
......@@ -74,16 +76,7 @@ public class RequestContext {
RequestContext instance = CURRENT_CONTEXT.get();
if (instance != null) {
instance.updatedEntities.clear();
instance.deletedEntities.clear();
instance.entityCache.clear();
instance.entityExtInfoCache.clear();
instance.addedPropagations.clear();
instance.removedPropagations.clear();
if (instance.entityGuidInRequest != null) {
instance.entityGuidInRequest.clear();
}
instance.clearCache();
synchronized (ACTIVE_REQUESTS) {
ACTIVE_REQUESTS.remove(instance);
......@@ -93,6 +86,19 @@ public class RequestContext {
CURRENT_CONTEXT.remove();
}
public void clearCache() {
this.updatedEntities.clear();
this.deletedEntities.clear();
this.entityCache.clear();
this.entityExtInfoCache.clear();
this.addedPropagations.clear();
this.removedPropagations.clear();
if (this.entityGuidInRequest != null) {
this.entityGuidInRequest.clear();
}
}
public static String getCurrentUser() {
RequestContext context = CURRENT_CONTEXT.get();
return context != null ? context.getUser() : null;
......@@ -111,6 +117,10 @@ public class RequestContext {
this.userGroups = userGroups;
}
public DeleteType getDeleteType() { return deleteType; }
public void setDeleteType(DeleteType deleteType) { this.deleteType = (deleteType == null) ? DeleteType.DEFAULT : deleteType; }
public String getClientIPAddress() {
return clientIPAddress;
}
......@@ -162,12 +172,6 @@ public class RequestContext {
}
}
public static RequestContext createContext() {
clear();
return get();
}
public static int getActiveRequestsCount() {
return ACTIVE_REQUESTS.size();
}
......
......@@ -22,10 +22,12 @@ import org.apache.atlas.AtlasClient;
import org.apache.atlas.AtlasException;
import org.apache.atlas.RequestContext;
import org.apache.atlas.authorize.AtlasAuthorizationUtils;
import org.apache.atlas.store.DeleteType;
import org.apache.atlas.util.AtlasRepositoryConfiguration;
import org.apache.atlas.web.util.DateTimeHelper;
import org.apache.atlas.web.util.Servlets;
import org.apache.commons.configuration.Configuration;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
......@@ -43,6 +45,8 @@ import java.util.Date;
import java.util.Set;
import java.util.UUID;
import static org.apache.atlas.AtlasConfiguration.REST_API_ENABLE_DELETE_TYPE_OVERRIDE;
/**
* This records audit information as part of the filter after processing the request
* and also introduces a UUID into request and response for tracing requests in logs.
......@@ -52,9 +56,15 @@ public class AuditFilter implements Filter {
private static final Logger LOG = LoggerFactory.getLogger(AuditFilter.class);
private static final Logger AUDIT_LOG = LoggerFactory.getLogger("AUDIT");
private boolean deleteTypeOverrideEnabled = false;
@Override
public void init(FilterConfig filterConfig) throws ServletException {
LOG.info("AuditFilter initialization started");
deleteTypeOverrideEnabled = REST_API_ENABLE_DELETE_TYPE_OVERRIDE.getBoolean();
LOG.info("REST_API_ENABLE_DELETE_TYPE_OVERRIDE={}", deleteTypeOverrideEnabled);
}
@Override
......@@ -69,6 +79,7 @@ public class AuditFilter implements Filter {
final String oldName = currentThread.getName();
final String user = AtlasAuthorizationUtils.getCurrentUserName();
final Set<String> userGroups = AtlasAuthorizationUtils.getCurrentUserGroups();
final String deleteType = httpRequest.getParameter("deleteType");
try {
currentThread.setName(formatName(oldName, requestId));
......@@ -77,6 +88,15 @@ public class AuditFilter implements Filter {
RequestContext requestContext = RequestContext.get();
requestContext.setUser(user, userGroups);
requestContext.setClientIPAddress(AtlasAuthorizationUtils.getRequestIpAddress(httpRequest));
if (StringUtils.isNotEmpty(deleteType)) {
if (deleteTypeOverrideEnabled) {
requestContext.setDeleteType(DeleteType.from(deleteType));
} else {
LOG.warn("Override of deleteType is not enabled. Ignoring parameter deleteType={}, in request from user={}", deleteType, user);
}
}
filterChain.doFilter(request, response);
} finally {
long timeTaken = System.currentTimeMillis() - startTime;
......
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* 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.
*/
package org.apache.atlas.web.adapters;
import org.apache.atlas.RequestContext;
import org.apache.atlas.TestModules;
import org.apache.atlas.TestUtilsV2;
import org.apache.atlas.exception.AtlasBaseException;
import org.apache.atlas.model.instance.AtlasEntity;
import org.apache.atlas.model.instance.AtlasEntityHeader;
import org.apache.atlas.model.instance.EntityMutationResponse;
import org.apache.atlas.model.instance.EntityMutations;
import org.apache.atlas.model.typedef.AtlasTypesDef;
import org.apache.atlas.store.AtlasTypeDefStore;
import org.apache.atlas.store.DeleteType;
import org.apache.atlas.web.rest.EntityREST;
import org.mockito.Mockito;
import org.testng.Assert;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Guice;
import org.testng.annotations.Test;
import javax.inject.Inject;
import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static org.testng.Assert.assertNotNull;
import static org.testng.AssertJUnit.assertTrue;
import static org.testng.FileAssert.fail;
@Guice(modules = {TestModules.TestOnlyModule.class})
public class TestEntityRESTDelete {
@Inject
private AtlasTypeDefStore typeStore;
@Inject
private EntityREST entityREST;
private List<AtlasEntity> dbEntities = new ArrayList<>();
@BeforeClass
public void setUp() throws Exception {
AtlasTypesDef typesDef = TestUtilsV2.defineHiveTypes();
typeStore.createTypesDef(typesDef);
}
@AfterMethod
public void cleanup() {
RequestContext.clear();
}
private void assertSoftDelete(String guid) throws AtlasBaseException {
AtlasEntity.AtlasEntityWithExtInfo entity = entityREST.getById(guid, false);
assertTrue(entity != null && entity.getEntity().getStatus() == AtlasEntity.Status.DELETED);
}
private void assertHardDelete(String guid) {
try {
entityREST.getById(guid, false);
fail("Entity should have been deleted. Exception should have been thrown.");
} catch (AtlasBaseException e) {
assertTrue(true);
}
}
private void createEntities() throws Exception {
dbEntities.clear();
for (int i = 1; i <= 2; i++) {
AtlasEntity dbEntity = TestUtilsV2.createDBEntity();
final EntityMutationResponse response = entityREST.createOrUpdate(new AtlasEntity.AtlasEntitiesWithExtInfo(dbEntity));
assertNotNull(response);
List<AtlasEntityHeader> entitiesMutated = response.getEntitiesByOperation(EntityMutations.EntityOperation.CREATE);
assertNotNull(entitiesMutated);
Assert.assertEquals(entitiesMutated.size(), 1);
assertNotNull(entitiesMutated.get(0));
dbEntity.setGuid(entitiesMutated.get(0).getGuid());
dbEntities.add(dbEntity);
}
}
@Test
public void deleteByGuidTestSoft() throws Exception {
RequestContext.get().setDeleteType(DeleteType.SOFT);
createEntities();
EntityMutationResponse response = entityREST.deleteByGuid(dbEntities.get(0).getGuid());
assertNotNull(response);
assertNotNull(response.getDeletedEntities());
assertSoftDelete(dbEntities.get(0).getGuid());
}
@Test
public void deleteByGuidTestHard() throws Exception {
RequestContext.get().setDeleteType(DeleteType.HARD);
createEntities();
EntityMutationResponse response = entityREST.deleteByGuid(dbEntities.get(0).getGuid());
assertNotNull(response);
assertNotNull(response.getDeletedEntities());
assertHardDelete(dbEntities.get(0).getGuid());
}
@Test
public void deleteByGuidsSoft() throws Exception {
RequestContext.get().setDeleteType(DeleteType.SOFT);
createEntities();
List<String> guids = new ArrayList<>();
guids.add(dbEntities.get(0).getGuid());
guids.add(dbEntities.get(1).getGuid());
EntityMutationResponse response = entityREST.deleteByGuids(guids);
assertNotNull(response);
assertNotNull(response.getDeletedEntities());
for (String guid : guids) {
assertSoftDelete(guid);
}
}
@Test
public void deleteByGuidsHard() throws Exception {
RequestContext.get().setDeleteType(DeleteType.HARD);
createEntities();
List<String> guids = new ArrayList<>();
guids.add(dbEntities.get(0).getGuid());
guids.add(dbEntities.get(1).getGuid());
EntityMutationResponse response = entityREST.deleteByGuids(guids);
assertNotNull(response);
assertNotNull(response.getDeletedEntities());
for (String guid : guids) {
assertHardDelete(guid);
}
}
@Test
public void testUpdateGetDeleteEntityByUniqueAttributeSoft() throws Exception {
RequestContext.get().setDeleteType(DeleteType.SOFT);
createEntities();
entityREST.deleteByUniqueAttribute(TestUtilsV2.DATABASE_TYPE, toHttpServletRequest(TestUtilsV2.NAME,
(String) dbEntities.get(0).getAttribute(TestUtilsV2.NAME)));
assertSoftDelete(dbEntities.get(0).getGuid());
}
@Test
public void testUpdateGetDeleteEntityByUniqueAttributeHard() throws Exception {
RequestContext.get().setDeleteType(DeleteType.HARD);
createEntities();
entityREST.deleteByUniqueAttribute(TestUtilsV2.DATABASE_TYPE, toHttpServletRequest(TestUtilsV2.NAME,
(String) dbEntities.get(0).getAttribute(TestUtilsV2.NAME)));
assertHardDelete(dbEntities.get(0).getGuid());
}
private HttpServletRequest toHttpServletRequest(String attrName, String attrValue) {
HttpServletRequest request = Mockito.mock(HttpServletRequest.class);
Map<String, String[]> paramsMap = toParametersMap(EntityREST.PREFIX_ATTR + attrName, attrValue);
Mockito.when(request.getParameterMap()).thenReturn(paramsMap);
return request;
}
private Map<String, String[]> toParametersMap(final String name, final String value) {
return new HashMap<String, String[]>() {{
put(name, new String[]{value});
}};
}
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment