From d0d893e1045eb4d7813e39249ed37b726536eaf3 Mon Sep 17 00:00:00 2001 From: Alan Woodward Date: Mon, 5 Sep 2016 10:13:49 +0100 Subject: [PATCH] SOLR-9344: Move BasicAuthIntegrationTest to SolrCloudTestCase --- .../cloud/TestMiniSolrCloudClusterBase.java | 207 ------------------ .../security/BasicAuthIntegrationTest.java | 76 +++---- .../apache/solr/cloud/SolrCloudTestCase.java | 5 + 3 files changed, 41 insertions(+), 247 deletions(-) delete mode 100644 solr/core/src/test/org/apache/solr/cloud/TestMiniSolrCloudClusterBase.java diff --git a/solr/core/src/test/org/apache/solr/cloud/TestMiniSolrCloudClusterBase.java b/solr/core/src/test/org/apache/solr/cloud/TestMiniSolrCloudClusterBase.java deleted file mode 100644 index 33fa43b1588..00000000000 --- a/solr/core/src/test/org/apache/solr/cloud/TestMiniSolrCloudClusterBase.java +++ /dev/null @@ -1,207 +0,0 @@ -/* - * 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.cloud; - -import java.io.File; -import java.lang.invoke.MethodHandles; -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import com.carrotsearch.randomizedtesting.rules.SystemPropertiesRestoreRule; -import org.apache.lucene.index.TieredMergePolicy; -import org.apache.lucene.util.LuceneTestCase; -import org.apache.solr.SolrTestCaseJ4; -import org.apache.solr.client.solrj.SolrQuery; -import org.apache.solr.client.solrj.embedded.JettyConfig; -import org.apache.solr.client.solrj.embedded.JettySolrRunner; -import org.apache.solr.client.solrj.impl.CloudSolrClient; -import org.apache.solr.client.solrj.response.QueryResponse; -import org.apache.solr.client.solrj.response.RequestStatusState; -import org.apache.solr.common.SolrInputDocument; -import org.apache.solr.common.cloud.ClusterState; -import org.apache.solr.common.cloud.Replica; -import org.apache.solr.common.cloud.Slice; -import org.apache.solr.common.cloud.SolrZkClient; -import org.apache.solr.common.cloud.ZkStateReader; -import org.apache.solr.core.CoreDescriptor; -import org.apache.solr.index.TieredMergePolicyFactory; -import org.apache.solr.util.RevertDefaultThreadHandlerRule; -import org.junit.ClassRule; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.RuleChain; -import org.junit.rules.TestRule; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -@LuceneTestCase.SuppressSysoutChecks(bugUrl = "Solr logs to JUL") -public class TestMiniSolrCloudClusterBase extends LuceneTestCase { - - private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); - protected int NUM_SERVERS = 5; - protected int NUM_SHARDS = 2; - protected int REPLICATION_FACTOR = 2; - - public TestMiniSolrCloudClusterBase () { - NUM_SERVERS = 5; - NUM_SHARDS = 2; - REPLICATION_FACTOR = 2; - } - - @Rule - public TestRule solrTestRules = RuleChain - .outerRule(new SystemPropertiesRestoreRule()); - - @ClassRule - public static TestRule solrClassRules = RuleChain.outerRule( - new SystemPropertiesRestoreRule()).around( - new RevertDefaultThreadHandlerRule()); - - @Test - public void testBasics() throws Exception { - final String collectionName = "testSolrCloudCollection"; - testCollectionCreateSearchDelete(collectionName); - } - - private MiniSolrCloudCluster createMiniSolrCloudCluster() throws Exception { - JettyConfig.Builder jettyConfig = JettyConfig.builder(); - jettyConfig.waitForLoadingCoresToFinish(null); - return new MiniSolrCloudCluster(NUM_SERVERS, createTempDir(), jettyConfig.build()); - } - - private void createCollection(MiniSolrCloudCluster miniCluster, String collectionName, String createNodeSet, String asyncId) throws Exception { - String configName = "solrCloudCollectionConfig"; - File configDir = new File(SolrTestCaseJ4.TEST_HOME() + File.separator + "collection1" + File.separator + "conf"); - miniCluster.uploadConfigDir(configDir, configName); - - Map collectionProperties = new HashMap<>(); - collectionProperties.put(CoreDescriptor.CORE_CONFIG, "solrconfig-tlog.xml"); - collectionProperties.put("solr.tests.maxBufferedDocs", "100000"); - collectionProperties.put("solr.tests.ramBufferSizeMB", "100"); - // use non-test classes so RandomizedRunner isn't necessary - if (random().nextBoolean()) { - collectionProperties.put(SolrTestCaseJ4.SYSTEM_PROPERTY_SOLR_TESTS_MERGEPOLICY, TieredMergePolicy.class.getName()); - collectionProperties.put(SolrTestCaseJ4.SYSTEM_PROPERTY_SOLR_TESTS_USEMERGEPOLICY, "true"); - collectionProperties.put(SolrTestCaseJ4.SYSTEM_PROPERTY_SOLR_TESTS_USEMERGEPOLICYFACTORY, "false"); - } else { - collectionProperties.put(SolrTestCaseJ4.SYSTEM_PROPERTY_SOLR_TESTS_MERGEPOLICYFACTORY, TieredMergePolicyFactory.class.getName()); - collectionProperties.put(SolrTestCaseJ4.SYSTEM_PROPERTY_SOLR_TESTS_USEMERGEPOLICYFACTORY, "true"); - collectionProperties.put(SolrTestCaseJ4.SYSTEM_PROPERTY_SOLR_TESTS_USEMERGEPOLICY, "false"); - } - collectionProperties.put("solr.tests.mergeScheduler", "org.apache.lucene.index.ConcurrentMergeScheduler"); - collectionProperties.put("solr.directoryFactory", "solr.RAMDirectoryFactory"); - - miniCluster.createCollection(collectionName, NUM_SHARDS, REPLICATION_FACTOR, configName, createNodeSet, asyncId, collectionProperties); - } - - protected void testCollectionCreateSearchDelete(String collectionName) throws Exception { - - MiniSolrCloudCluster miniCluster = createMiniSolrCloudCluster(); - - final CloudSolrClient cloudSolrClient = miniCluster.getSolrClient(); - - try { - assertNotNull(miniCluster.getZkServer()); - List jettys = miniCluster.getJettySolrRunners(); - assertEquals(NUM_SERVERS, jettys.size()); - for (JettySolrRunner jetty : jettys) { - assertTrue(jetty.isRunning()); - } - - // shut down a server - JettySolrRunner stoppedServer = miniCluster.stopJettySolrRunner(0); - assertTrue(stoppedServer.isStopped()); - assertEquals(NUM_SERVERS - 1, miniCluster.getJettySolrRunners().size()); - - // create a server - JettySolrRunner startedServer = miniCluster.startJettySolrRunner(); - assertTrue(startedServer.isRunning()); - assertEquals(NUM_SERVERS, miniCluster.getJettySolrRunners().size()); - - // create collection - final String asyncId = (random().nextBoolean() ? null : "asyncId("+collectionName+".create)="+random().nextInt()); - createCollection(miniCluster, collectionName, null, asyncId); - if (asyncId != null) { - final RequestStatusState state = AbstractFullDistribZkTestBase.getRequestStateAfterCompletion(asyncId, 330, - cloudSolrClient); - assertSame("did not see async createCollection completion", RequestStatusState.COMPLETED, state); - } - - try (SolrZkClient zkClient = new SolrZkClient - (miniCluster.getZkServer().getZkAddress(), AbstractZkTestCase.TIMEOUT, AbstractZkTestCase.TIMEOUT, null); - ZkStateReader zkStateReader = new ZkStateReader(zkClient)) { - zkStateReader.createClusterStateWatchersAndUpdate(); - AbstractDistribZkTestBase.waitForRecoveriesToFinish(collectionName, zkStateReader, true, true, 330); - - // modify/query collection - cloudSolrClient.setDefaultCollection(collectionName); - SolrInputDocument doc = new SolrInputDocument(); - doc.setField("id", "1"); - cloudSolrClient.add(doc); - cloudSolrClient.commit(); - SolrQuery query = new SolrQuery(); - query.setQuery("*:*"); - QueryResponse rsp = cloudSolrClient.query(query); - assertEquals(1, rsp.getResults().getNumFound()); - - // remove a server not hosting any replicas - zkStateReader.forceUpdateCollection(collectionName); - ClusterState clusterState = zkStateReader.getClusterState(); - HashMap jettyMap = new HashMap(); - for (JettySolrRunner jetty : miniCluster.getJettySolrRunners()) { - String key = jetty.getBaseUrl().toString().substring((jetty.getBaseUrl().getProtocol() + "://").length()); - jettyMap.put(key, jetty); - } - Collection slices = clusterState.getSlices(collectionName); - // track the servers not host repliacs - for (Slice slice : slices) { - jettyMap.remove(slice.getLeader().getNodeName().replace("_solr", "/solr")); - for (Replica replica : slice.getReplicas()) { - jettyMap.remove(replica.getNodeName().replace("_solr", "/solr")); - } - } - assertTrue("Expected to find a node without a replica", jettyMap.size() > 0); - JettySolrRunner jettyToStop = jettyMap.entrySet().iterator().next().getValue(); - jettys = miniCluster.getJettySolrRunners(); - for (int i = 0; i < jettys.size(); ++i) { - if (jettys.get(i).equals(jettyToStop)) { - miniCluster.stopJettySolrRunner(i); - assertEquals(NUM_SERVERS - 1, miniCluster.getJettySolrRunners().size()); - } - } - - // now restore the original state so that this function could be called multiple times - - // re-create a server (to restore original NUM_SERVERS count) - startedServer = miniCluster.startJettySolrRunner(); - assertTrue(startedServer.isRunning()); - assertEquals(NUM_SERVERS, miniCluster.getJettySolrRunners().size()); - - doExtraTests(miniCluster, zkClient, zkStateReader,cloudSolrClient, collectionName); - } - } - finally { - miniCluster.shutdown(); - } - } - - protected void doExtraTests(MiniSolrCloudCluster miniCluster, SolrZkClient zkClient, ZkStateReader zkStateReader, CloudSolrClient cloudSolrClient, - String defaultCollName) throws Exception { /*do nothing*/ } - -} diff --git a/solr/core/src/test/org/apache/solr/security/BasicAuthIntegrationTest.java b/solr/core/src/test/org/apache/solr/security/BasicAuthIntegrationTest.java index 6070cf69151..ecfa392ebca 100644 --- a/solr/core/src/test/org/apache/solr/security/BasicAuthIntegrationTest.java +++ b/solr/core/src/test/org/apache/solr/security/BasicAuthIntegrationTest.java @@ -40,20 +40,16 @@ import org.apache.http.message.BasicHeader; import org.apache.http.util.EntityUtils; import org.apache.solr.client.solrj.SolrRequest; import org.apache.solr.client.solrj.embedded.JettySolrRunner; -import org.apache.solr.client.solrj.impl.CloudSolrClient; import org.apache.solr.client.solrj.impl.HttpClientUtil; import org.apache.solr.client.solrj.impl.HttpSolrClient; import org.apache.solr.client.solrj.request.CollectionAdminRequest; import org.apache.solr.client.solrj.request.GenericSolrRequest; import org.apache.solr.client.solrj.request.UpdateRequest; -import org.apache.solr.cloud.MiniSolrCloudCluster; -import org.apache.solr.cloud.TestMiniSolrCloudClusterBase; +import org.apache.solr.cloud.SolrCloudTestCase; import org.apache.solr.common.SolrInputDocument; import org.apache.solr.common.cloud.DocCollection; import org.apache.solr.common.cloud.Replica; import org.apache.solr.common.cloud.Slice; -import org.apache.solr.common.cloud.SolrZkClient; -import org.apache.solr.common.cloud.ZkStateReader; import org.apache.solr.common.params.ModifiableSolrParams; import org.apache.solr.common.util.Base64; import org.apache.solr.common.util.ContentStreamBase; @@ -61,50 +57,49 @@ import org.apache.solr.common.util.NamedList; import org.apache.solr.common.util.StrUtils; import org.apache.solr.common.util.Utils; import org.apache.solr.util.SolrCLI; +import org.junit.BeforeClass; +import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import static java.nio.charset.StandardCharsets.UTF_8; import static java.util.Collections.singletonMap; -import static org.apache.solr.SolrTestCaseJ4.getHttpSolrClient; -import static org.apache.solr.common.cloud.ZkStateReader.BASE_URL_PROP; -public class BasicAuthIntegrationTest extends TestMiniSolrCloudClusterBase { +public class BasicAuthIntegrationTest extends SolrCloudTestCase { private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); - @Override - protected void doExtraTests(MiniSolrCloudCluster miniCluster, SolrZkClient zkClient, ZkStateReader zkStateReader, - CloudSolrClient cloudSolrClient, String defaultCollName) throws Exception { + private static final String COLLECTION = "authCollection"; + @BeforeClass + public static void setupCluster() throws Exception { + configureCluster(3) + .addConfig("conf", configset("cloud-minimal")) + .configure(); + + CollectionAdminRequest.createCollection(COLLECTION, "conf", 3, 1).process(cluster.getSolrClient()); + } + + @Test + public void testBasicAuth() throws Exception { String authcPrefix = "/admin/authentication"; String authzPrefix = "/admin/authorization"; - String old = cloudSolrClient.getDefaultCollection(); - cloudSolrClient.setDefaultCollection(null); - NamedList rsp; HttpClient cl = null; try { cl = HttpClientUtil.createClient(null); - String baseUrl = getRandomReplica(zkStateReader.getClusterState().getCollection(defaultCollName), random()).getStr(BASE_URL_PROP); + + JettySolrRunner randomJetty = cluster.getRandomJetty(random()); + String baseUrl = randomJetty.getBaseUrl().toString(); verifySecurityStatus(cl, baseUrl + authcPrefix, "/errorMessages", null, 20); - zkClient.setData("/security.json", STD_CONF.replaceAll("'", "\"").getBytes(UTF_8), true); + zkClient().setData("/security.json", STD_CONF.replaceAll("'", "\"").getBytes(UTF_8), true); verifySecurityStatus(cl, baseUrl + authcPrefix, "authentication/class", "solr.BasicAuthPlugin", 20); - boolean found = false; - for (JettySolrRunner jettySolrRunner : miniCluster.getJettySolrRunners()) { - if(baseUrl.contains(String.valueOf(jettySolrRunner.getLocalPort()))){ - found = true; - jettySolrRunner.stop(); - jettySolrRunner.start(); - verifySecurityStatus(cl, baseUrl + authcPrefix, "authentication/class", "solr.BasicAuthPlugin", 20); - break; - } - } - - assertTrue("No server found to restart , looking for : "+baseUrl , found); + randomJetty.stop(); + randomJetty.start(); + verifySecurityStatus(cl, baseUrl + authcPrefix, "authentication/class", "solr.BasicAuthPlugin", 20); String command = "{\n" + "'set-user': {'harry':'HarryIsCool'}\n" + @@ -112,11 +107,12 @@ public class BasicAuthIntegrationTest extends TestMiniSolrCloudClusterBase { GenericSolrRequest genericReq = new GenericSolrRequest(SolrRequest.METHOD.POST, authcPrefix, new ModifiableSolrParams()); genericReq.setContentStreams(Collections.singletonList(new ContentStreamBase.ByteArrayStream(command.getBytes(UTF_8), ""))); - try { - cloudSolrClient.request(genericReq); - fail("Should have failed with a 401"); - } catch (HttpSolrClient.RemoteSolrException e) { - } + + HttpSolrClient.RemoteSolrException exp = expectThrows(HttpSolrClient.RemoteSolrException.class, () -> { + cluster.getSolrClient().request(genericReq); + }); + assertEquals(401, exp.code()); + command = "{\n" + "'set-user': {'harry':'HarryIsUberCool'}\n" + "}"; @@ -130,7 +126,8 @@ public class BasicAuthIntegrationTest extends TestMiniSolrCloudClusterBase { int statusCode = r.getStatusLine().getStatusCode(); Utils.consumeFully(r.getEntity()); assertEquals("proper_cred sent, but access denied", 200, statusCode); - baseUrl = getRandomReplica(zkStateReader.getClusterState().getCollection(defaultCollName), random()).getStr(BASE_URL_PROP); + + baseUrl = cluster.getRandomJetty(random()).getBaseUrl().toString(); verifySecurityStatus(cl, baseUrl + authcPrefix, "authentication/credentials/harry", NOT_NULL_PREDICATE, 20); command = "{\n" + @@ -139,7 +136,7 @@ public class BasicAuthIntegrationTest extends TestMiniSolrCloudClusterBase { executeCommand(baseUrl + authzPrefix, cl,command, "solr", "SolrRocks"); - baseUrl = getRandomReplica(zkStateReader.getClusterState().getCollection(defaultCollName), random()).getStr(BASE_URL_PROP); + baseUrl = cluster.getRandomJetty(random()).getBaseUrl().toString(); verifySecurityStatus(cl, baseUrl + authzPrefix, "authorization/user-role/harry", NOT_NULL_PREDICATE, 20); executeCommand(baseUrl + authzPrefix, cl, Utils.toJSONString(singletonMap("set-permission", Utils.makeMap @@ -153,7 +150,7 @@ public class BasicAuthIntegrationTest extends TestMiniSolrCloudClusterBase { ("name", "collection-admin-edit", "role", "admin"))), "harry", "HarryIsUberCool" ); verifySecurityStatus(cl, baseUrl + authzPrefix, "authorization/permissions[2]/name", "collection-admin-edit", 20); - CollectionAdminRequest.Reload reload = CollectionAdminRequest.reloadCollection(defaultCollName); + CollectionAdminRequest.Reload reload = CollectionAdminRequest.reloadCollection(COLLECTION); try (HttpSolrClient solrClient = getHttpSolrClient(baseUrl)) { try { @@ -170,18 +167,17 @@ public class BasicAuthIntegrationTest extends TestMiniSolrCloudClusterBase { } } - cloudSolrClient.request(CollectionAdminRequest.reloadCollection(defaultCollName) + cluster.getSolrClient().request(CollectionAdminRequest.reloadCollection(COLLECTION) .setBasicAuthCredentials("harry", "HarryIsUberCool")); try { - cloudSolrClient.request(CollectionAdminRequest.reloadCollection(defaultCollName) + cluster.getSolrClient().request(CollectionAdminRequest.reloadCollection(COLLECTION) .setBasicAuthCredentials("harry", "Cool12345")); fail("This should not succeed"); } catch (HttpSolrClient.RemoteSolrException e) { } - cloudSolrClient.setDefaultCollection(old); executeCommand(baseUrl + authzPrefix, cl,"{set-permission : { name : update , role : admin}}", "harry", "HarryIsUberCool"); SolrInputDocument doc = new SolrInputDocument(); @@ -190,7 +186,7 @@ public class BasicAuthIntegrationTest extends TestMiniSolrCloudClusterBase { update.setBasicAuthCredentials("harry","HarryIsUberCool"); update.add(doc); update.setCommitWithin(100); - cloudSolrClient.request(update); + cluster.getSolrClient().request(update, COLLECTION); executeCommand(baseUrl + authcPrefix, cl, "{set-property : { blockUnknown: true}}", "harry", "HarryIsUberCool"); diff --git a/solr/test-framework/src/java/org/apache/solr/cloud/SolrCloudTestCase.java b/solr/test-framework/src/java/org/apache/solr/cloud/SolrCloudTestCase.java index ccf6e3ba1ab..427c62718ac 100644 --- a/solr/test-framework/src/java/org/apache/solr/cloud/SolrCloudTestCase.java +++ b/solr/test-framework/src/java/org/apache/solr/cloud/SolrCloudTestCase.java @@ -27,6 +27,7 @@ import java.util.List; import org.apache.solr.SolrTestCaseJ4; import org.apache.solr.client.solrj.embedded.JettyConfig; import org.apache.solr.client.solrj.impl.CloudSolrClient; +import org.apache.solr.common.cloud.SolrZkClient; import org.junit.AfterClass; import org.junit.Before; @@ -143,6 +144,10 @@ public class SolrCloudTestCase extends SolrTestCaseJ4 { /** The cluster */ protected static MiniSolrCloudCluster cluster; + protected SolrZkClient zkClient() { + return cluster.getSolrClient().getZkStateReader().getZkClient(); + } + /** * Call this to configure a cluster of n nodes. *