blob: c8db819c3adbdc5a6e3f5a92b48ee182f0bc9555 [file] [log] [blame]
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.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.nio.charset.StandardCharsets;
import org.apache.commons.io.FileUtils;
import org.apache.solr.SolrTestCaseJ4;
import org.apache.solr.common.SolrException;
import org.apache.solr.common.cloud.SolrZkClient;
import org.apache.solr.common.cloud.ZkStateReader;
import org.apache.solr.core.ConfigSolr;
import org.apache.solr.core.SolrResourceLoader;
import org.apache.solr.servlet.SolrDispatchFilter;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.RuleChain;
import org.junit.rules.TestRule;
import com.carrotsearch.randomizedtesting.rules.SystemPropertiesRestoreRule;
public class SolrXmlInZkTest extends SolrTestCaseJ4 {
@Rule
public TestRule solrTestRules = RuleChain.outerRule(new SystemPropertiesRestoreRule());
protected ZkTestServer zkServer;
protected String zkDir;
private SolrZkClient zkClient;
private ZkStateReader reader;
private ConfigSolr cfg;
@Before
public void beforeClass() {
System.setProperty("solr.solrxml.location", "zookeeper");
}
private void setUpZkAndDiskXml(boolean toZk, boolean leaveOnLocal) throws Exception {
File tmpDir = createTempDir();
File solrHome = new File(tmpDir, "home");
copyMinConf(new File(solrHome, "myCollect"));
if (leaveOnLocal) {
FileUtils.copyFile(new File(SolrTestCaseJ4.TEST_HOME(), "solr-stress-new.xml"), new File(solrHome, "solr.xml"));
}
System.setProperty("solr.solr.home", solrHome.getAbsolutePath());
ignoreException("No UpdateLog found - cannot sync");
ignoreException("No UpdateLog found - cannot recover");
System.setProperty("zkClientTimeout", "8000");
zkDir = tmpDir.getAbsolutePath() + File.separator
+ "zookeeper" + System.currentTimeMillis() + "/server1/data";
zkServer = new ZkTestServer(zkDir);
zkServer.run();
System.setProperty("zkHost", zkServer.getZkAddress());
AbstractZkTestCase.buildZooKeeper(zkServer.getZkHost(),
zkServer.getZkAddress(), "solrconfig.xml", "schema.xml");
zkClient = new SolrZkClient(zkServer.getZkAddress(), AbstractZkTestCase.TIMEOUT);
if (toZk) {
zkClient.makePath("solr.xml", XML_FOR_ZK.getBytes(StandardCharsets.UTF_8), true);
}
zkClient.close();
log.info("####SETUP_START " + getTestName());
// set some system properties for use by tests
System.setProperty("solr.test.sys.prop1", "propone");
System.setProperty("solr.test.sys.prop2", "proptwo");
Method method = SolrDispatchFilter.class.getDeclaredMethod("loadConfigSolr", SolrResourceLoader.class);
method.setAccessible(true);
Object obj = method.invoke(new SolrDispatchFilter(), new SolrResourceLoader(null));
cfg = (ConfigSolr) obj;
log.info("####SETUP_END " + getTestName());
}
private void closeZK() throws Exception {
if (zkClient != null) {
zkClient.close();
}
if (reader != null) {
reader.close();
}
zkServer.shutdown();
}
@Test
public void testXmlOnBoth() throws Exception {
try {
setUpZkAndDiskXml(true, true);
assertEquals("Should have gotten a new port the xml file sent to ZK, overrides the copy on disk",
cfg.getZkHostPort(), "9045");
} finally {
closeZK();
}
}
@Test
public void testXmlInZkOnly() throws Exception {
try {
setUpZkAndDiskXml(true, false);
assertEquals("Should have gotten a new port the xml file sent to ZK",
cfg.getZkHostPort(), "9045");
} finally {
closeZK();
}
}
@Test
public void testNotInZkAndShouldBe() throws Exception {
try {
setUpZkAndDiskXml(false, true);
fail("Should have gotten an exception here!");
} catch (InvocationTargetException ite) {
assertEquals("Should have an exception here, file not in ZK.",
"Could not load solr.xml from zookeeper", ite.getTargetException().getMessage());
} finally {
closeZK();
}
}
@Test
public void testNotInZkOrOnDisk() throws Exception {
try {
System.clearProperty("solr.solrxml.location");
System.setProperty("hostPort", "8787");
setUpZkAndDiskXml(false, false); // solr.xml not on disk either
fail("Should have thrown an exception here");
} catch (InvocationTargetException ite) {
assertTrue("Should be failing to create default solr.xml in code",
ite.getCause().getMessage().contains("solr.xml does not exist"));
} finally {
closeZK();
}
}
//TODO: Remove for 5.x, this should fail when we don't have a real solr.xml file after we take out the remove
// the hard-coded default from ConifgSolrXmlOld
@Test
public void testHardCodedSolrXml() throws IOException {
SolrResourceLoader loader = null;
final File solrHome = createTempDir("testHardCodedSolrXml");
try {
loader = new SolrResourceLoader(solrHome.getAbsolutePath());
ConfigSolr.fromSolrHome(loader, solrHome.getAbsolutePath());
} catch (Exception e) {
fail("Should NOT have thrown any exception here, solr.xml should have been received from the hard-coded string");
} finally {
loader.close();
}
}
@Test
public void testOnDiskOnly() throws Exception {
try {
System.clearProperty("solr.solrxml.location");
setUpZkAndDiskXml(false, true);
assertEquals("Should have gotten the default port", cfg.getZkHostPort(), "8983");
} finally {
closeZK();
}
}
@Test
public void testBadSysProp() throws Exception {
try {
System.setProperty("solr.solrxml.location", "solrHomeDir");
setUpZkAndDiskXml(false, true);
fail("Should have thrown exception in SolrXmlInZkTest.testBadSysProp");
} catch (InvocationTargetException ite) {
assertEquals("Should have an exception in SolrXmlInZkTest.testBadSysProp, sysprop set to bogus value.",
ite.getTargetException().getMessage(), "Bad solr.solrxml.location set: solrHomeDir - should be 'solrhome' or 'zookeeper'");
} finally {
closeZK();
}
}
//SolrDispatchFilter.protected static ConfigSolr loadConfigSolr(SolrResourceLoader loader) {
@Test
public void testZkHostDiscovery() throws ClassNotFoundException, NoSuchMethodException,
IllegalAccessException, InstantiationException, InvocationTargetException {
// Should see an error when zkHost is not defined but solr.solrxml.location is set to zookeeper.
System.clearProperty("zkHost");
try {
Method method = SolrDispatchFilter.class.getDeclaredMethod("loadConfigSolr", SolrResourceLoader.class);
method.setAccessible(true);
method.invoke(new SolrDispatchFilter(), new SolrResourceLoader(null));
fail("Should have thrown an exception");
} catch (InvocationTargetException ite) {
assertTrue("Should be catching a SolrException", ite.getTargetException() instanceof SolrException);
assertEquals("Caught Solr exception", ite.getTargetException().getMessage(),
"Could not load solr.xml from zookeeper: zkHost system property not set");
}
}
// Just a random port, I'm not going to use it but just check that the Solr instance constructed from the XML
// file in ZK overrides the default port.
private final String XML_FOR_ZK =
"<solr>" +
" <solrcloud>" +
" <str name=\"host\">127.0.0.1</str>" +
" <int name=\"hostPort\">9045</int>" +
" <str name=\"hostContext\">${hostContext:solr}</str>" +
" </solrcloud>" +
" <shardHandlerFactory name=\"shardHandlerFactory\" class=\"HttpShardHandlerFactory\">" +
" <int name=\"socketTimeout\">${socketTimeout:120000}</int>" +
" <int name=\"connTimeout\">${connTimeout:15000}</int>" +
" </shardHandlerFactory>" +
"</solr>";
}