/* * Copyright © 2014-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.explore.service; import co.cask.cdap.api.common.Bytes; import co.cask.cdap.api.dataset.DatasetDefinition; import co.cask.cdap.api.dataset.DatasetProperties; import co.cask.cdap.common.conf.CConfiguration; import co.cask.cdap.common.conf.Constants; import co.cask.cdap.common.guice.ConfigModule; import co.cask.cdap.common.guice.DiscoveryRuntimeModule; import co.cask.cdap.common.guice.IOModule; import co.cask.cdap.common.guice.LocationRuntimeModule; import co.cask.cdap.data.runtime.DataFabricModules; import co.cask.cdap.data.runtime.DataSetServiceModules; import co.cask.cdap.data.runtime.DataSetsModules; import co.cask.cdap.data.stream.StreamAdminModules; import co.cask.cdap.data.view.ViewAdminModules; import co.cask.cdap.data2.datafabric.dataset.service.DatasetService; import co.cask.cdap.data2.datafabric.dataset.service.executor.DatasetOpExecutor; import co.cask.cdap.data2.dataset2.DatasetFramework; import co.cask.cdap.explore.client.DiscoveryExploreClient; import co.cask.cdap.explore.client.ExploreClient; import co.cask.cdap.explore.guice.ExploreClientModule; import co.cask.cdap.explore.guice.ExploreRuntimeModule; import co.cask.cdap.explore.service.datasets.KeyStructValueTableDefinition; import co.cask.cdap.explore.service.datasets.NotRecordScannableTableDefinition; import co.cask.cdap.metrics.guice.MetricsClientRuntimeModule; import co.cask.cdap.notifications.feeds.NotificationFeedManager; import co.cask.cdap.notifications.feeds.service.NoOpNotificationFeedManager; import co.cask.cdap.notifications.guice.NotificationServiceRuntimeModule; import co.cask.cdap.proto.Id; import co.cask.cdap.proto.NamespaceMeta; import co.cask.cdap.store.NamespaceStore; import co.cask.cdap.store.guice.NamespaceStoreModule; import co.cask.tephra.Transaction; import co.cask.tephra.TransactionManager; import com.google.common.collect.ImmutableList; import com.google.common.collect.Lists; import com.google.inject.AbstractModule; import com.google.inject.Guice; import com.google.inject.Injector; import com.google.inject.Module; import org.apache.hadoop.conf.Configuration; import org.junit.AfterClass; import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; import java.io.File; import java.util.List; /** * Test deployment behavior when explore module is disabled. */ public class ExploreDisabledTest { private static final Id.Namespace namespaceId = Id.Namespace.from("myspace"); private static TransactionManager transactionManager; private static DatasetFramework datasetFramework; private static DatasetOpExecutor dsOpExecutor; private static DatasetService datasetService; private static ExploreClient exploreClient; private static NamespaceStore namespaceStore; @BeforeClass public static void start() throws Exception { Injector injector = Guice.createInjector(createInMemoryModules(CConfiguration.create(), new Configuration())); transactionManager = injector.getInstance(TransactionManager.class); transactionManager.startAndWait(); dsOpExecutor = injector.getInstance(DatasetOpExecutor.class); dsOpExecutor.startAndWait(); datasetService = injector.getInstance(DatasetService.class); datasetService.startAndWait(); exploreClient = injector.getInstance(DiscoveryExploreClient.class); Assert.assertFalse(exploreClient.isServiceAvailable()); datasetFramework = injector.getInstance(DatasetFramework.class); namespaceStore = injector.getInstance(NamespaceStore.class); namespaceStore.create(new NamespaceMeta.Builder().setName(namespaceId).build()); // This happens when you create a namespace via REST APIs. However, since we do not start AppFabricServer in // Explore tests, simulating that scenario by explicitly calling DatasetFramework APIs. datasetFramework.createNamespace(namespaceId); } @AfterClass public static void stop() throws Exception { datasetFramework.deleteNamespace(namespaceId); namespaceStore.delete(namespaceId); exploreClient.close(); datasetService.stopAndWait(); dsOpExecutor.stopAndWait(); transactionManager.stopAndWait(); } @Test public void testDeployRecordScannable() throws Exception { // Try to deploy a dataset that is not record scannable, when explore is enabled. // This should be processed with no exception being thrown Id.DatasetModule module1 = Id.DatasetModule.from(namespaceId, "module1"); Id.DatasetInstance instance1 = Id.DatasetInstance.from(namespaceId, "table1"); datasetFramework.addModule(module1, new KeyStructValueTableDefinition.KeyStructValueTableModule()); // Performing admin operations to create dataset instance datasetFramework.addInstance("keyStructValueTable", instance1, DatasetProperties.EMPTY); Transaction tx1 = transactionManager.startShort(100); // Accessing dataset instance to perform data operations KeyStructValueTableDefinition.KeyStructValueTable table = datasetFramework.getDataset(instance1, DatasetDefinition.NO_ARGUMENTS, null); Assert.assertNotNull(table); table.startTx(tx1); KeyStructValueTableDefinition.KeyValue.Value value1 = new KeyStructValueTableDefinition.KeyValue.Value("first", Lists.newArrayList(1, 2, 3, 4, 5)); KeyStructValueTableDefinition.KeyValue.Value value2 = new KeyStructValueTableDefinition.KeyValue.Value("two", Lists.newArrayList(10, 11, 12, 13, 14)); table.put("1", value1); table.put("2", value2); Assert.assertEquals(value1, table.get("1")); Assert.assertTrue(table.commitTx()); transactionManager.canCommit(tx1, table.getTxChanges()); transactionManager.commit(tx1); table.postTxCommit(); Transaction tx2 = transactionManager.startShort(100); table.startTx(tx2); Assert.assertEquals(value1, table.get("1")); datasetFramework.deleteInstance(instance1); datasetFramework.deleteModule(module1); } @Test public void testDeployNotRecordScannable() throws Exception { // Try to deploy a dataset that is not record scannable, when explore is enabled. // This should be processed with no exceptionbeing thrown Id.DatasetModule module2 = Id.DatasetModule.from(namespaceId, "module2"); Id.DatasetInstance instance2 = Id.DatasetInstance.from(namespaceId, "table1"); datasetFramework.addModule(module2, new NotRecordScannableTableDefinition.NotRecordScannableTableModule()); // Performing admin operations to create dataset instance datasetFramework.addInstance("NotRecordScannableTableDef", instance2, DatasetProperties.EMPTY); Transaction tx1 = transactionManager.startShort(100); // Accessing dataset instance to perform data operations NotRecordScannableTableDefinition.KeyValueTable table = datasetFramework.getDataset(instance2, DatasetDefinition.NO_ARGUMENTS, null); Assert.assertNotNull(table); table.startTx(tx1); table.write("key1", "value1"); table.write("key2", "value2"); byte[] value = table.read("key1"); Assert.assertEquals("value1", Bytes.toString(value)); Assert.assertTrue(table.commitTx()); transactionManager.canCommit(tx1, table.getTxChanges()); transactionManager.commit(tx1); table.postTxCommit(); Transaction tx2 = transactionManager.startShort(100); table.startTx(tx2); value = table.read("key1"); Assert.assertNotNull(value); Assert.assertEquals("value1", Bytes.toString(value)); datasetFramework.deleteInstance(instance2); datasetFramework.deleteModule(module2); } private static List<Module> createInMemoryModules(CConfiguration configuration, Configuration hConf) { configuration.set(Constants.CFG_DATA_INMEMORY_PERSISTENCE, Constants.InMemoryPersistenceType.MEMORY.name()); configuration.setBoolean(Constants.Explore.EXPLORE_ENABLED, false); configuration.set(Constants.Explore.LOCAL_DATA_DIR, new File(System.getProperty("java.io.tmpdir"), "hive").getAbsolutePath()); return ImmutableList.of( new ConfigModule(configuration, hConf), new IOModule(), new DiscoveryRuntimeModule().getInMemoryModules(), new LocationRuntimeModule().getInMemoryModules(), new DataFabricModules().getInMemoryModules(), new DataSetsModules().getStandaloneModules(), new DataSetServiceModules().getInMemoryModules(), new MetricsClientRuntimeModule().getInMemoryModules(), new ExploreRuntimeModule().getInMemoryModules(), new ExploreClientModule(), new ViewAdminModules().getInMemoryModules(), new StreamAdminModules().getInMemoryModules(), new NotificationServiceRuntimeModule().getInMemoryModules(), new NamespaceStoreModule().getInMemoryModules(), new AbstractModule() { @Override protected void configure() { bind(NotificationFeedManager.class).to(NoOpNotificationFeedManager.class); } } ); } }