Repository: kylin Updated Branches: refs/heads/KYILN-2317 [created] 48eaa3642
KYLIN-2317 Add HybridCubeCLI Project: http://git-wip-us.apache.org/repos/asf/kylin/repo Commit: http://git-wip-us.apache.org/repos/asf/kylin/commit/48eaa364 Tree: http://git-wip-us.apache.org/repos/asf/kylin/tree/48eaa364 Diff: http://git-wip-us.apache.org/repos/asf/kylin/diff/48eaa364 Branch: refs/heads/KYILN-2317 Commit: 48eaa3642a7ca5771c3d8b7278682c501091ef41 Parents: 74c2d6b Author: Billy Liu <[email protected]> Authored: Tue Dec 27 18:03:06 2016 +0800 Committer: Billy Liu <[email protected]> Committed: Tue Dec 27 18:03:06 2016 +0800 ---------------------------------------------------------------------- .../localmeta/cube/ssb_cube1.json | 14 ++ .../localmeta/cube/ssb_cube2.json | 14 ++ .../localmeta/cube_desc/ssb_cube1.json | 155 +++++++++++++++++ .../localmeta/cube_desc/ssb_cube2.json | 155 +++++++++++++++++ .../org/apache/kylin/tool/HybridCubeCLI.java | 165 +++++++++++++++++++ .../apache/kylin/tool/HybridCubeCLITest.java | 82 +++++++++ 6 files changed, 585 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/kylin/blob/48eaa364/examples/test_case_data/localmeta/cube/ssb_cube1.json ---------------------------------------------------------------------- diff --git a/examples/test_case_data/localmeta/cube/ssb_cube1.json b/examples/test_case_data/localmeta/cube/ssb_cube1.json new file mode 100644 index 0000000..b1eb2a5 --- /dev/null +++ b/examples/test_case_data/localmeta/cube/ssb_cube1.json @@ -0,0 +1,14 @@ +{ + "uuid" : "70a9f288-3c01-4745-a04b-5641e82d6c70", + "name" : "ssb_cube1", + "owner" : "ADMIN", + "cost" : 50, + "status" : "DISABLED", + "segments" : [ ], + "last_modified" : 1457534216410, + "descriptor" : "ssb_cube1", + "create_time_utc" : 1457444500888, + "size_kb" : 0, + "input_records_count" : 0, + "input_records_size" : 0 +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/kylin/blob/48eaa364/examples/test_case_data/localmeta/cube/ssb_cube2.json ---------------------------------------------------------------------- diff --git a/examples/test_case_data/localmeta/cube/ssb_cube2.json b/examples/test_case_data/localmeta/cube/ssb_cube2.json new file mode 100644 index 0000000..58f935d --- /dev/null +++ b/examples/test_case_data/localmeta/cube/ssb_cube2.json @@ -0,0 +1,14 @@ +{ + "uuid" : "70a9f288-3c01-4745-a04b-5641e82d6c71", + "name" : "ssb_cube2", + "owner" : "ADMIN", + "cost" : 50, + "status" : "DISABLED", + "segments" : [ ], + "last_modified" : 1457534216410, + "descriptor" : "ssb_cube2", + "create_time_utc" : 1457444500888, + "size_kb" : 0, + "input_records_count" : 0, + "input_records_size" : 0 +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/kylin/blob/48eaa364/examples/test_case_data/localmeta/cube_desc/ssb_cube1.json ---------------------------------------------------------------------- diff --git a/examples/test_case_data/localmeta/cube_desc/ssb_cube1.json b/examples/test_case_data/localmeta/cube_desc/ssb_cube1.json new file mode 100644 index 0000000..5986057 --- /dev/null +++ b/examples/test_case_data/localmeta/cube_desc/ssb_cube1.json @@ -0,0 +1,155 @@ +{ + "uuid" : "5c44df30-daec-486e-af90-927bf7851058", + "name" : "ssb_cube1", + "description" : "", + "dimensions" : [ { + "name" : "SSB.PART_DERIVED", + "table" : "SSB.PART", + "column" : null, + "derived" : [ "P_MFGR", "P_CATEGORY", "P_BRAND" ] + }, { + "name" : "C_CITY", + "table" : "SSB.CUSTOMER", + "column" : "C_CITY", + "derived" : null + }, { + "name" : "C_REGION", + "table" : "SSB.CUSTOMER", + "column" : "C_REGION", + "derived" : null + }, { + "name" : "C_NATION", + "table" : "SSB.CUSTOMER", + "column" : "C_NATION", + "derived" : null + }, { + "name" : "D_YEAR", + "table" : "SSB.DATES", + "column" : "D_YEAR", + "derived" : null + }, { + "name" : "D_YEARMONTH", + "table" : "SSB.DATES", + "column" : "D_YEARMONTH", + "derived" : null + }, { + "name" : "D_YEARMONTHNUM", + "table" : "SSB.DATES", + "column" : "D_YEARMONTHNUM", + "derived" : null + }, { + "name" : "D_WEEKNUMINYEAR", + "table" : "SSB.DATES", + "column" : "D_WEEKNUMINYEAR", + "derived" : null + } ], + "measures" : [ { + "name" : "_COUNT_", + "function" : { + "expression" : "COUNT", + "parameter" : { + "type" : "constant", + "value" : "1", + "next_parameter" : null + }, + "returntype" : "bigint" + }, + "dependent_measure_ref" : null + }, { + "name" : "TOTAL_REVENUE", + "function" : { + "expression" : "SUM", + "parameter" : { + "type" : "column", + "value" : "LO_REVENUE", + "next_parameter" : null + }, + "returntype" : "bigint" + }, + "dependent_measure_ref" : null + }, { + "name" : "TOTAL_SUPPLYCOST", + "function" : { + "expression" : "SUM", + "parameter" : { + "type" : "column", + "value" : "LO_SUPPLYCOST", + "next_parameter" : null + }, + "returntype" : "bigint" + }, + "dependent_measure_ref" : null + }, { + "name" : "TOTAL_V_REVENUE", + "function" : { + "expression" : "SUM", + "parameter" : { + "type" : "column", + "value" : "V_REVENUE", + "next_parameter" : null + }, + "returntype" : "bigint" + }, + "dependent_measure_ref" : null + } ], + "rowkey" : { + "rowkey_columns" : [ { + "column" : "LO_PARTKEY", + "encoding" : "dict" + }, { + "column" : "C_CITY", + "encoding" : "dict" + }, { + "column" : "C_REGION", + "encoding" : "dict" + }, { + "column" : "C_NATION", + "encoding" : "dict" + }, { + "column" : "D_YEAR", + "encoding" : "dict" + }, { + "column" : "D_YEARMONTH", + "encoding" : "dict" + }, { + "column" : "D_YEARMONTHNUM", + "encoding" : "dict" + }, { + "column" : "D_WEEKNUMINYEAR", + "encoding" : "dict" + } ] + }, + "signature" : "", + "last_modified" : 1457503036686, + "model_name" : "ssb", + "null_string" : null, + "hbase_mapping" : { + "column_family" : [ { + "name" : "F1", + "columns" : [ { + "qualifier" : "M", + "measure_refs" : [ "_COUNT_", "TOTAL_REVENUE", "TOTAL_SUPPLYCOST", "TOTAL_V_REVENUE" ] + } ] + } ] + }, + "aggregation_groups" : [ { + "includes" : [ "LO_PARTKEY", "C_CITY", "C_REGION", "C_NATION", "D_YEAR", "D_YEARMONTH", "D_YEARMONTHNUM", "D_WEEKNUMINYEAR" ], + "select_rule" : { + "hierarchy_dims" : [ [ "C_REGION", "C_NATION", "C_CITY" ], [ "D_YEARMONTH", "D_YEARMONTHNUM", "D_WEEKNUMINYEAR" ] ], + "mandatory_dims" : [ "D_YEAR" ], + "joint_dims" : [ ] + } + } ], + "notify_list" : [ ], + "status_need_notify" : [ ], + "partition_date_start" : 694224000000, + "partition_date_end" : 3153000000000, + "auto_merge_time_ranges" : [ 604800000, 2419200000 ], + "retention_range" : 0, + "engine_type" : 2, + "storage_type" : 2, + "override_kylin_properties" : { + "kylin.hbase.default.compression.codec" : "lz4", + "kylin.cube.aggrgroup.isMandatoryOnlyValid" : "true" + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/kylin/blob/48eaa364/examples/test_case_data/localmeta/cube_desc/ssb_cube2.json ---------------------------------------------------------------------- diff --git a/examples/test_case_data/localmeta/cube_desc/ssb_cube2.json b/examples/test_case_data/localmeta/cube_desc/ssb_cube2.json new file mode 100644 index 0000000..fc75ea8 --- /dev/null +++ b/examples/test_case_data/localmeta/cube_desc/ssb_cube2.json @@ -0,0 +1,155 @@ +{ + "uuid" : "5c44df30-daec-486e-af90-927bf7851059", + "name" : "ssb_cube2", + "description" : "", + "dimensions" : [ { + "name" : "SSB.PART_DERIVED", + "table" : "SSB.PART", + "column" : null, + "derived" : [ "P_MFGR", "P_CATEGORY", "P_BRAND" ] + }, { + "name" : "S_CITY", + "table" : "SSB.SUPPLIER", + "column" : "S_CITY", + "derived" : null + }, { + "name" : "S_REGION", + "table" : "SSB.SUPPLIER", + "column" : "S_REGION", + "derived" : null + }, { + "name" : "S_NATION", + "table" : "SSB.SUPPLIER", + "column" : "S_NATION", + "derived" : null + }, { + "name" : "D_YEAR", + "table" : "SSB.DATES", + "column" : "D_YEAR", + "derived" : null + }, { + "name" : "D_YEARMONTH", + "table" : "SSB.DATES", + "column" : "D_YEARMONTH", + "derived" : null + }, { + "name" : "D_YEARMONTHNUM", + "table" : "SSB.DATES", + "column" : "D_YEARMONTHNUM", + "derived" : null + }, { + "name" : "D_WEEKNUMINYEAR", + "table" : "SSB.DATES", + "column" : "D_WEEKNUMINYEAR", + "derived" : null + } ], + "measures" : [ { + "name" : "_COUNT_", + "function" : { + "expression" : "COUNT", + "parameter" : { + "type" : "constant", + "value" : "1", + "next_parameter" : null + }, + "returntype" : "bigint" + }, + "dependent_measure_ref" : null + }, { + "name" : "TOTAL_REVENUE", + "function" : { + "expression" : "SUM", + "parameter" : { + "type" : "column", + "value" : "LO_REVENUE", + "next_parameter" : null + }, + "returntype" : "bigint" + }, + "dependent_measure_ref" : null + }, { + "name" : "TOTAL_SUPPLYCOST", + "function" : { + "expression" : "SUM", + "parameter" : { + "type" : "column", + "value" : "LO_SUPPLYCOST", + "next_parameter" : null + }, + "returntype" : "bigint" + }, + "dependent_measure_ref" : null + }, { + "name" : "TOTAL_V_REVENUE", + "function" : { + "expression" : "SUM", + "parameter" : { + "type" : "column", + "value" : "V_REVENUE", + "next_parameter" : null + }, + "returntype" : "bigint" + }, + "dependent_measure_ref" : null + } ], + "rowkey" : { + "rowkey_columns" : [ { + "column" : "LO_PARTKEY", + "encoding" : "dict" + }, { + "column" : "S_CITY", + "encoding" : "dict" + }, { + "column" : "S_REGION", + "encoding" : "dict" + }, { + "column" : "S_NATION", + "encoding" : "dict" + }, { + "column" : "D_YEAR", + "encoding" : "dict" + }, { + "column" : "D_YEARMONTH", + "encoding" : "dict" + }, { + "column" : "D_YEARMONTHNUM", + "encoding" : "dict" + }, { + "column" : "D_WEEKNUMINYEAR", + "encoding" : "dict" + } ] + }, + "signature" : "", + "last_modified" : 1457503036686, + "model_name" : "ssb", + "null_string" : null, + "hbase_mapping" : { + "column_family" : [ { + "name" : "F1", + "columns" : [ { + "qualifier" : "M", + "measure_refs" : [ "_COUNT_", "TOTAL_REVENUE", "TOTAL_SUPPLYCOST", "TOTAL_V_REVENUE" ] + } ] + } ] + }, + "aggregation_groups" : [ { + "includes" : [ "LO_PARTKEY", "S_CITY", "S_REGION", "S_NATION", "D_YEAR", "D_YEARMONTH", "D_YEARMONTHNUM", "D_WEEKNUMINYEAR" ], + "select_rule" : { + "hierarchy_dims" : [ [ "S_REGION", "S_NATION", "S_CITY" ], [ "D_YEARMONTH", "D_YEARMONTHNUM", "D_WEEKNUMINYEAR" ] ], + "mandatory_dims" : [ "D_YEAR" ], + "joint_dims" : [ ] + } + } ], + "notify_list" : [ ], + "status_need_notify" : [ ], + "partition_date_start" : 3153000000000, + "partition_date_end" : 3153600000000, + "auto_merge_time_ranges" : [ 604800000, 2419200000 ], + "retention_range" : 0, + "engine_type" : 2, + "storage_type" : 2, + "override_kylin_properties" : { + "kylin.hbase.default.compression.codec" : "lz4", + "kylin.cube.aggrgroup.isMandatoryOnlyValid" : "true" + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/kylin/blob/48eaa364/tool/src/main/java/org/apache/kylin/tool/HybridCubeCLI.java ---------------------------------------------------------------------- diff --git a/tool/src/main/java/org/apache/kylin/tool/HybridCubeCLI.java b/tool/src/main/java/org/apache/kylin/tool/HybridCubeCLI.java new file mode 100644 index 0000000..1e2ecb9 --- /dev/null +++ b/tool/src/main/java/org/apache/kylin/tool/HybridCubeCLI.java @@ -0,0 +1,165 @@ +/* + * 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.kylin.tool; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import org.apache.commons.cli.Option; +import org.apache.commons.cli.OptionBuilder; +import org.apache.commons.cli.Options; +import org.apache.commons.lang3.StringUtils; +import org.apache.kylin.common.KylinConfig; +import org.apache.kylin.common.persistence.ResourceStore; +import org.apache.kylin.common.util.AbstractApplication; +import org.apache.kylin.common.util.OptionsHelper; +import org.apache.kylin.cube.CubeInstance; +import org.apache.kylin.cube.CubeManager; +import org.apache.kylin.metadata.MetadataManager; +import org.apache.kylin.metadata.cachesync.Broadcaster; +import org.apache.kylin.metadata.model.DataModelDesc; +import org.apache.kylin.metadata.project.ProjectManager; +import org.apache.kylin.metadata.project.RealizationEntry; +import org.apache.kylin.metadata.realization.RealizationType; +import org.apache.kylin.storage.hybrid.HybridInstance; +import org.apache.kylin.storage.hybrid.HybridManager; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class HybridCubeCLI extends AbstractApplication { + + private static final Logger logger = LoggerFactory.getLogger(HybridCubeCLI.class); + + private static final Option OPTION_HYBRID_NAME = OptionBuilder.withArgName("name").hasArg().isRequired(true).withDescription("HybridCube name").create("name"); + + private static final Option OPTION_PROJECT = OptionBuilder.withArgName("project").hasArg().isRequired(true).withDescription("the target project for the hybrid cube").create("project"); + + private static final Option OPTION_MODEL = OptionBuilder.withArgName("model").hasArg().isRequired(true).withDescription("the target model for the hybrid cube").create("model"); + + private static final Option OPTION_CUBES = OptionBuilder.withArgName("cubes").hasArg().isRequired(true).withDescription("the cubes used in HybridCube, seperated by comma, empty if to delete HybridCube").create("cubes"); + + private final Options options; + + private KylinConfig kylinConfig; + private CubeManager cubeManager; + private HybridManager hybridManager; + private MetadataManager metadataManager; + private ResourceStore store; + + public HybridCubeCLI() { + options = new Options(); + options.addOption(OPTION_HYBRID_NAME); + options.addOption(OPTION_PROJECT); + options.addOption(OPTION_MODEL); + options.addOption(OPTION_CUBES); + + this.kylinConfig = KylinConfig.getInstanceFromEnv(); + this.store = ResourceStore.getStore(kylinConfig); + this.cubeManager = CubeManager.getInstance(kylinConfig); + this.hybridManager = HybridManager.getInstance(kylinConfig); + this.metadataManager = MetadataManager.getInstance(kylinConfig); + } + + public static void main(String[] args) { + HybridCubeCLI cli = new HybridCubeCLI(); + cli.execute(args); + } + + @Override + protected Options getOptions() { + return options; + } + + @Override + protected void execute(OptionsHelper optionsHelper) throws Exception { + String hybridName = optionsHelper.getOptionValue(OPTION_HYBRID_NAME); + String projectName = optionsHelper.getOptionValue(OPTION_PROJECT); + String modelName = optionsHelper.getOptionValue(OPTION_MODEL); + String[] cubeNames = optionsHelper.getOptionValue(OPTION_CUBES).split(","); + String owner = null; + + DataModelDesc modelDesc = metadataManager.getDataModelDesc(modelName); + if (modelDesc == null) { + throw new RuntimeException("Could not find model: " + modelName); + } + + List<RealizationEntry> realizationEntries = new ArrayList<RealizationEntry>(); + for (String cubeName : cubeNames) { + if (StringUtils.isEmpty(cubeName)) + continue; + CubeInstance cube = cubeManager.getCube(cubeName); + if (cube == null) { + throw new RuntimeException("Could not find cube: " + cubeName); + } + if (owner == null) { + owner = cube.getOwner(); + } + realizationEntries.add(RealizationEntry.create(RealizationType.CUBE, cube.getName())); + } + + HybridInstance hybridInstance = hybridManager.getHybridInstance(hybridName); + if (hybridInstance == null) { + //Create new Hybrid + create(hybridName, realizationEntries, projectName, owner); + } else if (realizationEntries.size() == 0) { + // Delete the Hybrid + delete(hybridInstance); + } else { + // Update the Hybrid + update(hybridInstance, realizationEntries, projectName, owner); + } + + verify(); + } + + private HybridInstance create(String hybridName, List<RealizationEntry> realizationEntries, String projectName, String owner) throws IOException { + HybridInstance hybridInstance = HybridInstance.create(kylinConfig, hybridName, realizationEntries); + store.putResource(hybridInstance.getResourcePath(), hybridInstance, HybridManager.HYBRID_SERIALIZER); + ProjectManager.getInstance(kylinConfig).moveRealizationToProject(RealizationType.HYBRID, hybridInstance.getName(), projectName, owner); + hybridManager.reloadHybridInstance(hybridName); + logger.info("HybridInstance was created at: " + hybridInstance.getResourcePath()); + return hybridInstance; + } + + private void update(HybridInstance hybridInstance, List<RealizationEntry> realizationEntries, String projectName, String owner) throws IOException { + hybridInstance.setRealizationEntries(realizationEntries); + store.putResource(hybridInstance.getResourcePath(), hybridInstance, HybridManager.HYBRID_SERIALIZER); + ProjectManager.getInstance(kylinConfig).moveRealizationToProject(RealizationType.HYBRID, hybridInstance.getName(), projectName, owner); + logger.info("HybridInstance was updated at: " + hybridInstance.getResourcePath()); + } + + private void delete(HybridInstance hybridInstance) throws IOException { + ProjectManager.getInstance(kylinConfig).removeRealizationsFromProjects(RealizationType.HYBRID, hybridInstance.getName()); + store.deleteResource(hybridInstance.getResourcePath()); + Broadcaster.getInstance(KylinConfig.getInstanceFromEnv()).notifyListener("hybrid", Broadcaster.Event.DROP, hybridInstance.getName()); + logger.info("HybridInstance was deleted at: " + hybridInstance.getResourcePath()); + } + + private void verify() { + CubeManager.clearCache(); + CubeManager.getInstance(kylinConfig); + + ProjectManager.clearCache(); + ProjectManager.getInstance(kylinConfig); + + HybridManager.clearCache(); + HybridManager.getInstance(kylinConfig); + } +} http://git-wip-us.apache.org/repos/asf/kylin/blob/48eaa364/tool/src/test/java/org/apache/kylin/tool/HybridCubeCLITest.java ---------------------------------------------------------------------- diff --git a/tool/src/test/java/org/apache/kylin/tool/HybridCubeCLITest.java b/tool/src/test/java/org/apache/kylin/tool/HybridCubeCLITest.java new file mode 100644 index 0000000..7d73b64 --- /dev/null +++ b/tool/src/test/java/org/apache/kylin/tool/HybridCubeCLITest.java @@ -0,0 +1,82 @@ +/* + * 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.kylin.tool; + +import java.io.IOException; + +import org.apache.kylin.common.KylinConfig; +import org.apache.kylin.common.util.LocalFileMetadataTestCase; +import org.apache.kylin.metadata.project.ProjectManager; +import org.apache.kylin.metadata.realization.RealizationType; +import org.apache.kylin.storage.hybrid.HybridInstance; +import org.apache.kylin.storage.hybrid.HybridManager; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +public class HybridCubeCLITest extends LocalFileMetadataTestCase { + + @Before + public void setUp() throws Exception { + this.createTestMetadata(); + } + + @After + public void after() throws Exception { + this.cleanupTestMetadata(); + } + + @Test + public void testCreate() { + HybridManager hybridManager = HybridManager.getInstance(KylinConfig.getInstanceFromEnv()); + Assert.assertNull(hybridManager.getHybridInstance("ssb_hybrid")); + HybridCubeCLI.main(new String[] { "-name", "ssb_hybrid", "-project", "default", "-model", "ssb", "-cubes", "ssb_cube1,ssb_cube2" }); + + HybridInstance hybridInstance = hybridManager.getHybridInstance("ssb_hybrid"); + Assert.assertNotNull(hybridInstance); + Assert.assertEquals("ssb_hybrid", hybridInstance.getName()); + Assert.assertEquals(2, hybridInstance.getRealizationEntries().size()); + } + + @Test + public void testUpdate() { + HybridManager hybridManager = HybridManager.getInstance(KylinConfig.getInstanceFromEnv()); + Assert.assertNotNull(hybridManager.getHybridInstance("test_kylin_hybrid_ready")); + HybridCubeCLI.main(new String[] { "-name", "test_kylin_hybrid_ready", "-project", "default", "-model", "test_kylin_inner_join_model_desc", "-cubes", "ssb_cube1" }); + + HybridInstance hybridInstance = hybridManager.getHybridInstance("test_kylin_hybrid_ready"); + Assert.assertNotNull(hybridInstance); + Assert.assertEquals("test_kylin_hybrid_ready", hybridInstance.getName()); + Assert.assertEquals(1, hybridInstance.getRealizationEntries().size()); + } + + @Test + public void testDelete() throws IOException { + HybridManager hybridManager = HybridManager.getInstance(KylinConfig.getInstanceFromEnv()); + Assert.assertNotNull(hybridManager.getHybridInstance("test_kylin_hybrid_ready")); + HybridCubeCLI.main(new String[] { "-name", "test_kylin_hybrid_ready", "-project", "default", "-model", "test_kylin_inner_join_model_desc", "-cubes", "" }); + + HybridInstance hybridInstance = hybridManager.getHybridInstance("test_kylin_hybrid_ready"); + Assert.assertNull(hybridInstance); + + Assert.assertEquals(0, ProjectManager.getInstance(KylinConfig.getInstanceFromEnv()).findProjects(RealizationType.HYBRID, "test_kylin_hybrid_ready").size()); + } + +}
