This is an automated email from the ASF dual-hosted git repository. gerlowskija pushed a commit to branch SOLR-16825-migrate-definitions-to-api-module-pt4 in repository https://gitbox.apache.org/repos/asf/solr.git
commit 0ebd7ea84e0cbfda4f4a6a40d14fc3f895038295 Author: Jason Gerlowski <[email protected]> AuthorDate: Wed Sep 27 09:53:01 2023 -0400 Migrade create-shard to 'api' module --- .../solr/client/api/endpoint/CreateShardApi.java | 37 +++++++ .../client/api/model/CreateShardRequestBody.java | 50 ++++++++++ .../solr/handler/admin/CollectionsHandler.java | 6 +- .../api/{CreateShardAPI.java => CreateShard.java} | 110 ++++++--------------- .../solr/handler/admin/api/CreateShardAPITest.java | 27 ++--- 5 files changed, 135 insertions(+), 95 deletions(-) diff --git a/solr/api/src/java/org/apache/solr/client/api/endpoint/CreateShardApi.java b/solr/api/src/java/org/apache/solr/client/api/endpoint/CreateShardApi.java new file mode 100644 index 00000000000..0bd30763811 --- /dev/null +++ b/solr/api/src/java/org/apache/solr/client/api/endpoint/CreateShardApi.java @@ -0,0 +1,37 @@ +/* + * 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.client.api.endpoint; + +import io.swagger.v3.oas.annotations.Operation; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import org.apache.solr.client.api.model.CreateShardRequestBody; +import org.apache.solr.client.api.model.SubResponseAccumulatingJerseyResponse; + +/** V2 API definition for creating a new shard in a collection. */ +@Path("/collections/{collectionName}/shards") +public interface CreateShardApi { + + @POST + @Operation( + summary = "Create a new shard in an existing collection", + tags = {"shards"}) + SubResponseAccumulatingJerseyResponse createShard( + @PathParam("collectionName") String collectionName, CreateShardRequestBody requestBody) + throws Exception; +} diff --git a/solr/api/src/java/org/apache/solr/client/api/model/CreateShardRequestBody.java b/solr/api/src/java/org/apache/solr/client/api/model/CreateShardRequestBody.java new file mode 100644 index 00000000000..ea871998cca --- /dev/null +++ b/solr/api/src/java/org/apache/solr/client/api/model/CreateShardRequestBody.java @@ -0,0 +1,50 @@ +/* + * 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.client.api.model; + +import com.fasterxml.jackson.annotation.JsonProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import java.util.List; +import java.util.Map; + +public class CreateShardRequestBody { + @Schema(name = "shardName") + @JsonProperty("name") + public String shardName; + + @JsonProperty public Integer replicationFactor; + + @JsonProperty public Integer nrtReplicas; + + @JsonProperty public Integer tlogReplicas; + + @JsonProperty public Integer pullReplicas; + + @JsonProperty("createReplicas") + public Boolean createReplicas; + + @JsonProperty("nodeSet") + public List<String> nodeSet; + + @JsonProperty public Boolean waitForFinalState; + + @JsonProperty public Boolean followAliases; + + @JsonProperty public String async; + + @JsonProperty public Map<String, String> properties; +} diff --git a/solr/core/src/java/org/apache/solr/handler/admin/CollectionsHandler.java b/solr/core/src/java/org/apache/solr/handler/admin/CollectionsHandler.java index 5231393ea4e..5b0b97f7f07 100644 --- a/solr/core/src/java/org/apache/solr/handler/admin/CollectionsHandler.java +++ b/solr/core/src/java/org/apache/solr/handler/admin/CollectionsHandler.java @@ -176,7 +176,7 @@ import org.apache.solr.handler.admin.api.CreateCollectionAPI; import org.apache.solr.handler.admin.api.CreateCollectionBackupAPI; import org.apache.solr.handler.admin.api.CreateCollectionSnapshotAPI; import org.apache.solr.handler.admin.api.CreateReplica; -import org.apache.solr.handler.admin.api.CreateShardAPI; +import org.apache.solr.handler.admin.api.CreateShard; import org.apache.solr.handler.admin.api.DeleteAlias; import org.apache.solr.handler.admin.api.DeleteCollection; import org.apache.solr.handler.admin.api.DeleteCollectionBackup; @@ -729,7 +729,7 @@ public class CollectionsHandler extends RequestHandlerBase implements Permission CREATESHARD_OP( CREATESHARD, (req, rsp, h) -> { - CreateShardAPI.invokeFromV1Params(h.coreContainer, req, rsp); + CreateShard.invokeFromV1Params(h.coreContainer, req, rsp); return null; }), DELETEREPLICA_OP( @@ -1367,7 +1367,7 @@ public class CollectionsHandler extends RequestHandlerBase implements Permission CreateAliasAPI.class, CreateCollectionAPI.class, CreateCollectionBackupAPI.class, - CreateShardAPI.class, + CreateShard.class, DeleteAlias.class, DeleteCollectionBackup.class, DeleteCollection.class, diff --git a/solr/core/src/java/org/apache/solr/handler/admin/api/CreateShardAPI.java b/solr/core/src/java/org/apache/solr/handler/admin/api/CreateShard.java similarity index 69% rename from solr/core/src/java/org/apache/solr/handler/admin/api/CreateShardAPI.java rename to solr/core/src/java/org/apache/solr/handler/admin/api/CreateShard.java index 41be6e672d7..ea07ce19191 100644 --- a/solr/core/src/java/org/apache/solr/handler/admin/api/CreateShardAPI.java +++ b/solr/core/src/java/org/apache/solr/handler/admin/api/CreateShard.java @@ -17,7 +17,6 @@ package org.apache.solr.handler.admin.api; -import static org.apache.solr.client.solrj.impl.BinaryResponseParser.BINARY_CONTENT_TYPE_V2; import static org.apache.solr.cloud.Overseer.QUEUE_OPERATION; import static org.apache.solr.cloud.api.collections.CollectionHandlingUtils.CREATE_NODE_SET; import static org.apache.solr.common.cloud.ZkStateReader.COLLECTION_PROP; @@ -37,16 +36,12 @@ import static org.apache.solr.common.params.CommonParams.NAME; import static org.apache.solr.handler.admin.api.CreateCollectionAPI.copyPrefixedPropertiesWithoutPrefix; import static org.apache.solr.security.PermissionNameProvider.Name.COLL_EDIT_PERM; -import com.fasterxml.jackson.annotation.JsonProperty; import java.util.Arrays; import java.util.HashMap; -import java.util.List; import java.util.Map; import javax.inject.Inject; -import javax.ws.rs.POST; -import javax.ws.rs.Path; -import javax.ws.rs.PathParam; -import javax.ws.rs.Produces; +import org.apache.solr.client.api.endpoint.CreateShardApi; +import org.apache.solr.client.api.model.CreateShardRequestBody; import org.apache.solr.client.api.model.SubResponseAccumulatingJerseyResponse; import org.apache.solr.client.solrj.util.SolrIdentifierValidator; import org.apache.solr.common.SolrException; @@ -58,7 +53,6 @@ import org.apache.solr.common.params.CollectionParams; import org.apache.solr.common.params.SolrParams; import org.apache.solr.core.CoreContainer; import org.apache.solr.handler.api.V2ApiUtils; -import org.apache.solr.jersey.JacksonReflectMapWriter; import org.apache.solr.jersey.PermissionName; import org.apache.solr.request.SolrQueryRequest; import org.apache.solr.response.SolrQueryResponse; @@ -69,23 +63,19 @@ import org.apache.solr.response.SolrQueryResponse; * <p>This API (POST /v2/collections/collectionName/shards {...}) is analogous to the v1 * /admin/collections?action=CREATESHARD command. */ -@Path("/collections/{collectionName}/shards") -public class CreateShardAPI extends AdminAPIBase { +public class CreateShard extends AdminAPIBase implements CreateShardApi { @Inject - public CreateShardAPI( + public CreateShard( CoreContainer coreContainer, SolrQueryRequest solrQueryRequest, SolrQueryResponse solrQueryResponse) { super(coreContainer, solrQueryRequest, solrQueryResponse); } - @POST - @Produces({"application/json", "application/xml", BINARY_CONTENT_TYPE_V2}) @PermissionName(COLL_EDIT_PERM) public SubResponseAccumulatingJerseyResponse createShard( - @PathParam("collectionName") String collectionName, CreateShardRequestBody requestBody) - throws Exception { + String collectionName, CreateShardRequestBody requestBody) throws Exception { final var response = instantiateJerseyResponse(SubResponseAccumulatingJerseyResponse.class); if (requestBody == null) { throw new SolrException( @@ -101,71 +91,34 @@ public class CreateShardAPI extends AdminAPIBase { final ZkNodeProps remoteMessage = createRemoteMessage(resolvedCollectionName, requestBody); submitRemoteMessageAndHandleResponse( - response, - CollectionParams.CollectionAction.CREATESHARD, - remoteMessage, - requestBody.asyncId); + response, CollectionParams.CollectionAction.CREATESHARD, remoteMessage, requestBody.async); return response; } - public static class CreateShardRequestBody implements JacksonReflectMapWriter { - @JsonProperty(NAME) - public String shardName; - - @JsonProperty(REPLICATION_FACTOR) - public Integer replicationFactor; - - @JsonProperty(NRT_REPLICAS) - public Integer nrtReplicas; - - @JsonProperty(TLOG_REPLICAS) - public Integer tlogReplicas; - - @JsonProperty(PULL_REPLICAS) - public Integer pullReplicas; - - @JsonProperty("createReplicas") - public Boolean createReplicas; - - @JsonProperty("nodeSet") - public List<String> nodeSet; - - @JsonProperty(WAIT_FOR_FINAL_STATE) - public Boolean waitForFinalState; - - @JsonProperty(FOLLOW_ALIASES) - public Boolean followAliases; - - @JsonProperty(ASYNC) - public String asyncId; - - @JsonProperty public Map<String, String> properties; - - public static CreateShardRequestBody fromV1Params(SolrParams params) { - params.required().check(COLLECTION, SHARD); - - final var requestBody = new CreateShardRequestBody(); - requestBody.shardName = params.get(SHARD); - requestBody.replicationFactor = params.getInt(REPLICATION_FACTOR); - requestBody.nrtReplicas = params.getInt(NRT_REPLICAS); - requestBody.tlogReplicas = params.getInt(TLOG_REPLICAS); - requestBody.pullReplicas = params.getInt(PULL_REPLICAS); - if (params.get(CREATE_NODE_SET_PARAM) != null) { - final String nodeSetStr = params.get(CREATE_NODE_SET_PARAM); - if ("EMPTY".equals(nodeSetStr)) { - requestBody.createReplicas = false; - } else { - requestBody.nodeSet = Arrays.asList(nodeSetStr.split(",")); - } + public static CreateShardRequestBody createRequestBodyFromV1Params(SolrParams params) { + params.required().check(COLLECTION, SHARD); + + final var requestBody = new CreateShardRequestBody(); + requestBody.shardName = params.get(SHARD); + requestBody.replicationFactor = params.getInt(REPLICATION_FACTOR); + requestBody.nrtReplicas = params.getInt(NRT_REPLICAS); + requestBody.tlogReplicas = params.getInt(TLOG_REPLICAS); + requestBody.pullReplicas = params.getInt(PULL_REPLICAS); + if (params.get(CREATE_NODE_SET_PARAM) != null) { + final String nodeSetStr = params.get(CREATE_NODE_SET_PARAM); + if ("EMPTY".equals(nodeSetStr)) { + requestBody.createReplicas = false; + } else { + requestBody.nodeSet = Arrays.asList(nodeSetStr.split(",")); } - requestBody.waitForFinalState = params.getBool(WAIT_FOR_FINAL_STATE); - requestBody.followAliases = params.getBool(FOLLOW_ALIASES); - requestBody.asyncId = params.get(ASYNC); - requestBody.properties = - copyPrefixedPropertiesWithoutPrefix(params, new HashMap<>(), PROPERTY_PREFIX); - - return requestBody; } + requestBody.waitForFinalState = params.getBool(WAIT_FOR_FINAL_STATE); + requestBody.followAliases = params.getBool(FOLLOW_ALIASES); + requestBody.async = params.get(ASYNC); + requestBody.properties = + copyPrefixedPropertiesWithoutPrefix(params, new HashMap<>(), PROPERTY_PREFIX); + + return requestBody; } public static void invokeFromV1Params( @@ -173,9 +126,8 @@ public class CreateShardAPI extends AdminAPIBase { SolrQueryRequest solrQueryRequest, SolrQueryResponse solrQueryResponse) throws Exception { - final var requestBody = CreateShardRequestBody.fromV1Params(solrQueryRequest.getParams()); - final var createShardApi = - new CreateShardAPI(coreContainer, solrQueryRequest, solrQueryResponse); + final var requestBody = CreateShard.createRequestBodyFromV1Params(solrQueryRequest.getParams()); + final var createShardApi = new CreateShard(coreContainer, solrQueryRequest, solrQueryResponse); final var response = createShardApi.createShard(solrQueryRequest.getParams().get(COLLECTION), requestBody); V2ApiUtils.squashIntoSolrResponseWithoutHeader(solrQueryResponse, response); @@ -201,7 +153,7 @@ public class CreateShardAPI extends AdminAPIBase { insertIfNotNull(remoteMessage, PULL_REPLICAS, requestBody.pullReplicas); insertIfNotNull(remoteMessage, WAIT_FOR_FINAL_STATE, requestBody.waitForFinalState); insertIfNotNull(remoteMessage, FOLLOW_ALIASES, requestBody.followAliases); - insertIfNotNull(remoteMessage, ASYNC, requestBody.asyncId); + insertIfNotNull(remoteMessage, ASYNC, requestBody.async); if (requestBody.properties != null) { requestBody diff --git a/solr/core/src/test/org/apache/solr/handler/admin/api/CreateShardAPITest.java b/solr/core/src/test/org/apache/solr/handler/admin/api/CreateShardAPITest.java index 07b71d8a805..bb89fd326b5 100644 --- a/solr/core/src/test/org/apache/solr/handler/admin/api/CreateShardAPITest.java +++ b/solr/core/src/test/org/apache/solr/handler/admin/api/CreateShardAPITest.java @@ -33,12 +33,13 @@ import static org.hamcrest.Matchers.containsString; import java.util.List; import java.util.Map; import org.apache.solr.SolrTestCaseJ4; +import org.apache.solr.client.api.model.CreateShardRequestBody; import org.apache.solr.common.SolrException; import org.apache.solr.common.params.ModifiableSolrParams; import org.hamcrest.MatcherAssert; import org.junit.Test; -/** Unit tests for {@link CreateShardAPI} */ +/** Unit tests for {@link CreateShard} */ public class CreateShardAPITest extends SolrTestCaseJ4 { @Test @@ -47,7 +48,7 @@ public class CreateShardAPITest extends SolrTestCaseJ4 { expectThrows( SolrException.class, () -> { - final var api = new CreateShardAPI(null, null, null); + final var api = new CreateShard(null, null, null); api.createShard("someCollName", null); }); @@ -57,13 +58,13 @@ public class CreateShardAPITest extends SolrTestCaseJ4 { @Test public void testReportsErrorIfCollectionNameMissing() { - final var requestBody = new CreateShardAPI.CreateShardRequestBody(); + final var requestBody = new CreateShardRequestBody(); requestBody.shardName = "someShardName"; final SolrException thrown = expectThrows( SolrException.class, () -> { - final var api = new CreateShardAPI(null, null, null); + final var api = new CreateShard(null, null, null); api.createShard(null, requestBody); }); @@ -73,13 +74,13 @@ public class CreateShardAPITest extends SolrTestCaseJ4 { @Test public void testReportsErrorIfShardNameMissing() { - final var requestBody = new CreateShardAPI.CreateShardRequestBody(); + final var requestBody = new CreateShardRequestBody(); requestBody.shardName = null; final SolrException thrown = expectThrows( SolrException.class, () -> { - final var api = new CreateShardAPI(null, null, null); + final var api = new CreateShard(null, null, null); api.createShard("someCollectionName", requestBody); }); @@ -89,13 +90,13 @@ public class CreateShardAPITest extends SolrTestCaseJ4 { @Test public void testReportsErrorIfShardNameIsInvalid() { - final var requestBody = new CreateShardAPI.CreateShardRequestBody(); + final var requestBody = new CreateShardRequestBody(); requestBody.shardName = "invalid$shard@name"; final SolrException thrown = expectThrows( SolrException.class, () -> { - final var api = new CreateShardAPI(null, null, null); + final var api = new CreateShard(null, null, null); api.createShard("someCollectionName", requestBody); }); @@ -106,7 +107,7 @@ public class CreateShardAPITest extends SolrTestCaseJ4 { @Test public void testCreateRemoteMessageAllProperties() { - final var requestBody = new CreateShardAPI.CreateShardRequestBody(); + final var requestBody = new CreateShardRequestBody(); requestBody.shardName = "someShardName"; requestBody.replicationFactor = 123; requestBody.nrtReplicas = 123; @@ -116,11 +117,11 @@ public class CreateShardAPITest extends SolrTestCaseJ4 { requestBody.nodeSet = List.of("node1", "node2"); requestBody.waitForFinalState = true; requestBody.followAliases = true; - requestBody.asyncId = "someAsyncId"; + requestBody.async = "someAsyncId"; requestBody.properties = Map.of("propName1", "propVal1", "propName2", "propVal2"); final var remoteMessage = - CreateShardAPI.createRemoteMessage("someCollectionName", requestBody).getProperties(); + CreateShard.createRemoteMessage("someCollectionName", requestBody).getProperties(); assertEquals(13, remoteMessage.size()); assertEquals("createshard", remoteMessage.get(QUEUE_OPERATION)); @@ -154,7 +155,7 @@ public class CreateShardAPITest extends SolrTestCaseJ4 { v1Params.add("property.propName1", "propVal1"); v1Params.add("property.propName2", "propVal2"); - final var requestBody = CreateShardAPI.CreateShardRequestBody.fromV1Params(v1Params); + final var requestBody = CreateShard.createRequestBodyFromV1Params(v1Params); assertEquals("someShardName", requestBody.shardName); assertEquals(Integer.valueOf(123), requestBody.replicationFactor); @@ -165,7 +166,7 @@ public class CreateShardAPITest extends SolrTestCaseJ4 { assertEquals(List.of("node1", "node2"), requestBody.nodeSet); assertEquals(Boolean.TRUE, requestBody.waitForFinalState); assertEquals(Boolean.TRUE, requestBody.followAliases); - assertEquals("someAsyncId", requestBody.asyncId); + assertEquals("someAsyncId", requestBody.async); assertEquals("propVal1", requestBody.properties.get("propName1")); assertEquals("propVal2", requestBody.properties.get("propName2")); }
