/* * Copyright © 2016 Cask Data, Inc. * * 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. */ package co.cask.cdap.internal.audit; import co.cask.cdap.WordCountApp; import co.cask.cdap.common.conf.Constants; import co.cask.cdap.common.guice.KafkaClientModule; import co.cask.cdap.common.guice.ZKClientModule; import co.cask.cdap.data2.audit.AuditModule; import co.cask.cdap.internal.AppFabricTestHelper; import co.cask.cdap.kafka.KafkaTester; import co.cask.cdap.proto.Id; import co.cask.cdap.proto.audit.AuditMessage; import co.cask.cdap.proto.audit.AuditType; import co.cask.cdap.proto.codec.AuditMessageTypeAdapter; import co.cask.cdap.proto.codec.EntityIdTypeAdapter; import co.cask.cdap.proto.element.EntityType; import co.cask.cdap.proto.id.ArtifactId; import co.cask.cdap.proto.id.EntityId; import co.cask.cdap.proto.id.Ids; import co.cask.cdap.proto.id.NamespaceId; import co.cask.cdap.proto.id.NamespacedId; import com.google.common.collect.HashMultimap; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Multimap; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.inject.AbstractModule; import com.google.inject.Injector; import com.google.inject.Module; import org.apache.twill.kafka.client.KafkaClientService; import org.apache.twill.zookeeper.ZKClientService; import org.junit.AfterClass; import org.junit.Assert; import org.junit.BeforeClass; import org.junit.ClassRule; import org.junit.Test; import java.util.Collections; import java.util.List; import java.util.Set; /** * Tests audit publishing. */ public class AuditPublishTest { @ClassRule public static final KafkaTester KAFKA_TESTER = new KafkaTester( ImmutableMap.of(Constants.Audit.ENABLED, "true"), Collections.<Module>emptyList(), 1); private static final Gson GSON = new GsonBuilder() .registerTypeAdapter(AuditMessage.class, new AuditMessageTypeAdapter()) .registerTypeAdapter(EntityId.class, new EntityIdTypeAdapter()) .create(); private static ZKClientService zkClient; private static KafkaClientService kafkaClient; @BeforeClass public static void init() throws Exception { Injector injector = AppFabricTestHelper.getInjector(KAFKA_TESTER.getCConf(), new AbstractModule() { @Override protected void configure() { install(new AuditModule().getDistributedModules()); install(new ZKClientModule()); install(new KafkaClientModule()); } }); zkClient = injector.getInstance(ZKClientService.class); zkClient.startAndWait(); kafkaClient = injector.getInstance(KafkaClientService.class); kafkaClient.startAndWait(); } @AfterClass public static void stop() throws Exception { zkClient.stopAndWait(); kafkaClient.startAndWait(); } @Test public void testPublish() throws Exception { String defaultNs = NamespaceId.DEFAULT.getNamespace(); String appName = WordCountApp.class.getSimpleName(); // Define expected values Set<? extends EntityId> expectedMetadataChangeEntities = ImmutableSet.of(Ids.namespace(defaultNs).artifact(WordCountApp.class.getSimpleName(), "1"), Ids.namespace(defaultNs).app(appName), Ids.namespace(defaultNs).app(appName).flow(WordCountApp.WordCountFlow.class.getSimpleName()), Ids.namespace(defaultNs).app(appName).mr(WordCountApp.VoidMapReduceJob.class.getSimpleName()), Ids.namespace(defaultNs).app(appName) .service(WordCountApp.WordFrequencyService.class.getSimpleName()), Ids.namespace(defaultNs).dataset("mydataset"), Ids.namespace(defaultNs).stream("text")); Multimap<AuditType, EntityId> expectedAuditEntities = HashMultimap.create(); expectedAuditEntities.putAll(AuditType.METADATA_CHANGE, expectedMetadataChangeEntities); expectedAuditEntities.putAll(AuditType.CREATE, ImmutableSet.of(Ids.namespace(defaultNs).dataset("mydataset"), Ids.namespace(defaultNs).stream("text"))); // Deploy application AppFabricTestHelper.deployApplication(Id.Namespace.DEFAULT, WordCountApp.class, null, KAFKA_TESTER.getCConf()); // Verify audit messages List<AuditMessage> publishedMessages = KAFKA_TESTER.getPublishedMessages(KAFKA_TESTER.getCConf().get(Constants.Audit.KAFKA_TOPIC), 11, AuditMessage.class, GSON); Multimap<AuditType, EntityId> actualAuditEntities = HashMultimap.create(); for (AuditMessage message : publishedMessages) { EntityId entityId = message.getEntityId(); if (entityId instanceof NamespacedId) { if (((NamespacedId) entityId).getNamespace().equals(NamespaceId.SYSTEM.getNamespace())) { // Ignore system audit messages continue; } } if (entityId.getEntity() == EntityType.ARTIFACT && entityId instanceof ArtifactId) { ArtifactId artifactId = (ArtifactId) entityId; // Version is dynamic for deploys in test cases entityId = Ids.namespace(artifactId.getNamespace()).artifact(artifactId.getArtifact(), "1"); } actualAuditEntities.put(message.getType(), entityId); } Assert.assertEquals(expectedAuditEntities, actualAuditEntities); } }