blob: 9d196cf50add74c1b13896cfa08e29dae8317e0d [file] [log] [blame]
/*
* 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.solr.handler;
import java.io.File;
import java.io.IOException;
import java.util.List;
import org.apache.commons.io.FileUtils;
import org.apache.solr.SolrTestCaseJ4;
import org.apache.solr.client.solrj.embedded.JettySolrRunner;
import org.apache.solr.client.solrj.impl.CloudSolrClient;
import org.apache.solr.client.solrj.request.CollectionAdminRequest;
import org.apache.solr.client.solrj.request.SolrPing;
import org.apache.solr.client.solrj.response.SolrPingResponse;
import org.apache.solr.cloud.MiniSolrCloudCluster;
import org.apache.solr.cloud.SolrCloudTestCase;
import org.apache.solr.common.SolrException;
import org.apache.solr.common.util.NamedList;
import org.apache.solr.request.SolrQueryRequest;
import org.apache.solr.response.SolrQueryResponse;
import org.junit.Before;
import org.junit.BeforeClass;
public class PingRequestHandlerTest extends SolrTestCaseJ4 {
protected int NUM_SERVERS = 5;
protected int NUM_SHARDS = 2;
protected int REPLICATION_FACTOR = 2;
private final String fileName = this.getClass().getName() + ".server-enabled";
private File healthcheckFile = null;
private PingRequestHandler handler = null;
@BeforeClass
public static void beforeClass() throws Exception {
initCore("solrconfig.xml", "schema.xml");
}
@Before
@SuppressWarnings({"unchecked"})
public void before() throws IOException {
// by default, use relative file in dataDir
healthcheckFile = new File(initAndGetDataDir(), fileName);
String fileNameParam = fileName;
// sometimes randomly use an absolute File path instead
if (random().nextBoolean()) {
fileNameParam = healthcheckFile.getAbsolutePath();
}
if (healthcheckFile.exists()) FileUtils.forceDelete(healthcheckFile);
handler = new PingRequestHandler();
@SuppressWarnings({"rawtypes"})
NamedList initParams = new NamedList();
initParams.add(PingRequestHandler.HEALTHCHECK_FILE_PARAM,
fileNameParam);
handler.init(initParams);
handler.inform(h.getCore());
}
@SuppressWarnings({"rawtypes"})
public void testPingWithNoHealthCheck() throws Exception {
// for this test, we don't want any healthcheck file configured at all
handler = new PingRequestHandler();
handler.init(new NamedList());
handler.inform(h.getCore());
SolrQueryResponse rsp = null;
rsp = makeRequest(handler, req());
assertEquals("OK", rsp.getValues().get("status"));
rsp = makeRequest(handler, req("action","ping"));
assertEquals("OK", rsp.getValues().get("status"));
}
public void testEnablingServer() throws Exception {
assertTrue(!healthcheckFile.exists());
// first make sure that ping responds back that the service is disabled
SolrQueryResponse sqr = makeRequest(handler, req());
SolrException se = (SolrException) sqr.getException();
assertEquals(
"Response should have been replaced with a 503 SolrException.",
se.code(), SolrException.ErrorCode.SERVICE_UNAVAILABLE.code);
// now enable
makeRequest(handler, req("action", "enable"));
assertTrue(healthcheckFile.exists());
assertNotNull(FileUtils.readFileToString(healthcheckFile, "UTF-8"));
// now verify that the handler response with success
SolrQueryResponse rsp = makeRequest(handler, req());
assertEquals("OK", rsp.getValues().get("status"));
// enable when already enabled shouldn't cause any problems
makeRequest(handler, req("action", "enable"));
assertTrue(healthcheckFile.exists());
}
public void testDisablingServer() throws Exception {
assertTrue(! healthcheckFile.exists());
healthcheckFile.createNewFile();
// first make sure that ping responds back that the service is enabled
SolrQueryResponse rsp = makeRequest(handler, req());
assertEquals("OK", rsp.getValues().get("status"));
// now disable
makeRequest(handler, req("action", "disable"));
assertFalse(healthcheckFile.exists());
// now make sure that ping responds back that the service is disabled
SolrQueryResponse sqr = makeRequest(handler, req());
SolrException se = (SolrException) sqr.getException();
assertEquals(
"Response should have been replaced with a 503 SolrException.",
se.code(), SolrException.ErrorCode.SERVICE_UNAVAILABLE.code);
// disable when already disabled shouldn't cause any problems
makeRequest(handler, req("action", "disable"));
assertFalse(healthcheckFile.exists());
}
public void testGettingStatus() throws Exception {
SolrQueryResponse rsp = null;
handler.handleEnable(true);
rsp = makeRequest(handler, req("action", "status"));
assertEquals("enabled", rsp.getValues().get("status"));
handler.handleEnable(false);
rsp = makeRequest(handler, req("action", "status"));
assertEquals("disabled", rsp.getValues().get("status"));
}
public void testBadActionRaisesException() throws Exception {
SolrException se = expectThrows(SolrException.class, () -> makeRequest(handler, req("action", "badaction")));
assertEquals(SolrException.ErrorCode.BAD_REQUEST.code,se.code());
}
public void testPingInClusterWithNoHealthCheck() throws Exception {
MiniSolrCloudCluster miniCluster = new MiniSolrCloudCluster(NUM_SERVERS, createTempDir(), buildJettyConfig("/solr"));
final CloudSolrClient cloudSolrClient = miniCluster.getSolrClient();
try {
assertNotNull(miniCluster.getZkServer());
List<JettySolrRunner> jettys = miniCluster.getJettySolrRunners();
assertEquals(NUM_SERVERS, jettys.size());
for (JettySolrRunner jetty : jettys) {
assertTrue(jetty.isRunning());
}
// create collection
String collectionName = "testSolrCloudCollection";
String configName = "solrCloudCollectionConfig";
miniCluster.uploadConfigSet(SolrTestCaseJ4.TEST_PATH().resolve("collection1").resolve("conf"), configName);
CollectionAdminRequest.createCollection(collectionName, configName, NUM_SHARDS, REPLICATION_FACTOR)
.setPerReplicaState(SolrCloudTestCase.USE_PER_REPLICA_STATE)
.process(miniCluster.getSolrClient());
// Send distributed and non-distributed ping query
SolrPingWithDistrib reqDistrib = new SolrPingWithDistrib();
reqDistrib.setDistrib(true);
SolrPingResponse rsp = reqDistrib.process(cloudSolrClient, collectionName);
assertEquals(0, rsp.getStatus());
assertTrue(rsp.getResponseHeader().getBooleanArg(("zkConnected")));
SolrPing reqNonDistrib = new SolrPing();
rsp = reqNonDistrib.process(cloudSolrClient, collectionName);
assertEquals(0, rsp.getStatus());
assertTrue(rsp.getResponseHeader().getBooleanArg(("zkConnected")));
}
finally {
miniCluster.shutdown();
}
}
/**
* Helper Method: Executes the request against the handler, returns
* the response, and closes the request.
*/
private SolrQueryResponse makeRequest(PingRequestHandler handler,
SolrQueryRequest req)
throws Exception {
SolrQueryResponse rsp = new SolrQueryResponse();
try {
handler.handleRequestBody(req, rsp);
} finally {
req.close();
}
return rsp;
}
static class SolrPingWithDistrib extends SolrPing {
public SolrPing setDistrib(boolean distrib) {
getParams().add("distrib", distrib ? "true" : "false");
return this;
}
}
}