/** * 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.notification; import com.google.inject.Inject; import org.apache.atlas.EntityAuditEvent; import org.apache.atlas.notification.hook.HookNotification; import org.apache.atlas.typesystem.Referenceable; import org.apache.atlas.typesystem.persistence.Id; import org.apache.atlas.web.resources.BaseResourceIT; import org.codehaus.jettison.json.JSONArray; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; import org.testng.annotations.Guice; import org.testng.annotations.Test; import java.util.List; import static org.testng.Assert.assertEquals; @Guice(modules = NotificationModule.class) public class NotificationHookConsumerIT extends BaseResourceIT { private static final String TEST_USER = "testuser"; public static final String NAME = "name"; public static final String DESCRIPTION = "description"; public static final String QUALIFIED_NAME = "qualifiedName"; public static final String CLUSTER_NAME = "clusterName"; @Inject private NotificationInterface kafka; @BeforeClass public void setUp() throws Exception { super.setUp(); createTypeDefinitionsV1(); } @AfterClass public void teardown() throws Exception { kafka.close(); } private void sendHookMessage(HookNotification.HookNotificationMessage message) throws NotificationException { kafka.send(NotificationInterface.NotificationType.HOOK, message); } @Test public void testMessageHandleFailureConsumerContinues() throws Exception { //send invalid message - update with invalid type sendHookMessage(new HookNotification.EntityPartialUpdateRequest(TEST_USER, randomString(), null, null, new Referenceable(randomString()))); //send valid message final Referenceable entity = new Referenceable(DATABASE_TYPE_BUILTIN); String dbName = "db" + randomString(); entity.set(NAME, dbName); entity.set(DESCRIPTION, randomString()); entity.set(QUALIFIED_NAME, dbName); entity.set(CLUSTER_NAME, randomString()); sendHookMessage(new HookNotification.EntityCreateRequest(TEST_USER, entity)); waitFor(MAX_WAIT_TIME, new Predicate() { @Override public boolean evaluate() throws Exception { JSONArray results = searchByDSL(String.format("%s where name='%s'", DATABASE_TYPE_BUILTIN, entity.get(NAME))); return results.length() == 1; } }); } @Test public void testCreateEntity() throws Exception { final Referenceable entity = new Referenceable(DATABASE_TYPE_BUILTIN); String dbName = "db" + randomString(); entity.set(NAME, dbName); entity.set(DESCRIPTION, randomString()); entity.set(QUALIFIED_NAME, dbName); entity.set(CLUSTER_NAME, randomString()); sendHookMessage(new HookNotification.EntityCreateRequest(TEST_USER, entity)); waitFor(MAX_WAIT_TIME, new Predicate() { @Override public boolean evaluate() throws Exception { JSONArray results = searchByDSL(String.format("%s where qualifiedName='%s'", DATABASE_TYPE_BUILTIN, entity.get(QUALIFIED_NAME))); return results.length() == 1; } }); //Assert that user passed in hook message is used in audit Referenceable instance = atlasClientV1.getEntity(DATABASE_TYPE_BUILTIN, QUALIFIED_NAME, (String) entity.get(QUALIFIED_NAME)); List<EntityAuditEvent> events = atlasClientV1.getEntityAuditEvents(instance.getId()._getId(), (short) 1); assertEquals(events.size(), 1); assertEquals(events.get(0).getUser(), TEST_USER); } @Test public void testUpdateEntityPartial() throws Exception { final Referenceable entity = new Referenceable(DATABASE_TYPE_BUILTIN); final String dbName = "db" + randomString(); entity.set(NAME, dbName); entity.set(DESCRIPTION, randomString()); entity.set(QUALIFIED_NAME, dbName); entity.set(CLUSTER_NAME, randomString()); atlasClientV1.createEntity(entity); final Referenceable newEntity = new Referenceable(DATABASE_TYPE_BUILTIN); newEntity.set("owner", randomString()); sendHookMessage( new HookNotification.EntityPartialUpdateRequest(TEST_USER, DATABASE_TYPE_BUILTIN, QUALIFIED_NAME, dbName, newEntity)); waitFor(MAX_WAIT_TIME, new Predicate() { @Override public boolean evaluate() throws Exception { Referenceable localEntity = atlasClientV1.getEntity(DATABASE_TYPE_BUILTIN, QUALIFIED_NAME, dbName); return (localEntity.get("owner") != null && localEntity.get("owner").equals(newEntity.get("owner"))); } }); //Its partial update and un-set fields are not updated Referenceable actualEntity = atlasClientV1.getEntity(DATABASE_TYPE_BUILTIN, QUALIFIED_NAME, dbName); assertEquals(actualEntity.get(DESCRIPTION), entity.get(DESCRIPTION)); } @Test public void testUpdatePartialUpdatingQualifiedName() throws Exception { final Referenceable entity = new Referenceable(DATABASE_TYPE_BUILTIN); final String dbName = "db" + randomString(); entity.set(NAME, dbName); entity.set(DESCRIPTION, randomString()); entity.set(QUALIFIED_NAME, dbName); entity.set(CLUSTER_NAME, randomString()); atlasClientV1.createEntity(entity); final Referenceable newEntity = new Referenceable(DATABASE_TYPE_BUILTIN); final String newName = "db" + randomString(); newEntity.set(QUALIFIED_NAME, newName); sendHookMessage( new HookNotification.EntityPartialUpdateRequest(TEST_USER, DATABASE_TYPE_BUILTIN, QUALIFIED_NAME, dbName, newEntity)); waitFor(MAX_WAIT_TIME, new Predicate() { @Override public boolean evaluate() throws Exception { JSONArray results = searchByDSL(String.format("%s where qualifiedName='%s'", DATABASE_TYPE_BUILTIN, newName)); return results.length() == 1; } }); //no entity with the old qualified name JSONArray results = searchByDSL(String.format("%s where qualifiedName='%s'", DATABASE_TYPE_BUILTIN, dbName)); assertEquals(results.length(), 0); } @Test public void testDeleteByQualifiedName() throws Exception { Referenceable entity = new Referenceable(DATABASE_TYPE_BUILTIN); final String dbName = "db" + randomString(); entity.set(NAME, dbName); entity.set(DESCRIPTION, randomString()); entity.set(QUALIFIED_NAME, dbName); entity.set(CLUSTER_NAME, randomString()); final String dbId = atlasClientV1.createEntity(entity).get(0); sendHookMessage( new HookNotification.EntityDeleteRequest(TEST_USER, DATABASE_TYPE_BUILTIN, QUALIFIED_NAME, dbName)); waitFor(MAX_WAIT_TIME, new Predicate() { @Override public boolean evaluate() throws Exception { Referenceable getEntity = atlasClientV1.getEntity(dbId); return getEntity.getId().getState() == Id.EntityState.DELETED; } }); } @Test public void testUpdateEntityFullUpdate() throws Exception { Referenceable entity = new Referenceable(DATABASE_TYPE_BUILTIN); final String dbName = "db" + randomString(); entity.set(NAME, dbName); entity.set(DESCRIPTION, randomString()); entity.set(QUALIFIED_NAME, dbName); entity.set(CLUSTER_NAME, randomString()); atlasClientV1.createEntity(entity); final Referenceable newEntity = new Referenceable(DATABASE_TYPE_BUILTIN); newEntity.set(NAME, randomString()); newEntity.set(DESCRIPTION, randomString()); newEntity.set("owner", randomString()); newEntity.set(QUALIFIED_NAME, dbName); newEntity.set(CLUSTER_NAME, randomString()); //updating unique attribute sendHookMessage(new HookNotification.EntityUpdateRequest(TEST_USER, newEntity)); waitFor(MAX_WAIT_TIME, new Predicate() { @Override public boolean evaluate() throws Exception { JSONArray results = searchByDSL(String.format("%s where qualifiedName='%s'", DATABASE_TYPE_BUILTIN, newEntity.get(QUALIFIED_NAME))); return results.length() == 1; } }); Referenceable actualEntity = atlasClientV1.getEntity(DATABASE_TYPE_BUILTIN, QUALIFIED_NAME, dbName); assertEquals(actualEntity.get(DESCRIPTION), newEntity.get(DESCRIPTION)); assertEquals(actualEntity.get("owner"), newEntity.get("owner")); } }