Repository: atlas Updated Branches: refs/heads/branch-0.8 9c1008ddb -> 8d926f21f
ATLAS-2798: Export & Import Audits. Project: http://git-wip-us.apache.org/repos/asf/atlas/repo Commit: http://git-wip-us.apache.org/repos/asf/atlas/commit/8d926f21 Tree: http://git-wip-us.apache.org/repos/asf/atlas/tree/8d926f21 Diff: http://git-wip-us.apache.org/repos/asf/atlas/diff/8d926f21 Branch: refs/heads/branch-0.8 Commit: 8d926f21fe3d447f8fbe13a760cc224fc1b6e757 Parents: 9c1008d Author: Ashutosh Mestry <ames...@hortonworks.com> Authored: Thu Aug 2 08:26:20 2018 -0700 Committer: Ashutosh Mestry <ames...@hortonworks.com> Committed: Thu Aug 2 08:46:41 2018 -0700 ---------------------------------------------------------------------- addons/models/0010-base_model.json | 73 ++++++++++ .../model/impexp/ExportImportAuditEntry.java | 135 +++++++++++++++++++ .../impexp/ExportImportAuditService.java | 121 +++++++++++++++++ .../atlas/repository/ogm/DTORegistry.java | 1 + .../apache/atlas/repository/ogm/DataAccess.java | 7 +- .../ogm/ExportImportAuditEntryDTO.java | 90 +++++++++++++ .../impexp/ExportImportAuditServiceTest.java | 119 ++++++++++++++++ .../atlas/web/resources/AdminResource.java | 34 ++++- .../atlas/web/resources/AdminResourceTest.java | 4 +- 9 files changed, 579 insertions(+), 5 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/atlas/blob/8d926f21/addons/models/0010-base_model.json ---------------------------------------------------------------------- diff --git a/addons/models/0010-base_model.json b/addons/models/0010-base_model.json index 2003d89..59660c5 100644 --- a/addons/models/0010-base_model.json +++ b/addons/models/0010-base_model.json @@ -249,6 +249,79 @@ "isUnique": false } ] + }, + { + "name": "__ExportImportAuditEntry", + "typeVersion": "1.0", + "superTypes": [ + "__internal" + ], + "attributeDefs": [ + { + "name": "userName", + "typeName": "string", + "cardinality": "SINGLE", + "isIndexable": false, + "isOptional": true, + "isUnique": false + }, + { + "name": "operation", + "typeName": "string", + "cardinality": "SINGLE", + "isIndexable": true, + "isOptional": false, + "isUnique": false + }, + { + "name": "sourceClusterName", + "typeName": "string", + "cardinality": "SINGLE", + "isIndexable": true, + "isOptional": false, + "isUnique": false + }, + { + "name": "targetClusterName", + "typeName": "string", + "cardinality": "SINGLE", + "isIndexable": true, + "isOptional": true, + "isUnique": false + }, + { + "name": "operationParams", + "typeName": "string", + "cardinality": "SINGLE", + "isIndexable": true, + "isOptional": true, + "isUnique": false + }, + { + "name": "operationStartTime", + "typeName": "long", + "cardinality": "SINGLE", + "isIndexable": true, + "isOptional": false, + "isUnique": false + }, + { + "name": "operationEndTime", + "typeName": "long", + "cardinality": "SINGLE", + "isIndexable": true, + "isOptional": true, + "isUnique": false + }, + { + "name": "resultSummary", + "typeName": "string", + "cardinality": "SINGLE", + "isIndexable": false, + "isOptional": true, + "isUnique": false + } + ] } ] } http://git-wip-us.apache.org/repos/asf/atlas/blob/8d926f21/intg/src/main/java/org/apache/atlas/model/impexp/ExportImportAuditEntry.java ---------------------------------------------------------------------- diff --git a/intg/src/main/java/org/apache/atlas/model/impexp/ExportImportAuditEntry.java b/intg/src/main/java/org/apache/atlas/model/impexp/ExportImportAuditEntry.java new file mode 100644 index 0000000..2c83c42 --- /dev/null +++ b/intg/src/main/java/org/apache/atlas/model/impexp/ExportImportAuditEntry.java @@ -0,0 +1,135 @@ +/** + * 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.model.impexp; + +import org.apache.atlas.model.AtlasBaseModelObject; +import org.codehaus.jackson.annotate.JsonAutoDetect; +import org.codehaus.jackson.annotate.JsonIgnoreProperties; +import org.codehaus.jackson.map.annotate.JsonSerialize; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +import static org.codehaus.jackson.annotate.JsonAutoDetect.Visibility.NONE; +import static org.codehaus.jackson.annotate.JsonAutoDetect.Visibility.PUBLIC_ONLY; + +@JsonAutoDetect(getterVisibility = PUBLIC_ONLY, setterVisibility = PUBLIC_ONLY, fieldVisibility = NONE) +@JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL) +@JsonIgnoreProperties(ignoreUnknown = true) +public class ExportImportAuditEntry extends AtlasBaseModelObject implements Serializable { + private static final long serialVersionUID = 1L; + public static final String OPERATION_EXPORT = "EXPORT"; + public static final String OPERATION_IMPORT = "IMPORT"; + + private String userName; + private String operation; + private String operationParams; + private long startTime; + private long endTime; + private String resultSummary; + private String sourceClusterName; + private String targetClusterName; + + public ExportImportAuditEntry() { + + } + + public ExportImportAuditEntry(String sourceClusterName, String operation) { + this.sourceClusterName = sourceClusterName; + this.operation = operation; + } + + public String getOperation() { + return operation; + } + + public void setOperation(String operation) { + this.operation = operation; + } + + public void setUserName(String userName) { + this.userName = userName; + } + + public String getUserName() { + return this.userName; + } + public void setOperationParams(String operationParams) { + this.operationParams = operationParams; + } + + public String getOperationParams() { + return this.operationParams; + } + + public void setStartTime(long startTime) { + this.startTime = startTime; + } + + public long getStartTime() { + return startTime; + } + + public void setEndTime(long endTime) { + this.endTime = endTime; + } + + public long getEndTime() { + return this.endTime; + } + + public String getTargetClusterName() { + return this.targetClusterName; + } + + public String getSourceClusterName() { + return this.sourceClusterName; + } + + public void setSourceClusterName(String sourceClusterName) { + this.sourceClusterName = sourceClusterName; + } + + public void setTargetClusterName(String targetClusterName) { + this.targetClusterName = targetClusterName; + } + + public String getResultSummary() { + return resultSummary; + } + + public void setResultSummary(String resultSummary) { + this.resultSummary = resultSummary; + } + + @Override + public StringBuilder toString(StringBuilder sb) { + sb.append(", userName: ").append(userName); + sb.append(", operation: ").append(operation); + sb.append(", operationParams: ").append(operationParams); + sb.append(", sourceClusterName: ").append(sourceClusterName); + sb.append(", targetClusterName: ").append(targetClusterName); + sb.append(", startTime: ").append(startTime); + sb.append(", endTime: ").append(endTime); + sb.append(", resultSummary: ").append(resultSummary); + + return sb; + } +} http://git-wip-us.apache.org/repos/asf/atlas/blob/8d926f21/repository/src/main/java/org/apache/atlas/repository/impexp/ExportImportAuditService.java ---------------------------------------------------------------------- diff --git a/repository/src/main/java/org/apache/atlas/repository/impexp/ExportImportAuditService.java b/repository/src/main/java/org/apache/atlas/repository/impexp/ExportImportAuditService.java new file mode 100644 index 0000000..ebfc33f --- /dev/null +++ b/repository/src/main/java/org/apache/atlas/repository/impexp/ExportImportAuditService.java @@ -0,0 +1,121 @@ +/** + * 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.impexp; + +import org.apache.atlas.annotation.AtlasService; +import org.apache.atlas.discovery.AtlasDiscoveryService; +import org.apache.atlas.exception.AtlasBaseException; +import org.apache.atlas.model.discovery.AtlasSearchResult; +import org.apache.atlas.model.discovery.SearchParameters; +import org.apache.atlas.model.impexp.ExportImportAuditEntry; +import org.apache.atlas.repository.ogm.DataAccess; +import org.apache.atlas.repository.ogm.ExportImportAuditEntryDTO; +import org.apache.commons.lang.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.inject.Inject; +import java.util.ArrayList; + +@AtlasService +public class ExportImportAuditService { + private static final Logger LOG = LoggerFactory.getLogger(ExportImportAuditService.class); + private static final String ENTITY_TYPE_NAME = "__ExportImportAuditEntry"; + + private final DataAccess dataAccess; + private AtlasDiscoveryService discoveryService; + + @Inject + public ExportImportAuditService(DataAccess dataAccess, AtlasDiscoveryService discoveryService) { + this.dataAccess = dataAccess; + this.discoveryService = discoveryService; + } + + public void save(ExportImportAuditEntry entry) throws AtlasBaseException { + dataAccess.saveNoLoad(entry); + } + public ExportImportAuditEntry get(ExportImportAuditEntry entry) throws AtlasBaseException { + if(entry.getGuid() == null) { + throw new AtlasBaseException("entity does not have GUID set. load cannot proceed."); + } + return dataAccess.load(entry); + } + + public AtlasSearchResult get(String userName, String operation, String sourceCluster, String targetCluster, + String startTime, String endTime, + int limit, int offset) throws AtlasBaseException { + SearchParameters.FilterCriteria criteria = new SearchParameters.FilterCriteria(); + criteria.setCriterion(new ArrayList<SearchParameters.FilterCriteria>()); + + addSearchParameters(criteria, userName, operation, sourceCluster, targetCluster, startTime, endTime); + + SearchParameters searchParameters = getSearchParameters(limit, offset, criteria); + + return discoveryService.searchWithParameters(searchParameters); + } + + private SearchParameters getSearchParameters(int limit, int offset, SearchParameters.FilterCriteria criteria) { + SearchParameters searchParameters = new SearchParameters(); + searchParameters.setTypeName(ENTITY_TYPE_NAME); + searchParameters.setEntityFilters(criteria); + searchParameters.setLimit(limit); + searchParameters.setOffset(offset); + return searchParameters; + } + + private void addSearchParameters(SearchParameters.FilterCriteria criteria, + String userName, String operation, String sourceCluster, String targetCluster, + String startTime, String endTime) { + + addParameterIfValueNotEmpty(criteria, ExportImportAuditEntryDTO.PROPERTY_USER_NAME, userName); + addParameterIfValueNotEmpty(criteria, ExportImportAuditEntryDTO.PROPERTY_OPERATION, operation); + addParameterIfValueNotEmpty(criteria, ExportImportAuditEntryDTO.PROPERTY_SOURCE_CLUSTER_NAME, sourceCluster); + addParameterIfValueNotEmpty(criteria, ExportImportAuditEntryDTO.PROPERTY_TARGET_CLUSTER_NAME, targetCluster); + addParameterIfValueNotEmpty(criteria, ExportImportAuditEntryDTO.PROPERTY_START_TIME, startTime); + addParameterIfValueNotEmpty(criteria, ExportImportAuditEntryDTO.PROPERTY_END_TIME, endTime); + } + + private void addParameterIfValueNotEmpty(SearchParameters.FilterCriteria criteria, + String attributeName, String value) { + if(StringUtils.isEmpty(value)) return; + + boolean isFirstCriteria = criteria.getAttributeName() == null; + SearchParameters.FilterCriteria cx = isFirstCriteria + ? criteria + : new SearchParameters.FilterCriteria(); + + setCriteria(cx, attributeName, value); + + if(isFirstCriteria) { + cx.setCondition(SearchParameters.FilterCriteria.Condition.AND); + } + + if(!isFirstCriteria) { + criteria.getCriterion().add(cx); + } + } + + private SearchParameters.FilterCriteria setCriteria(SearchParameters.FilterCriteria criteria, String attributeName, String value) { + criteria.setAttributeName(attributeName); + criteria.setAttributeValue(value); + criteria.setOperator(SearchParameters.Operator.EQ); + + return criteria; + } +} http://git-wip-us.apache.org/repos/asf/atlas/blob/8d926f21/repository/src/main/java/org/apache/atlas/repository/ogm/DTORegistry.java ---------------------------------------------------------------------- diff --git a/repository/src/main/java/org/apache/atlas/repository/ogm/DTORegistry.java b/repository/src/main/java/org/apache/atlas/repository/ogm/DTORegistry.java index c62ce1b..d417ce7 100644 --- a/repository/src/main/java/org/apache/atlas/repository/ogm/DTORegistry.java +++ b/repository/src/main/java/org/apache/atlas/repository/ogm/DTORegistry.java @@ -38,6 +38,7 @@ public class DTORegistry { registerDTO(savedSearchDTO); registerDTO(userProfileDTO); registerDTO(new AtlasClusterDTO(typeRegistry)); + registerDTO(new ExportImportAuditEntryDTO(typeRegistry)); } public <T extends DataTransferObject> DataTransferObject get(Type t) { http://git-wip-us.apache.org/repos/asf/atlas/blob/8d926f21/repository/src/main/java/org/apache/atlas/repository/ogm/DataAccess.java ---------------------------------------------------------------------- diff --git a/repository/src/main/java/org/apache/atlas/repository/ogm/DataAccess.java b/repository/src/main/java/org/apache/atlas/repository/ogm/DataAccess.java index c99d2f8..b7e943f 100644 --- a/repository/src/main/java/org/apache/atlas/repository/ogm/DataAccess.java +++ b/repository/src/main/java/org/apache/atlas/repository/ogm/DataAccess.java @@ -42,6 +42,11 @@ public class DataAccess { } public <T extends AtlasBaseModelObject> T save(T obj) throws AtlasBaseException { + saveNoLoad(obj); + return this.load(obj); + } + + public <T extends AtlasBaseModelObject> void saveNoLoad(T obj) throws AtlasBaseException { DataTransferObject<T> dto = (DataTransferObject<T>)dtoRegistry.get(obj.getClass()); AtlasEntityWithExtInfo entityWithExtInfo = dto.toEntityWithExtInfo(obj); @@ -50,8 +55,6 @@ public class DataAccess { if (hasError(entityMutationResponse)) { throw new AtlasBaseException(AtlasErrorCode.DATA_ACCESS_SAVE_FAILED, obj.toString()); } - - return this.load(obj); } public <T extends AtlasBaseModelObject> T load(T obj) throws AtlasBaseException { http://git-wip-us.apache.org/repos/asf/atlas/blob/8d926f21/repository/src/main/java/org/apache/atlas/repository/ogm/ExportImportAuditEntryDTO.java ---------------------------------------------------------------------- diff --git a/repository/src/main/java/org/apache/atlas/repository/ogm/ExportImportAuditEntryDTO.java b/repository/src/main/java/org/apache/atlas/repository/ogm/ExportImportAuditEntryDTO.java new file mode 100644 index 0000000..8d1aebf --- /dev/null +++ b/repository/src/main/java/org/apache/atlas/repository/ogm/ExportImportAuditEntryDTO.java @@ -0,0 +1,90 @@ +/** + * 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.ogm; + +import org.apache.atlas.exception.AtlasBaseException; +import org.apache.atlas.model.instance.AtlasEntity; +import org.apache.atlas.model.impexp.ExportImportAuditEntry; +import org.apache.atlas.type.AtlasTypeRegistry; + +import java.util.Map; + +public class ExportImportAuditEntryDTO extends AbstractDataTransferObject<ExportImportAuditEntry> { + + public static final String PROPERTY_USER_NAME = "userName"; + public static final String PROPERTY_OPERATION = "operation"; + public static final String PROPERTY_OPERATION_PARAMS = "operationParams"; + public static final String PROPERTY_START_TIME = "operationStartTime"; + public static final String PROPERTY_END_TIME = "operationEndTime"; + public static final String PROPERTY_RESULT_SUMMARY = "resultSummary"; + public static final String PROPERTY_SOURCE_CLUSTER_NAME = "sourceClusterName"; + public static final String PROPERTY_TARGET_CLUSTER_NAME = "targetClusterName"; + + protected ExportImportAuditEntryDTO(AtlasTypeRegistry typeRegistry) { + super(typeRegistry, ExportImportAuditEntry.class); + } + + @Override + public ExportImportAuditEntry from(AtlasEntity entity) { + ExportImportAuditEntry entry = new ExportImportAuditEntry(); + + setGuid(entry, entity); + entry.setUserName((String) entity.getAttribute(PROPERTY_USER_NAME)); + entry.setOperation((String) entity.getAttribute(PROPERTY_OPERATION)); + entry.setOperationParams((String) entity.getAttribute(PROPERTY_OPERATION_PARAMS)); + entry.setStartTime((long) entity.getAttribute(PROPERTY_START_TIME)); + entry.setEndTime((long) entity.getAttribute(PROPERTY_END_TIME)); + entry.setSourceClusterName((String) entity.getAttribute(PROPERTY_SOURCE_CLUSTER_NAME)); + entry.setTargetClusterName((String) entity.getAttribute(PROPERTY_TARGET_CLUSTER_NAME)); + entry.setResultSummary((String) entity.getAttribute(PROPERTY_RESULT_SUMMARY)); + + return entry; + } + + @Override + public ExportImportAuditEntry from(AtlasEntity.AtlasEntityWithExtInfo entityWithExtInfo) { + return from(entityWithExtInfo.getEntity()); + } + + @Override + public AtlasEntity toEntity(ExportImportAuditEntry obj) { + AtlasEntity entity = getDefaultAtlasEntity(obj); + + entity.setAttribute(PROPERTY_USER_NAME, obj.getUserName()); + entity.setAttribute(PROPERTY_OPERATION, obj.getOperation()); + entity.setAttribute(PROPERTY_OPERATION_PARAMS, obj.getOperationParams()); + entity.setAttribute(PROPERTY_START_TIME, obj.getStartTime()); + entity.setAttribute(PROPERTY_END_TIME, obj.getEndTime()); + entity.setAttribute(PROPERTY_SOURCE_CLUSTER_NAME, obj.getSourceClusterName()); + entity.setAttribute(PROPERTY_TARGET_CLUSTER_NAME, obj.getTargetClusterName()); + entity.setAttribute(PROPERTY_RESULT_SUMMARY, obj.getResultSummary()); + + return entity; + } + + @Override + public AtlasEntity.AtlasEntityWithExtInfo toEntityWithExtInfo(ExportImportAuditEntry obj) throws AtlasBaseException { + return new AtlasEntity.AtlasEntityWithExtInfo(toEntity(obj)); + } + + @Override + public Map<String, Object> getUniqueAttributes(final ExportImportAuditEntry obj) { + return null; + } +} http://git-wip-us.apache.org/repos/asf/atlas/blob/8d926f21/repository/src/test/java/org/apache/atlas/repository/impexp/ExportImportAuditServiceTest.java ---------------------------------------------------------------------- diff --git a/repository/src/test/java/org/apache/atlas/repository/impexp/ExportImportAuditServiceTest.java b/repository/src/test/java/org/apache/atlas/repository/impexp/ExportImportAuditServiceTest.java new file mode 100644 index 0000000..f3803e5 --- /dev/null +++ b/repository/src/test/java/org/apache/atlas/repository/impexp/ExportImportAuditServiceTest.java @@ -0,0 +1,119 @@ +/** + * 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.impexp; + +import org.apache.atlas.TestModules; +import org.apache.atlas.exception.AtlasBaseException; +import org.apache.atlas.model.discovery.AtlasSearchResult; +import org.apache.atlas.model.impexp.ExportImportAuditEntry; +import org.apache.atlas.repository.store.graph.AtlasEntityStore; +import org.apache.atlas.store.AtlasTypeDefStore; +import org.apache.atlas.type.AtlasType; +import org.apache.atlas.type.AtlasTypeRegistry; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Guice; +import org.testng.annotations.Test; + +import javax.inject.Inject; +import java.io.IOException; + +import static org.apache.atlas.repository.impexp.ZipFileResourceTestUtils.loadBaseModel; +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertNotEquals; +import static org.testng.Assert.assertNotNull; + +@Guice(modules = TestModules.TestOnlyModule.class) +public class ExportImportAuditServiceTest { + @Inject + AtlasTypeRegistry typeRegistry; + + @Inject + private AtlasTypeDefStore typeDefStore; + + @Inject + ExportImportAuditService auditService; + + @BeforeClass + public void setup() throws IOException, AtlasBaseException { + loadBaseModel(typeDefStore, typeRegistry); + } + + @Test + public void checkTypeRegistered() throws AtlasBaseException { + AtlasType auditEntryType = typeRegistry.getType("__" + ExportImportAuditEntry.class.getSimpleName()); + assertNotNull(auditEntryType); + } + + @Test + public void saveLogEntry() throws AtlasBaseException, InterruptedException { + final String source1 = "clx"; + final String target1 = "cly"; + ExportImportAuditEntry entry = saveAndGet(source1, ExportImportAuditEntry.OPERATION_EXPORT, target1); + + String source2 = "clx2"; + String target2 = "clx1"; + ExportImportAuditEntry entry2 = saveAndGet(source2, ExportImportAuditEntry.OPERATION_EXPORT, target2); + + Thread.sleep(1000); + ExportImportAuditEntry actualEntry = retrieveEntry(entry); + ExportImportAuditEntry actualEntry2 = retrieveEntry(entry2); + + assertNotEquals(actualEntry.getGuid(), actualEntry2.getGuid()); + assertNotNull(actualEntry.getGuid()); + assertEquals(actualEntry.getSourceClusterName(), entry.getSourceClusterName()); + assertEquals(actualEntry.getTargetClusterName(), entry.getTargetClusterName()); + assertEquals(actualEntry.getOperation(), entry.getOperation()); + } + + @Test + public void numberOfSavedEntries_Retrieved() throws AtlasBaseException, InterruptedException { + final String source1 = "cluster1"; + final String target1 = "cly"; + int MAX_ENTRIES = 5; + + for (int i = 0; i < MAX_ENTRIES; i++) { + saveAndGet(source1, ExportImportAuditEntry.OPERATION_EXPORT, target1); + } + + Thread.sleep(1000); + AtlasSearchResult results = auditService.get(source1, ExportImportAuditEntry.OPERATION_EXPORT, "", "", "", "", 10, 0); + assertEquals(results.getEntities().size(), MAX_ENTRIES); + } + + + private ExportImportAuditEntry retrieveEntry(ExportImportAuditEntry entry) throws AtlasBaseException { + AtlasSearchResult result = auditService.get(entry.getUserName(), entry.getOperation(), entry.getSourceClusterName(), + entry.getTargetClusterName(), Long.toString(entry.getStartTime()), "", 10, 0); + assertNotNull(result); + assertEquals(result.getEntities().size(), 1); + entry.setGuid(result.getEntities().get(0).getGuid()); + return auditService.get(entry); + } + + private ExportImportAuditEntry saveAndGet(String sourceClusterName, String operation, String targetClusterName) throws AtlasBaseException { + ExportImportAuditEntry entry = new ExportImportAuditEntry(sourceClusterName, operation); + + entry.setTargetClusterName(targetClusterName); + entry.setUserName("default"); + entry.setStartTime(System.currentTimeMillis()); + entry.setEndTime(System.currentTimeMillis() + 1000L); + auditService.save(entry); + return entry; + } +} http://git-wip-us.apache.org/repos/asf/atlas/blob/8d926f21/webapp/src/main/java/org/apache/atlas/web/resources/AdminResource.java ---------------------------------------------------------------------- diff --git a/webapp/src/main/java/org/apache/atlas/web/resources/AdminResource.java b/webapp/src/main/java/org/apache/atlas/web/resources/AdminResource.java index 072dbb4..4224bb1 100755 --- a/webapp/src/main/java/org/apache/atlas/web/resources/AdminResource.java +++ b/webapp/src/main/java/org/apache/atlas/web/resources/AdminResource.java @@ -28,6 +28,7 @@ import org.apache.atlas.authorize.AtlasResourceTypes; import org.apache.atlas.authorize.simple.AtlasAuthorizationUtils; import org.apache.atlas.discovery.SearchContext; import org.apache.atlas.exception.AtlasBaseException; +import org.apache.atlas.model.discovery.AtlasSearchResult; import org.apache.atlas.model.impexp.AtlasExportRequest; import org.apache.atlas.model.impexp.AtlasExportResult; import org.apache.atlas.model.impexp.AtlasImportRequest; @@ -37,9 +38,11 @@ import org.apache.atlas.repository.impexp.ExportService; import org.apache.atlas.repository.impexp.ImportService; import org.apache.atlas.repository.impexp.ZipSink; import org.apache.atlas.repository.impexp.ZipSource; +import org.apache.atlas.repository.impexp.ExportImportAuditService; import org.apache.atlas.services.MetricsService; import org.apache.atlas.type.AtlasType; import org.apache.atlas.util.SearchTracker; +import org.apache.atlas.utils.AtlasPerfTracer; import org.apache.atlas.web.filters.AtlasCSRFPreventionFilter; import org.apache.atlas.web.service.ServiceState; import org.apache.atlas.web.util.Servlets; @@ -89,6 +92,7 @@ import java.util.concurrent.locks.ReentrantLock; @Service public class AdminResource { private static final Logger LOG = LoggerFactory.getLogger(AdminResource.class); + private static final Logger PERF_LOG = AtlasPerfTracer.getPerfLogger("AdminResource"); @Context private HttpServletRequest httpServletRequest; @@ -115,6 +119,7 @@ public class AdminResource { private final ExportService exportService; private final ImportService importService; private final SearchTracker activeSearches; + private ExportImportAuditService exportImportAuditService; static { try { @@ -126,12 +131,14 @@ public class AdminResource { @Inject public AdminResource(ServiceState serviceState, MetricsService metricsService, - ExportService exportService, ImportService importService, SearchTracker activeSearches) { + ExportService exportService, ImportService importService, SearchTracker activeSearches, + ExportImportAuditService exportImportAuditService) { this.serviceState = serviceState; this.metricsService = metricsService; this.exportService = exportService; this.importService = importService; this.activeSearches = activeSearches; + this.exportImportAuditService = exportImportAuditService; importExportOperationLock = new ReentrantLock(); } @@ -425,6 +432,31 @@ public class AdminResource { } @GET + @Path("/expimp/audit") + @Consumes(Servlets.JSON_MEDIA_TYPE) + @Produces(Servlets.JSON_MEDIA_TYPE) + public AtlasSearchResult getExportImportAudit(@QueryParam("sourceClusterName") String sourceCluster, + @QueryParam("targetCluster") String targetCluster, + @QueryParam("userName") String userName, + @QueryParam("operation") String operation, + @QueryParam("startTime") String startTime, + @QueryParam("endTime") String endTime, + @QueryParam("limit") int limit, + @QueryParam("offset") int offset) throws AtlasBaseException { + AtlasPerfTracer perf = null; + + try { + if (AtlasPerfTracer.isPerfTraceEnabled(PERF_LOG)) { + perf = AtlasPerfTracer.getPerfTracer(PERF_LOG, "getExportImportAudit(" + sourceCluster + ")"); + } + + return exportImportAuditService.get(userName, operation, sourceCluster, targetCluster, startTime, endTime, limit, offset); + } finally { + AtlasPerfTracer.log(perf); + } + } + + @GET @Path("activeSearches") @Produces(Servlets.JSON_MEDIA_TYPE) public Set<String> getActiveSearches() { http://git-wip-us.apache.org/repos/asf/atlas/blob/8d926f21/webapp/src/test/java/org/apache/atlas/web/resources/AdminResourceTest.java ---------------------------------------------------------------------- diff --git a/webapp/src/test/java/org/apache/atlas/web/resources/AdminResourceTest.java b/webapp/src/test/java/org/apache/atlas/web/resources/AdminResourceTest.java index c0bbf09..1fe3119 100644 --- a/webapp/src/test/java/org/apache/atlas/web/resources/AdminResourceTest.java +++ b/webapp/src/test/java/org/apache/atlas/web/resources/AdminResourceTest.java @@ -48,7 +48,7 @@ public class AdminResourceTest { when(serviceState.getState()).thenReturn(ServiceState.ServiceStateValue.ACTIVE); - AdminResource adminResource = new AdminResource(serviceState, null, null, null, null); + AdminResource adminResource = new AdminResource(serviceState, null, null, null, null, null); Response response = adminResource.getStatus(); assertEquals(response.getStatus(), HttpServletResponse.SC_OK); JSONObject entity = (JSONObject) response.getEntity(); @@ -59,7 +59,7 @@ public class AdminResourceTest { public void testResourceGetsValueFromServiceState() throws JSONException { when(serviceState.getState()).thenReturn(ServiceState.ServiceStateValue.PASSIVE); - AdminResource adminResource = new AdminResource(serviceState, null, null, null, null); + AdminResource adminResource = new AdminResource(serviceState, null, null, null, null, null); Response response = adminResource.getStatus(); verify(serviceState).getState();