package org.apache.solr.cloud; /* * 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. */ import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.InputStream; import java.util.Collection; import java.util.List; import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; import org.apache.commons.io.filefilter.RegexFileFilter; import org.apache.commons.io.filefilter.TrueFileFilter; import org.apache.solr.SolrTestCaseJ4; import org.apache.solr.common.SolrException; import org.apache.solr.common.cloud.SolrZkClient; import org.apache.solr.common.cloud.ZkNodeProps; import org.apache.solr.common.cloud.ZkStateReader; import org.apache.solr.util.ExternalPaths; import org.apache.zookeeper.CreateMode; import org.apache.zookeeper.KeeperException; import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; // TODO: This test would be a lot faster if it used a solrhome with fewer config // files - there are a lot of them to upload public class ZkCLITest extends SolrTestCaseJ4 { protected static Logger log = LoggerFactory .getLogger(AbstractZkTestCase.class); private static final boolean VERBOSE = false; protected ZkTestServer zkServer; protected String zkDir; private String solrHome; private SolrZkClient zkClient; protected static final String SOLR_HOME = SolrTestCaseJ4.TEST_HOME(); @BeforeClass public static void beforeClass() { System.setProperty("solrcloud.skip.autorecovery", "true"); } @AfterClass public static void afterClass() throws InterruptedException { System.clearProperty("solrcloud.skip.autorecovery"); } @Override public void setUp() throws Exception { super.setUp(); log.info("####SETUP_START " + getTestName()); createTempDir(); boolean useNewSolrXml = random().nextBoolean(); if (useNewSolrXml) { solrHome = ExternalPaths.EXAMPLE_HOME; } else { File tmpSolrHome = new File(dataDir, "tmp-solr-home"); FileUtils.copyDirectory(new File(ExternalPaths.EXAMPLE_HOME), tmpSolrHome); FileUtils.copyFile(getFile("old-solr-example/solr.xml"), new File(tmpSolrHome, "solr.xml")); solrHome = tmpSolrHome.getAbsolutePath(); } zkDir = dataDir.getAbsolutePath() + File.separator + "zookeeper/server1/data"; log.info("ZooKeeper dataDir:" + zkDir); zkServer = new ZkTestServer(zkDir); zkServer.run(); System.setProperty("zkHost", zkServer.getZkAddress()); SolrZkClient zkClient = new SolrZkClient(zkServer.getZkHost(), AbstractZkTestCase.TIMEOUT); zkClient.makePath("/solr", false, true); zkClient.close(); this.zkClient = new SolrZkClient(zkServer.getZkAddress(), AbstractZkTestCase.TIMEOUT); log.info("####SETUP_END " + getTestName()); } @Test public void testBootstrap() throws Exception { // test bootstrap_conf String[] args = new String[] {"-zkhost", zkServer.getZkAddress(), "-cmd", "bootstrap", "-solrhome", this.solrHome}; ZkCLI.main(args); assertTrue(zkClient.exists(ZkController.CONFIGS_ZKNODE + "/collection1", true)); args = new String[] {"-zkhost", zkServer.getZkAddress(), "-cmd", "bootstrap", "-solrhome", ExternalPaths.EXAMPLE_MULTICORE_HOME}; ZkCLI.main(args); assertTrue(zkClient.exists(ZkController.CONFIGS_ZKNODE + "/core0", true)); assertTrue(zkClient.exists(ZkController.CONFIGS_ZKNODE + "/core1", true)); } @Test public void testBootstrapWithChroot() throws Exception { String chroot = "/foo/bar"; assertFalse(zkClient.exists(chroot, true)); String[] args = new String[] {"-zkhost", zkServer.getZkAddress() + chroot, "-cmd", "bootstrap", "-solrhome", this.solrHome}; ZkCLI.main(args); assertTrue(zkClient.exists(chroot + ZkController.CONFIGS_ZKNODE + "/collection1", true)); } @Test public void testMakePath() throws Exception { // test bootstrap_conf String[] args = new String[] {"-zkhost", zkServer.getZkAddress(), "-cmd", "makepath", "/path/mynewpath"}; ZkCLI.main(args); assertTrue(zkClient.exists("/path/mynewpath", true)); } @Test public void testPut() throws Exception { // test put String data = "my data"; String[] args = new String[] {"-zkhost", zkServer.getZkAddress(), "-cmd", "put", "/data.txt", data}; ZkCLI.main(args); zkClient.getData("/data.txt", null, null, true); assertArrayEquals(zkClient.getData("/data.txt", null, null, true), data.getBytes("UTF-8")); } @Test public void testPutFile() throws Exception { // test put file String[] args = new String[] {"-zkhost", zkServer.getZkAddress(), "-cmd", "putfile", "/solr.xml", SOLR_HOME + File.separator + "solr-stress-new.xml"}; ZkCLI.main(args); String fromZk = new String(zkClient.getData("/solr.xml", null, null, true), "UTF-8"); File locFile = new File(SOLR_HOME + File.separator + "solr-stress-new.xml"); InputStream is = new FileInputStream(locFile); String fromLoc; try { fromLoc = new String(IOUtils.toByteArray(is), "UTF-8"); } finally { IOUtils.closeQuietly(is); } assertEquals("Should get back what we put in ZK", fromZk, fromLoc); } @Test public void testPutFileNotExists() throws Exception { // test put file String[] args = new String[] {"-zkhost", zkServer.getZkAddress(), "-cmd", "putfile", "/solr.xml", SOLR_HOME + File.separator + "not-there.xml"}; try { ZkCLI.main(args); fail("Should have had a file not found exception"); } catch (FileNotFoundException fne) { String msg = fne.getMessage(); assertTrue("Didn't find expected error message containing 'not-there.xml' in " + msg, msg.indexOf("not-there.xml") != -1); } } @Test public void testList() throws Exception { zkClient.makePath("/test", true); String[] args = new String[] {"-zkhost", zkServer.getZkAddress(), "-cmd", "list"}; ZkCLI.main(args); } @Test public void testUpConfigLinkConfigClearZk() throws Exception { // test upconfig String confsetname = "confsetone"; String[] args = new String[] { "-zkhost", zkServer.getZkAddress(), "-cmd", "upconfig", "-confdir", ExternalPaths.EXAMPLE_HOME + File.separator + "collection1" + File.separator + "conf", "-confname", confsetname}; ZkCLI.main(args); assertTrue(zkClient.exists(ZkController.CONFIGS_ZKNODE + "/" + confsetname, true)); // print help // ZkCLI.main(new String[0]); // test linkconfig args = new String[] {"-zkhost", zkServer.getZkAddress(), "-cmd", "linkconfig", "-collection", "collection1", "-confname", confsetname}; ZkCLI.main(args); ZkNodeProps collectionProps = ZkNodeProps.load(zkClient.getData(ZkStateReader.COLLECTIONS_ZKNODE + "/collection1", null, null, true)); assertTrue(collectionProps.containsKey("configName")); assertEquals(confsetname, collectionProps.getStr("configName")); // test down config File confDir = new File(TEMP_DIR, "solrtest-confdropspot-" + this.getClass().getName() + "-" + System.currentTimeMillis()); assertFalse(confDir.exists()); args = new String[] {"-zkhost", zkServer.getZkAddress(), "-cmd", "downconfig", "-confdir", confDir.getAbsolutePath(), "-confname", confsetname}; ZkCLI.main(args); File[] files = confDir.listFiles(); List<String> zkFiles = zkClient.getChildren(ZkController.CONFIGS_ZKNODE + "/" + confsetname, null, true); assertEquals(files.length, zkFiles.size()); File sourceConfDir = new File(ExternalPaths.EXAMPLE_HOME + File.separator + "collection1" + File.separator + "conf"); // filter out all directories starting with . (e.g. .svn) Collection<File> sourceFiles = FileUtils.listFiles(sourceConfDir, TrueFileFilter.INSTANCE, new RegexFileFilter("[^\\.].*")); for (File sourceFile :sourceFiles){ int indexOfRelativePath = sourceFile.getAbsolutePath().lastIndexOf("collection1" + File.separator + "conf"); String relativePathofFile = sourceFile.getAbsolutePath().substring(indexOfRelativePath + 17, sourceFile.getAbsolutePath().length()); File downloadedFile = new File(confDir,relativePathofFile); assertTrue(downloadedFile.getAbsolutePath() + " does not exist source:" + sourceFile.getAbsolutePath(), downloadedFile.exists()); assertTrue("Content didn't change",FileUtils.contentEquals(sourceFile,downloadedFile)); } // test reset zk args = new String[] {"-zkhost", zkServer.getZkAddress(), "-cmd", "clear", "/"}; ZkCLI.main(args); assertEquals(0, zkClient.getChildren("/", null, true).size()); } @Test public void testGet() throws Exception { String getNode = "/getNode"; byte [] data = new String("getNode-data").getBytes("UTF-8"); this.zkClient.create(getNode, data, CreateMode.PERSISTENT, true); String[] args = new String[] {"-zkhost", zkServer.getZkAddress(), "-cmd", "get", getNode}; ZkCLI.main(args); } @Test public void testGetFile() throws Exception { String getNode = "/getFileNode"; byte [] data = new String("getFileNode-data").getBytes("UTF-8"); this.zkClient.create(getNode, data, CreateMode.PERSISTENT, true); File file = new File(TEMP_DIR, "solrtest-getfile-" + this.getClass().getName() + "-" + System.currentTimeMillis()); String[] args = new String[] {"-zkhost", zkServer.getZkAddress(), "-cmd", "getfile", getNode, file.getAbsolutePath()}; ZkCLI.main(args); byte [] readData = FileUtils.readFileToByteArray(file); assertArrayEquals(data, readData); } @Test public void testGetFileNotExists() throws Exception { String getNode = "/getFileNotExistsNode"; File file = new File(TEMP_DIR, "solrtest-getfilenotexists-" + this.getClass().getName() + "-" + System.currentTimeMillis()); String[] args = new String[] {"-zkhost", zkServer.getZkAddress(), "-cmd", "getfile", getNode, file.getAbsolutePath()}; try { ZkCLI.main(args); fail("Expected NoNodeException"); } catch (KeeperException.NoNodeException ex) { } } @Test(expected = SolrException.class) public void testInvalidZKAddress() throws SolrException{ SolrZkClient zkClient = new SolrZkClient("----------:33332", 100); zkClient.close(); } @Override public void tearDown() throws Exception { if (VERBOSE) { printLayout(zkServer.getZkHost()); } zkClient.close(); zkServer.shutdown(); super.tearDown(); } private void printLayout(String zkHost) throws Exception { SolrZkClient zkClient = new SolrZkClient(zkHost, AbstractZkTestCase.TIMEOUT); zkClient.printLayoutToStdOut(); zkClient.close(); } }