You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@solr.apache.org by ge...@apache.org on 2023/09/27 17:40:15 UTC

[solr] 03/06: Migrade create-shard to 'api' module

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 <ge...@apache.org>
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"));
   }