Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
0989327
Scope: don't use Apache HttpClient directly; use of it via HttpSolrCl…
dsmiley Apr 5, 2026
00e89df
Finish-ish.
dsmiley Apr 6, 2026
09f3bfb
Use clearer GET(uri) method
dsmiley Apr 6, 2026
ed8b57b
Use convenient POST method
dsmiley Apr 6, 2026
3f37f1c
more HttpMethod use
dsmiley Apr 6, 2026
5c7bf2e
dedupe/simplify doHttpPost/doHttpPostWithHeader
dsmiley Apr 6, 2026
548abfd
pass headers better
dsmiley Apr 6, 2026
40b9991
reverting some things
dsmiley Apr 6, 2026
e77d8db
optimize buildURI
dsmiley Apr 6, 2026
0dd173a
Merge remote-tracking branch 'refs/remotes/apache/main' into SOLR-181…
dsmiley Apr 6, 2026
2683172
fix merge
dsmiley Apr 6, 2026
ad3f730
enhanced switch statements.
dsmiley Apr 6, 2026
11ee2f2
CreateRoutedAliasTest: align comments
dsmiley Apr 6, 2026
3eee082
multi-line string
dsmiley Apr 6, 2026
c6b32c5
callMigrateReplicas var naming
dsmiley Apr 6, 2026
cd72b3f
RestTestHarness:
dsmiley Apr 6, 2026
28d1faf
define logger correctly
dsmiley Apr 6, 2026
30597c6
@SuppressWarnings("try")
dsmiley Apr 7, 2026
2b02520
Merge remote-tracking branch 'apache/main' into SOLR-18188-migrateToJ…
dsmiley Apr 7, 2026
f376e61
Refactor RestTestHarness: make immutable, lightweight, and cheap to c…
dsmiley Apr 7, 2026
8ae9852
JettySolrRunner.getRestClient & getBaseUri.
dsmiley Apr 7, 2026
49fbdcb
JettySolrRunner.getRestClient & getBaseUri.
dsmiley Apr 7, 2026
b96cfe1
head() should return the status code
dsmiley Apr 7, 2026
ad62248
Revert changes split to another PR
dsmiley Apr 7, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion solr/core/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,6 @@ dependencies {
exclude group: "net.bytebuddy", module: "byte-buddy-agent"
})
testImplementation libs.apache.httpcomponents.httpclient
testImplementation libs.apache.httpcomponents.httpcore
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

progress


testImplementation libs.opentelemetry.sdk.testing
testImplementation libs.dropwizard.metrics.core
Expand Down
27 changes: 1 addition & 26 deletions solr/core/src/java/org/apache/solr/security/SimplePrincipal.java
Comment thread
dsmiley marked this conversation as resolved.
Original file line number Diff line number Diff line change
Expand Up @@ -18,37 +18,12 @@
package org.apache.solr.security;

import java.security.Principal;
import java.util.Objects;

/** A basic name-only {@link Principal}. */
public final class SimplePrincipal implements Principal {
// TODO use a record. But javadoc tooling complained as it was confused (Java version issue?)
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this mystery was solved previously, unblocking this nice conversion

private final String name;

public SimplePrincipal(String name) {
this.name = name;
}
public record SimplePrincipal(String name) implements Principal {

@Override
public String getName() {
return name;
}

@Override
public boolean equals(Object obj) {
if (obj == this) return true;
if (obj == null || obj.getClass() != this.getClass()) return false;
var that = (SimplePrincipal) obj;
return Objects.equals(this.name, that.name);
}

@Override
public int hashCode() {
return Objects.hash(name);
}

@Override
public String toString() {
return "SimplePrincipal[" + "name=" + name + ']';
}
}
142 changes: 67 additions & 75 deletions solr/core/src/test/org/apache/solr/cloud/AliasIntegrationTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,25 +19,16 @@
import static org.apache.solr.common.cloud.ZkStateReader.ALIASES;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
import java.util.function.UnaryOperator;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.util.EntityUtils;
import org.apache.solr.client.solrj.SolrClient;
import org.apache.solr.client.solrj.SolrRequest;
import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.client.solrj.apache.CloudLegacySolrClient;
import org.apache.solr.client.solrj.cloud.SolrCloudManager;
import org.apache.solr.client.solrj.impl.CloudSolrClient;
import org.apache.solr.client.solrj.impl.ClusterStateProvider;
Expand All @@ -60,15 +51,17 @@
import org.apache.solr.embedded.JettySolrRunner;
import org.apache.solr.util.TimeOut;
import org.apache.zookeeper.KeeperException;
import org.eclipse.jetty.client.ContentResponse;
import org.eclipse.jetty.client.HttpClient;
import org.eclipse.jetty.client.StringRequestContent;
import org.eclipse.jetty.http.HttpMethod;
import org.junit.After;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;

public class AliasIntegrationTest extends SolrCloudTestCase {

private CloseableHttpClient httpClient;
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

usually no field is needed since it's easy to grab a managed Jetty HttpClient from places


@BeforeClass
public static void setupCluster() throws Exception {
configureCluster(2).addConfig("conf", configset("cloud-minimal")).configure();
Expand All @@ -78,9 +71,6 @@ public static void setupCluster() throws Exception {
@Override
public void setUp() throws Exception {
super.setUp();

httpClient =
(CloseableHttpClient) ((CloudLegacySolrClient) cluster.getSolrClient()).getHttpClient();
}

@After
Expand Down Expand Up @@ -238,49 +228,53 @@ public void testProperties() throws Exception {
public void testModifyPropertiesV2() throws Exception {
final String aliasName = getSaferTestName();
ZkStateReader zkStateReader = createColectionsAndAlias(aliasName);
final String baseUrl = cluster.getRandomJetty(random()).getBaseURLV2().toString();
final JettySolrRunner runner = cluster.getRandomJetty(random());
final String baseUrl = runner.getBaseURLV2().toString();
final HttpClient httpClient = runner.getSolrClient().getHttpClient();
String aliasApi = String.format(Locale.ENGLISH, "/aliases/%s/properties", aliasName);

HttpPut withoutBody = new HttpPut(baseUrl + aliasApi);
assertEquals(400, httpClient.execute(withoutBody).getStatusLine().getStatusCode());

HttpPut update = new HttpPut(baseUrl + aliasApi);
update.setEntity(
new StringEntity(
"{\n"
+ " \"properties\":\n"
+ " {\n"
+ " \"foo\": \"baz\",\n"
+ " \"bar\": \"bam\"\n"
+ " }\n"
+ "}",
ContentType.APPLICATION_JSON));
assertSuccess(update);
assertEquals(
400, httpClient.newRequest(baseUrl + aliasApi).method(HttpMethod.PUT).send().getStatus());

String body =
"{\n"
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i had good luck with the """ tags to simplify json formatted strings. Since you are reformatting a lot in this PR, might be worth embracing it for the JSON?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I may change some of these where I add new code but otherwise don't want to change more lines in a massive PR.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I get that! I was thinking since whitespace changed, but I guess you can diff wihtout whitespace and that reduces the change.

+ " \"properties\":\n"
+ " {\n"
+ " \"foo\": \"baz\",\n"
+ " \"bar\": \"bam\"\n"
+ " }\n"
+ "}";
assertSuccess(
httpClient
.newRequest(baseUrl + aliasApi)
.method(HttpMethod.PUT)
.body(new StringRequestContent("application/json", body, StandardCharsets.UTF_8))
.send());
Comment thread
dsmiley marked this conversation as resolved.
checkFooAndBarMeta(aliasName, zkStateReader, "baz", "bam");

String aliasPropertyApi =
String.format(Locale.ENGLISH, "/aliases/%s/properties/%s", aliasName, "foo");
HttpPut updateByProperty = new HttpPut(baseUrl + aliasPropertyApi);
updateByProperty.setEntity(
new StringEntity("{ \"value\": \"zab\" }", ContentType.APPLICATION_JSON));
assertSuccess(updateByProperty);
assertSuccess(
httpClient
.newRequest(baseUrl + aliasPropertyApi)
.method(HttpMethod.PUT)
.body(
new StringRequestContent(
"application/json", "{ \"value\": \"zab\" }", StandardCharsets.UTF_8))
.send());
checkFooAndBarMeta(aliasName, zkStateReader, "zab", "bam");

HttpDelete deleteByProperty = new HttpDelete(baseUrl + aliasPropertyApi);
assertSuccess(deleteByProperty);
assertSuccess(
httpClient.newRequest(baseUrl + aliasPropertyApi).method(HttpMethod.DELETE).send());
checkFooAndBarMeta(aliasName, zkStateReader, null, "bam");

HttpPut deleteByEmptyValue = new HttpPut(baseUrl + aliasApi);
deleteByEmptyValue.setEntity(
new StringEntity(
"{\n"
+ " \"properties\":\n"
+ " {\n"
+ " \"bar\": \"\"\n"
+ " }\n"
+ "}",
ContentType.APPLICATION_JSON));
assertSuccess(deleteByEmptyValue);
body = "{ \"properties\": { \"bar\": \"\" } }";
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i know you can make the json more compact, but the long form makes the nesting easier to read. maybe just my personal preference.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Triple-quote would be clearer and also compact -- can then remove the quote escaping (I think).

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for one-liners, no it forces you to use another line. So I don't plan to update much for this matter.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that works.

assertSuccess(
httpClient
.newRequest(baseUrl + aliasApi)
.method(HttpMethod.PUT)
.body(new StringRequestContent("application/json", body, StandardCharsets.UTF_8))
.send());
checkFooAndBarMeta(aliasName, zkStateReader, null, null);
}

Expand All @@ -289,29 +283,29 @@ public void testModifyPropertiesV1() throws Exception {
// note we don't use TZ in this test, thus it's UTC
final String aliasName = getSaferTestName();
ZkStateReader zkStateReader = createColectionsAndAlias(aliasName);
final String baseUrl = cluster.getRandomJetty(random()).getBaseUrl().toString();
HttpGet get =
new HttpGet(
baseUrl
+ "/admin/collections?action=ALIASPROP"
+ "&wt=xml"
+ "&name="
+ aliasName
+ "&property.foo=baz"
+ "&property.bar=bam");
assertSuccess(get);
final JettySolrRunner runner = cluster.getRandomJetty(random());
final String baseUrl = runner.getBaseUrl().toString();
final HttpClient httpClient = runner.getSolrClient().getHttpClient();
String url =
baseUrl
+ "/admin/collections?action=ALIASPROP"
+ "&wt=xml"
+ "&name="
+ aliasName
+ "&property.foo=baz"
+ "&property.bar=bam";
assertSuccess(httpClient.GET(url));
checkFooAndBarMeta(aliasName, zkStateReader, "baz", "bam");

HttpGet remove =
new HttpGet(
baseUrl
+ "/admin/collections?action=ALIASPROP"
+ "&wt=xml"
+ "&name="
+ aliasName
+ "&property.foo="
+ "&property.bar=bar");
assertSuccess(remove);
url =
baseUrl
+ "/admin/collections?action=ALIASPROP"
+ "&wt=xml"
+ "&name="
+ aliasName
+ "&property.foo="
+ "&property.bar=bar";
assertSuccess(httpClient.GET(url));
checkFooAndBarMeta(aliasName, zkStateReader, null, "bar");
}

Expand Down Expand Up @@ -508,12 +502,10 @@ private ZkStateReader createColectionsAndAlias(String aliasName)
return zkStateReader;
}

private void assertSuccess(HttpUriRequest msg) throws IOException {
try (CloseableHttpResponse response = httpClient.execute(msg)) {
if (200 != response.getStatusLine().getStatusCode()) {
System.err.println(EntityUtils.toString(response.getEntity()));
fail("Unexpected status: " + response.getStatusLine());
}
private void assertSuccess(ContentResponse response) {
Comment thread
dsmiley marked this conversation as resolved.
if (200 != response.getStatus()) {
System.err.println(response.getContentAsString());
fail("Unexpected status: " + response.getStatus());
}
}

Expand Down
52 changes: 18 additions & 34 deletions solr/core/src/test/org/apache/solr/cloud/BalanceReplicasTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@

package org.apache.solr.cloud;

import static java.nio.charset.StandardCharsets.UTF_8;

import java.io.IOException;
import java.lang.invoke.MethodHandles;
import java.util.ArrayList;
Expand All @@ -27,21 +25,16 @@
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.HttpEntityEnclosingRequestBase;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ByteArrayEntity;
import org.apache.http.entity.ContentType;
import org.apache.http.util.EntityUtils;
import org.apache.solr.client.api.model.BalanceReplicasRequestBody;
import org.apache.solr.client.solrj.apache.CloudLegacySolrClient;
import org.apache.solr.client.solrj.impl.CloudSolrClient;
import org.apache.solr.client.solrj.request.CollectionAdminRequest;
import org.apache.solr.common.cloud.DocCollection;
import org.apache.solr.common.cloud.Replica;
import org.apache.solr.common.util.SimpleOrderedMap;
import org.apache.solr.common.util.StrUtils;
import org.apache.solr.common.util.Utils;
import org.eclipse.jetty.client.BytesRequestContent;
import org.eclipse.jetty.client.HttpClient;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
Expand Down Expand Up @@ -99,8 +92,7 @@ public void testAllNodes() throws Exception {
DocCollection collection = cloudClient.getClusterState().getCollection(coll);
log.debug("### Before balancing: {}", collection);

postDataAndGetResponse(
cluster.getSolrClient(), "/api/cluster/replicas/balance", SimpleOrderedMap.of());
postDataAndGetResponse("/api/cluster/replicas/balance", SimpleOrderedMap.of());

collection = cloudClient.getClusterState().getCollectionOrNull(coll, false);
log.debug("### After balancing: {}", collection);
Expand Down Expand Up @@ -146,7 +138,6 @@ public void testSomeNodes() throws Exception {
log.debug("### Before balancing: {}", collection);

postDataAndGetResponse(
cluster.getSolrClient(),
"/api/cluster/replicas/balance",
Utils.getReflectWriter(
new BalanceReplicasRequestBody(new HashSet<>(l.subList(1, 4)), true, null)));
Expand All @@ -162,31 +153,24 @@ public void testSomeNodes() throws Exception {
"A non-balanced node gained replicas during balancing", replicaNodes.contains(l.get(4)));
}

public Map<?, ?> postDataAndGetResponse(CloudSolrClient cloudClient, String uri, Object body)
throws IOException {
HttpEntityEnclosingRequestBase httpRequest = null;
HttpEntity entity;
String response = null;
Map<?, ?> m = null;
public Map<?, ?> postDataAndGetResponse(String uri, Object jsonBody) throws IOException {
String rspStr = null;

uri = cluster.getJettySolrRunners().get(0).getBaseUrl().toString().replace("/solr", "") + uri;
HttpClient httpClient = cluster.getRandomJetty(random()).getSolrClient().getHttpClient();
try {
httpRequest = new HttpPost(uri);

httpRequest.setEntity(new ByteArrayEntity(Utils.toJSON(body), ContentType.APPLICATION_JSON));
httpRequest.setHeader("Accept", "application/json");
entity =
((CloudLegacySolrClient) cloudClient).getHttpClient().execute(httpRequest).getEntity();
try {
response = EntityUtils.toString(entity, UTF_8);
m = (Map<?, ?>) Utils.fromJSONString(response);
} catch (JSONParser.ParseException e) {
log.error("err response: {}", response);
throw new AssertionError(e);
}
} finally {
httpRequest.releaseConnection();
var rsp =
httpClient
.POST(uri)
.body(new BytesRequestContent("application/json", Utils.toJSON(jsonBody)))
.send();
rspStr = rsp.getContentAsString();
return (Map<?, ?>) Utils.fromJSONString(rspStr);
} catch (JSONParser.ParseException e) {
log.error("err response: {}", rspStr);
throw new AssertionError(e);
} catch (Exception e) {
throw new IOException(e);
}
return m;
}
}
Loading