This is an automated email from the ASF dual-hosted git repository. gerlowskija pushed a commit to branch branch_9x in repository https://gitbox.apache.org/repos/asf/solr.git
commit 058f15be47e7e55f22b319767dffd653767cf683 Author: Jason Gerlowski <[email protected]> AuthorDate: Fri Oct 6 10:48:06 2023 -0400 SOLR-16825: Migrate v2 definitions to 'api' module, pt 5 (#1974) This commit covers the collection-prop, core-snapshot, migrate-replicas, reload-core, and restore-core APIs. Extracting annotated interfaces for these APIs includes them in the SolrRequest- generation we now do in SolrJ --- .../client/api/endpoint/CollectionPropertyApi.java | 47 ++++++++ .../solr/client/api/endpoint/CoreSnapshotApi.java | 79 ++++++++++++ .../client/api/endpoint/MigrateReplicasApi.java | 37 ++++++ .../solr/client/api/endpoint/ReloadCoreApi.java | 44 +++++++ .../solr/client/api/endpoint/RestoreCoreApi.java | 40 ++++++ .../apache/solr/client/api/model/Constants.java | 7 ++ .../api/model/CreateCoreSnapshotResponse.java | 45 +++++++ .../client/api/model/DeleteSnapshotResponse.java | 32 +++++ .../api/model/ListCoreSnapshotsResponse.java | 27 +++++ .../api/model/MigrateReplicasRequestBody.java | 56 +++++++++ .../client/api/model/ReloadCoreRequestBody.java | 26 ++++ .../client/api/model/RestoreCoreRequestBody.java | 36 ++++++ .../solr/client/api/model/SnapshotInformation.java | 41 +++++++ .../model/UpdateCollectionPropertyRequestBody.java | 30 +++++ .../solr/core/snapshots/SolrSnapshotManager.java | 4 +- .../solr/handler/admin/CollectionsHandler.java | 17 ++- .../solr/handler/admin/CoreAdminHandler.java | 12 +- .../solr/handler/admin/CoreAdminOperation.java | 21 ++-- .../solr/handler/admin/CreateSnapshotOp.java | 9 +- .../solr/handler/admin/DeleteSnapshotOp.java | 9 +- .../apache/solr/handler/admin/RestoreCoreOp.java | 13 +- ...ionPropertyAPI.java => CollectionProperty.java} | 42 ++----- .../{CoreSnapshotAPI.java => CoreSnapshot.java} | 134 +++------------------ ...igrateReplicasAPI.java => MigrateReplicas.java} | 60 +-------- .../api/{ReloadCoreAPI.java => ReloadCore.java} | 35 ++---- .../api/{RestoreCoreAPI.java => RestoreCore.java} | 63 +++------- .../org/apache/solr/cloud/MigrateReplicasTest.java | 18 +-- .../test/org/apache/solr/core/PluginBagTest.java | 4 +- .../handler/admin/api/CoreSnapshotAPITest.java | 16 +-- .../handler/admin/api/MigrateReplicasAPITest.java | 23 ++-- .../solr/handler/admin/api/ReloadCoreAPITest.java | 12 +- 31 files changed, 687 insertions(+), 352 deletions(-) diff --git a/solr/api/src/java/org/apache/solr/client/api/endpoint/CollectionPropertyApi.java b/solr/api/src/java/org/apache/solr/client/api/endpoint/CollectionPropertyApi.java new file mode 100644 index 00000000000..ed26ea443cc --- /dev/null +++ b/solr/api/src/java/org/apache/solr/client/api/endpoint/CollectionPropertyApi.java @@ -0,0 +1,47 @@ +/* + * 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.DELETE; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import org.apache.solr.client.api.model.SolrJerseyResponse; +import org.apache.solr.client.api.model.UpdateCollectionPropertyRequestBody; + +/** V2 API definitions for modifying collection-level properties. */ +@Path("/collections/{collName}/properties/{propName}") +public interface CollectionPropertyApi { + @PUT + @Operation( + summary = "Create or update a collection property", + tags = {"collection-properties"}) + SolrJerseyResponse createOrUpdateCollectionProperty( + @PathParam("collName") String collName, + @PathParam("propName") String propName, + UpdateCollectionPropertyRequestBody requestBody) + throws Exception; + + @DELETE + @Operation( + summary = "Delete the specified collection property from the collection", + tags = {"collection-properties"}) + SolrJerseyResponse deleteCollectionProperty( + @PathParam("collName") String collName, @PathParam("propName") String propName) + throws Exception; +} diff --git a/solr/api/src/java/org/apache/solr/client/api/endpoint/CoreSnapshotApi.java b/solr/api/src/java/org/apache/solr/client/api/endpoint/CoreSnapshotApi.java new file mode 100644 index 00000000000..8d19211da16 --- /dev/null +++ b/solr/api/src/java/org/apache/solr/client/api/endpoint/CoreSnapshotApi.java @@ -0,0 +1,79 @@ +/* + * 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 io.swagger.v3.oas.annotations.Parameter; +import javax.ws.rs.DELETE; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.QueryParam; +import org.apache.solr.client.api.model.CreateCoreSnapshotResponse; +import org.apache.solr.client.api.model.DeleteSnapshotResponse; +import org.apache.solr.client.api.model.ListCoreSnapshotsResponse; + +/** V2 API definitions for Creating, Listing, and Deleting Core Snapshots. */ +@Path("/cores/{coreName}/snapshots") +public interface CoreSnapshotApi { + @POST + @Path("/{snapshotName}") + @Operation( + summary = "Create a new snapshot of the specified core.", + tags = {"core-snapshots"}) + CreateCoreSnapshotResponse createSnapshot( + @Parameter(description = "The name of the core to snapshot.", required = true) + @PathParam("coreName") + String coreName, + @Parameter(description = "The name to associate with the core snapshot.", required = true) + @PathParam("snapshotName") + String snapshotName, + @Parameter(description = "The id to associate with the async task.") @QueryParam("async") + String taskId) + throws Exception; + + @GET + @Operation( + summary = "List existing snapshots for the specified core.", + tags = {"core-snapshots"}) + ListCoreSnapshotsResponse listSnapshots( + @Parameter( + description = "The name of the core for which to retrieve snapshots.", + required = true) + @PathParam("coreName") + String coreName) + throws Exception; + + @DELETE + @Path("/{snapshotName}") + @Operation( + summary = "Delete a single snapshot from the specified core.", + tags = {"core-snapshots"}) + DeleteSnapshotResponse deleteSnapshot( + @Parameter( + description = "The name of the core for which to delete a snapshot.", + required = true) + @PathParam("coreName") + String coreName, + @Parameter(description = "The name of the core snapshot to delete.", required = true) + @PathParam("snapshotName") + String snapshotName, + @Parameter(description = "The id to associate with the async task.") @QueryParam("async") + String taskId) + throws Exception; +} diff --git a/solr/api/src/java/org/apache/solr/client/api/endpoint/MigrateReplicasApi.java b/solr/api/src/java/org/apache/solr/client/api/endpoint/MigrateReplicasApi.java new file mode 100644 index 00000000000..82e8110b697 --- /dev/null +++ b/solr/api/src/java/org/apache/solr/client/api/endpoint/MigrateReplicasApi.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 io.swagger.v3.oas.annotations.parameters.RequestBody; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import org.apache.solr.client.api.model.MigrateReplicasRequestBody; +import org.apache.solr.client.api.model.SolrJerseyResponse; + +/** V2 API definition for migrating replicas from a set of nodes to another set of nodes. */ +@Path("cluster/replicas/migrate") +public interface MigrateReplicasApi { + @POST + @Operation( + summary = "Migrate Replicas from a given set of nodes.", + tags = {"cluster"}) + SolrJerseyResponse migrateReplicas( + @RequestBody(description = "Contains user provided parameters", required = true) + MigrateReplicasRequestBody requestBody) + throws Exception; +} diff --git a/solr/api/src/java/org/apache/solr/client/api/endpoint/ReloadCoreApi.java b/solr/api/src/java/org/apache/solr/client/api/endpoint/ReloadCoreApi.java new file mode 100644 index 00000000000..8a7cced7aa1 --- /dev/null +++ b/solr/api/src/java/org/apache/solr/client/api/endpoint/ReloadCoreApi.java @@ -0,0 +1,44 @@ +/* + * 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 io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.parameters.RequestBody; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import org.apache.solr.client.api.model.ReloadCoreRequestBody; +import org.apache.solr.client.api.model.SolrJerseyResponse; + +/** V2 API definition for reloading an individual core. */ +@Path("/cores/{coreName}/reload") +public interface ReloadCoreApi { + + @POST + @Operation( + summary = "Reload the specified core.", + tags = {"cores"}) + SolrJerseyResponse reloadCore( + @Parameter(description = "The name of the core to reload.", required = true) + @PathParam("coreName") + String coreName, + @Schema(description = "Additional parameters for reloading the core") @RequestBody + ReloadCoreRequestBody reloadCoreRequestBody) + throws Exception; +} diff --git a/solr/api/src/java/org/apache/solr/client/api/endpoint/RestoreCoreApi.java b/solr/api/src/java/org/apache/solr/client/api/endpoint/RestoreCoreApi.java new file mode 100644 index 00000000000..3f2264a6562 --- /dev/null +++ b/solr/api/src/java/org/apache/solr/client/api/endpoint/RestoreCoreApi.java @@ -0,0 +1,40 @@ +/* + * 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 io.swagger.v3.oas.annotations.Parameter; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import org.apache.solr.client.api.model.RestoreCoreRequestBody; +import org.apache.solr.client.api.model.SolrJerseyResponse; + +/** V2 API definition for restoring a previously taken backup to a core */ +@Path("/cores/{coreName}/restore") +public interface RestoreCoreApi { + + @POST + @Operation( + summary = "Restore a previously-taken backup to the specified core", + tags = {"cores"}) + SolrJerseyResponse restoreCore( + @Parameter(description = "The name of the core to be restored") @PathParam("coreName") + String coreName, + RestoreCoreRequestBody requestBody) + throws Exception; +} diff --git a/solr/api/src/java/org/apache/solr/client/api/model/Constants.java b/solr/api/src/java/org/apache/solr/client/api/model/Constants.java index 0992c2c3a17..798e09d5e26 100644 --- a/solr/api/src/java/org/apache/solr/client/api/model/Constants.java +++ b/solr/api/src/java/org/apache/solr/client/api/model/Constants.java @@ -19,6 +19,9 @@ package org.apache.solr.client.api.model; public class Constants { + // TODO Most of these constants are also defined in various constant files in 'solrj' - we should + // move those into the 'api' module and eliminate this file. + private Constants() { /* Private ctor prevents instantiation */ } @@ -51,4 +54,8 @@ public class Constants { /** The name of the config set to be used for a collection */ public static final String COLL_CONF = "collection.configName"; + + public static final String SNAPSHOT_GENERATION_NUM = "generation"; + + public static final String SNAPSHOT_NAME = "snapshotName"; } diff --git a/solr/api/src/java/org/apache/solr/client/api/model/CreateCoreSnapshotResponse.java b/solr/api/src/java/org/apache/solr/client/api/model/CreateCoreSnapshotResponse.java new file mode 100644 index 00000000000..9f633a8830b --- /dev/null +++ b/solr/api/src/java/org/apache/solr/client/api/model/CreateCoreSnapshotResponse.java @@ -0,0 +1,45 @@ +/* + * 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 static org.apache.solr.client.api.model.Constants.SNAPSHOT_NAME; + +import com.fasterxml.jackson.annotation.JsonProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import java.util.Collection; + +public class CreateCoreSnapshotResponse extends SolrJerseyResponse { + @Schema(description = "The name of the core.") + @JsonProperty + public String core; + + @Schema(name = "commitName", description = "The name of the created snapshot.") + @JsonProperty(SNAPSHOT_NAME) + public String commitName; + + @Schema(description = "The path to the directory containing the index files.") + @JsonProperty + public String indexDirPath; + + @Schema(description = "The generation value for the created snapshot.") + @JsonProperty + public Long generation; + + @Schema(description = "The list of index filenames contained within the created snapshot.") + @JsonProperty + public Collection<String> files; +} diff --git a/solr/api/src/java/org/apache/solr/client/api/model/DeleteSnapshotResponse.java b/solr/api/src/java/org/apache/solr/client/api/model/DeleteSnapshotResponse.java new file mode 100644 index 00000000000..970387edc5e --- /dev/null +++ b/solr/api/src/java/org/apache/solr/client/api/model/DeleteSnapshotResponse.java @@ -0,0 +1,32 @@ +/* + * 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 static org.apache.solr.client.api.model.Constants.SNAPSHOT_NAME; + +import com.fasterxml.jackson.annotation.JsonProperty; +import io.swagger.v3.oas.annotations.media.Schema; + +public class DeleteSnapshotResponse extends SolrJerseyResponse { + @Schema(name = "coreName", description = "The name of the core.") + @JsonProperty("core") + public String coreName; + + @Schema(name = "commitName", description = "The name of the deleted snapshot.") + @JsonProperty(SNAPSHOT_NAME) + public String commitName; +} diff --git a/solr/api/src/java/org/apache/solr/client/api/model/ListCoreSnapshotsResponse.java b/solr/api/src/java/org/apache/solr/client/api/model/ListCoreSnapshotsResponse.java new file mode 100644 index 00000000000..0e6d87709ea --- /dev/null +++ b/solr/api/src/java/org/apache/solr/client/api/model/ListCoreSnapshotsResponse.java @@ -0,0 +1,27 @@ +/* + * 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.Map; + +public class ListCoreSnapshotsResponse extends SolrJerseyResponse { + @Schema(description = "The collection of snapshots found for the requested core.") + @JsonProperty + public Map<String, SnapshotInformation> snapshots; +} diff --git a/solr/api/src/java/org/apache/solr/client/api/model/MigrateReplicasRequestBody.java b/solr/api/src/java/org/apache/solr/client/api/model/MigrateReplicasRequestBody.java new file mode 100644 index 00000000000..8970d6b7c4d --- /dev/null +++ b/solr/api/src/java/org/apache/solr/client/api/model/MigrateReplicasRequestBody.java @@ -0,0 +1,56 @@ +/* + * 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.Set; + +public class MigrateReplicasRequestBody { + + public MigrateReplicasRequestBody() {} + + public MigrateReplicasRequestBody( + Set<String> sourceNodes, Set<String> targetNodes, Boolean waitForFinalState, String async) { + this.sourceNodes = sourceNodes; + this.targetNodes = targetNodes; + this.waitForFinalState = waitForFinalState; + this.async = async; + } + + @Schema(description = "The set of nodes which all replicas will be migrated off of.") + @JsonProperty(required = true) + public Set<String> sourceNodes; + + @Schema( + description = + "A set of nodes to migrate the replicas to. If this is not provided, then the API will use the live data nodes not in 'sourceNodes'.") + @JsonProperty + public Set<String> targetNodes; + + @Schema( + description = + "If true, the request will complete only when all affected replicas become active. " + + "If false, the API will return the status of the single action, which may be " + + "before the new replicas are online and active.") + @JsonProperty + public Boolean waitForFinalState = false; + + @Schema(description = "Request ID to track this action which will be processed asynchronously.") + @JsonProperty + public String async; +} diff --git a/solr/api/src/java/org/apache/solr/client/api/model/ReloadCoreRequestBody.java b/solr/api/src/java/org/apache/solr/client/api/model/ReloadCoreRequestBody.java new file mode 100644 index 00000000000..51b0d4bd761 --- /dev/null +++ b/solr/api/src/java/org/apache/solr/client/api/model/ReloadCoreRequestBody.java @@ -0,0 +1,26 @@ +/* + * 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; + +public class ReloadCoreRequestBody { + @Schema(description = "Request ID to track this action which will be processed asynchronously.") + @JsonProperty + public String async; +} diff --git a/solr/api/src/java/org/apache/solr/client/api/model/RestoreCoreRequestBody.java b/solr/api/src/java/org/apache/solr/client/api/model/RestoreCoreRequestBody.java new file mode 100644 index 00000000000..ca2a9f5cf98 --- /dev/null +++ b/solr/api/src/java/org/apache/solr/client/api/model/RestoreCoreRequestBody.java @@ -0,0 +1,36 @@ +/* + * 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 static org.apache.solr.client.api.model.Constants.BACKUP_REPOSITORY; + +import com.fasterxml.jackson.annotation.JsonProperty; +import io.swagger.v3.oas.annotations.media.Schema; + +public class RestoreCoreRequestBody { + @JsonProperty public String name; + + @JsonProperty public String shardBackupId; + + @Schema(name = "backupRepository") + @JsonProperty(BACKUP_REPOSITORY) + public String backupRepository; + + @JsonProperty public String location; + + @JsonProperty public String async; +} diff --git a/solr/api/src/java/org/apache/solr/client/api/model/SnapshotInformation.java b/solr/api/src/java/org/apache/solr/client/api/model/SnapshotInformation.java new file mode 100644 index 00000000000..31ec92d3045 --- /dev/null +++ b/solr/api/src/java/org/apache/solr/client/api/model/SnapshotInformation.java @@ -0,0 +1,41 @@ +/* + * 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 static org.apache.solr.client.api.model.Constants.SNAPSHOT_GENERATION_NUM; + +import com.fasterxml.jackson.annotation.JsonProperty; +import io.swagger.v3.oas.annotations.media.Schema; + +/** + * Contained in {@link ListCoreSnapshotsResponse}, this holds information for a given core's + * Snapshot + */ +public class SnapshotInformation { + @Schema(name = "generationNumber", description = "The generation value for the snapshot.") + @JsonProperty(SNAPSHOT_GENERATION_NUM) + public final long generationNumber; + + @Schema(description = "The path to the directory containing the index files.") + @JsonProperty + public final String indexDirPath; + + public SnapshotInformation(long generationNumber, String indexDirPath) { + this.generationNumber = generationNumber; + this.indexDirPath = indexDirPath; + } +} diff --git a/solr/api/src/java/org/apache/solr/client/api/model/UpdateCollectionPropertyRequestBody.java b/solr/api/src/java/org/apache/solr/client/api/model/UpdateCollectionPropertyRequestBody.java new file mode 100644 index 00000000000..73e6bd200dd --- /dev/null +++ b/solr/api/src/java/org/apache/solr/client/api/model/UpdateCollectionPropertyRequestBody.java @@ -0,0 +1,30 @@ +/* + * 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; + +public class UpdateCollectionPropertyRequestBody { + public UpdateCollectionPropertyRequestBody() {} + + public UpdateCollectionPropertyRequestBody(String value) { + this.value = value; + } + + @JsonProperty(required = true) + public String value; +} diff --git a/solr/core/src/java/org/apache/solr/core/snapshots/SolrSnapshotManager.java b/solr/core/src/java/org/apache/solr/core/snapshots/SolrSnapshotManager.java index dd475b03e6e..acdbd722717 100644 --- a/solr/core/src/java/org/apache/solr/core/snapshots/SolrSnapshotManager.java +++ b/solr/core/src/java/org/apache/solr/core/snapshots/SolrSnapshotManager.java @@ -16,6 +16,8 @@ */ package org.apache.solr.core.snapshots; +import static org.apache.solr.client.api.model.Constants.SNAPSHOT_GENERATION_NUM; + import java.io.IOException; import java.lang.invoke.MethodHandles; import java.util.ArrayList; @@ -49,7 +51,7 @@ public class SolrSnapshotManager { private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); public static final String INDEX_DIR_PATH = "indexDirPath"; - public static final String GENERATION_NUM = "generation"; + public static final String GENERATION_NUM = SNAPSHOT_GENERATION_NUM; public static final String SNAPSHOT_STATUS = "status"; public static final String CREATION_DATE = "creationDate"; public static final String SNAPSHOT_REPLICAS = "replicas"; 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 d91f4e1914b..0ed22f2f065 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 @@ -127,6 +127,7 @@ import org.apache.solr.client.api.model.InstallShardDataRequestBody; import org.apache.solr.client.api.model.ReplaceNodeRequestBody; import org.apache.solr.client.api.model.SolrJerseyResponse; import org.apache.solr.client.api.model.UpdateAliasPropertiesRequestBody; +import org.apache.solr.client.api.model.UpdateCollectionPropertyRequestBody; import org.apache.solr.client.solrj.SolrResponse; import org.apache.solr.client.solrj.request.CollectionAdminRequest; import org.apache.solr.client.solrj.response.RequestStatusState; @@ -170,7 +171,7 @@ import org.apache.solr.handler.admin.api.AdminAPIBase; import org.apache.solr.handler.admin.api.AliasProperty; import org.apache.solr.handler.admin.api.BalanceReplicas; import org.apache.solr.handler.admin.api.BalanceShardUniqueAPI; -import org.apache.solr.handler.admin.api.CollectionPropertyAPI; +import org.apache.solr.handler.admin.api.CollectionProperty; import org.apache.solr.handler.admin.api.CollectionStatusAPI; import org.apache.solr.handler.admin.api.CreateAliasAPI; import org.apache.solr.handler.admin.api.CreateCollection; @@ -193,7 +194,7 @@ import org.apache.solr.handler.admin.api.ListCollectionBackups; import org.apache.solr.handler.admin.api.ListCollectionSnapshotsAPI; import org.apache.solr.handler.admin.api.ListCollections; import org.apache.solr.handler.admin.api.MigrateDocsAPI; -import org.apache.solr.handler.admin.api.MigrateReplicasAPI; +import org.apache.solr.handler.admin.api.MigrateReplicas; import org.apache.solr.handler.admin.api.ModifyCollectionAPI; import org.apache.solr.handler.admin.api.MoveReplicaAPI; import org.apache.solr.handler.admin.api.RebalanceLeadersAPI; @@ -786,14 +787,12 @@ public class CollectionsHandler extends RequestHandlerBase implements Permission final String propName = req.getParams().required().get(PROPERTY_NAME); final String val = req.getParams().get(PROPERTY_VALUE); - final CollectionPropertyAPI setCollPropApi = - new CollectionPropertyAPI(h.coreContainer, req, rsp); + final CollectionProperty setCollPropApi = + new CollectionProperty(h.coreContainer, req, rsp); final SolrJerseyResponse setPropRsp = (val != null) ? setCollPropApi.createOrUpdateCollectionProperty( - collection, - propName, - new CollectionPropertyAPI.UpdateCollectionPropertyRequestBody(val)) + collection, propName, new UpdateCollectionPropertyRequestBody(val)) : setCollPropApi.deleteCollectionProperty(collection, propName); V2ApiUtils.squashIntoSolrResponseWithoutHeader(rsp, setPropRsp); return null; @@ -1381,11 +1380,11 @@ public class CollectionsHandler extends RequestHandlerBase implements Permission ReloadCollectionAPI.class, RenameCollection.class, ReplaceNode.class, - MigrateReplicasAPI.class, + MigrateReplicas.class, BalanceReplicas.class, RestoreCollectionAPI.class, SyncShard.class, - CollectionPropertyAPI.class, + CollectionProperty.class, DeleteNode.class, ListAliases.class, AliasProperty.class, diff --git a/solr/core/src/java/org/apache/solr/handler/admin/CoreAdminHandler.java b/solr/core/src/java/org/apache/solr/handler/admin/CoreAdminHandler.java index d9ece272f75..25af745db5b 100644 --- a/solr/core/src/java/org/apache/solr/handler/admin/CoreAdminHandler.java +++ b/solr/core/src/java/org/apache/solr/handler/admin/CoreAdminHandler.java @@ -56,21 +56,21 @@ import org.apache.solr.core.CoreDescriptor; import org.apache.solr.handler.RequestHandlerBase; import org.apache.solr.handler.admin.api.AllCoresStatusAPI; import org.apache.solr.handler.admin.api.BackupCoreAPI; -import org.apache.solr.handler.admin.api.CoreSnapshotAPI; +import org.apache.solr.handler.admin.api.CoreSnapshot; import org.apache.solr.handler.admin.api.CreateCoreAPI; import org.apache.solr.handler.admin.api.InstallCoreData; import org.apache.solr.handler.admin.api.MergeIndexesAPI; import org.apache.solr.handler.admin.api.OverseerOperationAPI; import org.apache.solr.handler.admin.api.PrepareCoreRecoveryAPI; import org.apache.solr.handler.admin.api.RejoinLeaderElectionAPI; -import org.apache.solr.handler.admin.api.ReloadCoreAPI; +import org.apache.solr.handler.admin.api.ReloadCore; import org.apache.solr.handler.admin.api.RenameCoreAPI; import org.apache.solr.handler.admin.api.RequestApplyCoreUpdatesAPI; import org.apache.solr.handler.admin.api.RequestBufferUpdatesAPI; import org.apache.solr.handler.admin.api.RequestCoreCommandStatusAPI; import org.apache.solr.handler.admin.api.RequestCoreRecoveryAPI; import org.apache.solr.handler.admin.api.RequestSyncShardAPI; -import org.apache.solr.handler.admin.api.RestoreCoreAPI; +import org.apache.solr.handler.admin.api.RestoreCore; import org.apache.solr.handler.admin.api.SingleCoreStatusAPI; import org.apache.solr.handler.admin.api.SplitCoreAPI; import org.apache.solr.handler.admin.api.SwapCoresAPI; @@ -402,11 +402,11 @@ public class CoreAdminHandler extends RequestHandlerBase implements PermissionNa @Override public Collection<Class<? extends JerseyResource>> getJerseyResources() { return List.of( - CoreSnapshotAPI.class, + CoreSnapshot.class, InstallCoreData.class, BackupCoreAPI.class, - RestoreCoreAPI.class, - ReloadCoreAPI.class); + RestoreCore.class, + ReloadCore.class); } public interface CoreAdminOp { diff --git a/solr/core/src/java/org/apache/solr/handler/admin/CoreAdminOperation.java b/solr/core/src/java/org/apache/solr/handler/admin/CoreAdminOperation.java index 987c79d376b..5c95a20a36f 100644 --- a/solr/core/src/java/org/apache/solr/handler/admin/CoreAdminOperation.java +++ b/solr/core/src/java/org/apache/solr/handler/admin/CoreAdminOperation.java @@ -58,6 +58,8 @@ import java.lang.invoke.MethodHandles; import java.nio.file.Path; import java.util.Locale; import java.util.Map; +import org.apache.solr.client.api.model.ListCoreSnapshotsResponse; +import org.apache.solr.client.api.model.ReloadCoreRequestBody; import org.apache.solr.client.api.model.SolrJerseyResponse; import org.apache.solr.cloud.ZkController; import org.apache.solr.common.SolrException; @@ -72,8 +74,8 @@ import org.apache.solr.core.CoreContainer; import org.apache.solr.core.CoreDescriptor; import org.apache.solr.core.SolrCore; import org.apache.solr.handler.admin.CoreAdminHandler.CoreAdminOp; -import org.apache.solr.handler.admin.api.CoreSnapshotAPI; -import org.apache.solr.handler.admin.api.ReloadCoreAPI; +import org.apache.solr.handler.admin.api.CoreSnapshot; +import org.apache.solr.handler.admin.api.ReloadCore; import org.apache.solr.handler.api.V2ApiUtils; import org.apache.solr.search.SolrIndexSearcher; import org.apache.solr.update.UpdateLog; @@ -135,11 +137,10 @@ public enum CoreAdminOperation implements CoreAdminOp { SolrParams params = it.req.getParams(); String cname = params.required().get(CoreAdminParams.CORE); - ReloadCoreAPI reloadCoreAPI = - new ReloadCoreAPI( + ReloadCore reloadCoreAPI = + new ReloadCore( it.req, it.rsp, it.handler.coreContainer, it.handler.getCoreAdminAsyncTracker()); - ReloadCoreAPI.ReloadCoreRequestBody reloadCoreRequestBody = - new ReloadCoreAPI.ReloadCoreRequestBody(); + ReloadCoreRequestBody reloadCoreRequestBody = new ReloadCoreRequestBody(); SolrJerseyResponse response = reloadCoreAPI.reloadCore(cname, reloadCoreRequestBody); V2ApiUtils.squashIntoSolrResponseWithoutHeader(it.rsp, response); }), @@ -293,12 +294,10 @@ public enum CoreAdminOperation implements CoreAdminOp { final String coreName = params.required().get(CoreAdminParams.CORE); final CoreContainer coreContainer = it.handler.getCoreContainer(); - final CoreSnapshotAPI coreSnapshotAPI = - new CoreSnapshotAPI( - it.req, it.rsp, coreContainer, it.handler.getCoreAdminAsyncTracker()); + final CoreSnapshot coreSnapshotAPI = + new CoreSnapshot(it.req, it.rsp, coreContainer, it.handler.getCoreAdminAsyncTracker()); - final CoreSnapshotAPI.ListSnapshotsResponse response = - coreSnapshotAPI.listSnapshots(coreName); + final ListCoreSnapshotsResponse response = coreSnapshotAPI.listSnapshots(coreName); V2ApiUtils.squashIntoSolrResponseWithoutHeader(it.rsp, response); }); diff --git a/solr/core/src/java/org/apache/solr/handler/admin/CreateSnapshotOp.java b/solr/core/src/java/org/apache/solr/handler/admin/CreateSnapshotOp.java index 6b27293c47f..4dea78c92b2 100644 --- a/solr/core/src/java/org/apache/solr/handler/admin/CreateSnapshotOp.java +++ b/solr/core/src/java/org/apache/solr/handler/admin/CreateSnapshotOp.java @@ -17,10 +17,11 @@ package org.apache.solr.handler.admin; +import org.apache.solr.client.api.model.CreateCoreSnapshotResponse; import org.apache.solr.common.params.CoreAdminParams; import org.apache.solr.common.params.SolrParams; import org.apache.solr.core.CoreContainer; -import org.apache.solr.handler.admin.api.CoreSnapshotAPI; +import org.apache.solr.handler.admin.api.CoreSnapshot; import org.apache.solr.handler.api.V2ApiUtils; class CreateSnapshotOp implements CoreAdminHandler.CoreAdminOp { @@ -31,10 +32,10 @@ class CreateSnapshotOp implements CoreAdminHandler.CoreAdminOp { final String commitName = params.required().get(CoreAdminParams.COMMIT_NAME); final CoreContainer coreContainer = it.handler.getCoreContainer(); - final CoreSnapshotAPI coreSnapshotAPI = - new CoreSnapshotAPI(it.req, it.rsp, coreContainer, it.handler.getCoreAdminAsyncTracker()); + final CoreSnapshot coreSnapshotAPI = + new CoreSnapshot(it.req, it.rsp, coreContainer, it.handler.getCoreAdminAsyncTracker()); - final CoreSnapshotAPI.CreateSnapshotResponse response = + final CreateCoreSnapshotResponse response = coreSnapshotAPI.createSnapshot(coreName, commitName, null); V2ApiUtils.squashIntoSolrResponseWithoutHeader(it.rsp, response); diff --git a/solr/core/src/java/org/apache/solr/handler/admin/DeleteSnapshotOp.java b/solr/core/src/java/org/apache/solr/handler/admin/DeleteSnapshotOp.java index a13bd6d5163..d49863ff7a4 100644 --- a/solr/core/src/java/org/apache/solr/handler/admin/DeleteSnapshotOp.java +++ b/solr/core/src/java/org/apache/solr/handler/admin/DeleteSnapshotOp.java @@ -17,10 +17,11 @@ package org.apache.solr.handler.admin; +import org.apache.solr.client.api.model.DeleteSnapshotResponse; import org.apache.solr.common.params.CoreAdminParams; import org.apache.solr.common.params.SolrParams; import org.apache.solr.core.CoreContainer; -import org.apache.solr.handler.admin.api.CoreSnapshotAPI; +import org.apache.solr.handler.admin.api.CoreSnapshot; import org.apache.solr.handler.api.V2ApiUtils; class DeleteSnapshotOp implements CoreAdminHandler.CoreAdminOp { @@ -32,10 +33,10 @@ class DeleteSnapshotOp implements CoreAdminHandler.CoreAdminOp { final String coreName = params.required().get(CoreAdminParams.CORE); final CoreContainer coreContainer = it.handler.getCoreContainer(); - final CoreSnapshotAPI coreSnapshotAPI = - new CoreSnapshotAPI(it.req, it.rsp, coreContainer, it.handler.getCoreAdminAsyncTracker()); + final CoreSnapshot coreSnapshotAPI = + new CoreSnapshot(it.req, it.rsp, coreContainer, it.handler.getCoreAdminAsyncTracker()); - final CoreSnapshotAPI.DeleteSnapshotResponse response = + final DeleteSnapshotResponse response = coreSnapshotAPI.deleteSnapshot(coreName, commitName, null); V2ApiUtils.squashIntoSolrResponseWithoutHeader(it.rsp, response); diff --git a/solr/core/src/java/org/apache/solr/handler/admin/RestoreCoreOp.java b/solr/core/src/java/org/apache/solr/handler/admin/RestoreCoreOp.java index c95af84d3d7..1bfc32f56e0 100644 --- a/solr/core/src/java/org/apache/solr/handler/admin/RestoreCoreOp.java +++ b/solr/core/src/java/org/apache/solr/handler/admin/RestoreCoreOp.java @@ -17,10 +17,11 @@ package org.apache.solr.handler.admin; +import org.apache.solr.client.api.model.RestoreCoreRequestBody; import org.apache.solr.common.params.CoreAdminParams; import org.apache.solr.common.params.SolrParams; import org.apache.solr.core.CoreContainer; -import org.apache.solr.handler.admin.api.RestoreCoreAPI; +import org.apache.solr.handler.admin.api.RestoreCore; import org.apache.solr.handler.api.V2ApiUtils; class RestoreCoreOp implements CoreAdminHandler.CoreAdminOp { @@ -34,23 +35,23 @@ class RestoreCoreOp implements CoreAdminHandler.CoreAdminOp { public void execute(CoreAdminHandler.CallInfo it) throws Exception { final SolrParams params = it.req.getParams(); String cname = params.required().get(CoreAdminParams.CORE); - final var requestBody = new RestoreCoreAPI.RestoreCoreRequestBody(); + final var requestBody = new RestoreCoreRequestBody(); // "async" param intentionally omitted because CoreAdminHandler has already processed requestBody.name = params.get(CoreAdminParams.NAME); requestBody.shardBackupId = params.get(CoreAdminParams.SHARD_BACKUP_ID); requestBody.location = params.get(CoreAdminParams.BACKUP_LOCATION); requestBody.backupRepository = params.get(CoreAdminParams.BACKUP_REPOSITORY); - requestBody.validate(); + RestoreCore.validateRequestBody(requestBody); final CoreContainer coreContainer = it.handler.getCoreContainer(); final var api = - new RestoreCoreAPI(coreContainer, it.req, it.rsp, it.handler.getCoreAdminAsyncTracker()); + new RestoreCore(coreContainer, it.req, it.rsp, it.handler.getCoreAdminAsyncTracker()); final var response = api.restoreCore(cname, requestBody); V2ApiUtils.squashIntoSolrResponseWithoutHeader(it.rsp, response); } - public static RestoreCoreAPI.RestoreCoreRequestBody createRequestFromV1Params(SolrParams params) { - final var requestBody = new RestoreCoreAPI.RestoreCoreRequestBody(); + public static RestoreCoreRequestBody createRequestFromV1Params(SolrParams params) { + final var requestBody = new RestoreCoreRequestBody(); // "async" param intentionally omitted because CoreAdminHandler has already processed requestBody.name = params.get(CoreAdminParams.NAME); requestBody.shardBackupId = params.get(CoreAdminParams.SHARD_BACKUP_ID); diff --git a/solr/core/src/java/org/apache/solr/handler/admin/api/CollectionPropertyAPI.java b/solr/core/src/java/org/apache/solr/handler/admin/api/CollectionProperty.java similarity index 68% rename from solr/core/src/java/org/apache/solr/handler/admin/api/CollectionPropertyAPI.java rename to solr/core/src/java/org/apache/solr/handler/admin/api/CollectionProperty.java index a50e2895d52..55da1ea0d53 100644 --- a/solr/core/src/java/org/apache/solr/handler/admin/api/CollectionPropertyAPI.java +++ b/solr/core/src/java/org/apache/solr/handler/admin/api/CollectionProperty.java @@ -17,49 +17,38 @@ 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.security.PermissionNameProvider.Name.COLL_EDIT_PERM; -import com.fasterxml.jackson.annotation.JsonProperty; import java.io.IOException; -import javax.ws.rs.DELETE; -import javax.ws.rs.PUT; -import javax.ws.rs.Path; -import javax.ws.rs.PathParam; -import javax.ws.rs.Produces; -import javax.ws.rs.core.MediaType; +import org.apache.solr.client.api.endpoint.CollectionPropertyApi; import org.apache.solr.client.api.model.SolrJerseyResponse; +import org.apache.solr.client.api.model.UpdateCollectionPropertyRequestBody; import org.apache.solr.common.SolrException; import org.apache.solr.common.cloud.CollectionProperties; import org.apache.solr.core.CoreContainer; -import org.apache.solr.jersey.JacksonReflectMapWriter; import org.apache.solr.jersey.PermissionName; import org.apache.solr.request.SolrQueryRequest; import org.apache.solr.response.SolrQueryResponse; /** - * V2 API for modifying collection-level properties. + * V2 API implementations for modifying collection-level properties. * * <p>These APIs (PUT and DELETE /api/collections/collName/properties/propName) are analogous to the * v1 /admin/collections?action=COLLECTIONPROP command. */ -@Path("/collections/{collName}/properties/{propName}") -public class CollectionPropertyAPI extends AdminAPIBase { +public class CollectionProperty extends AdminAPIBase implements CollectionPropertyApi { - public CollectionPropertyAPI( + public CollectionProperty( CoreContainer coreContainer, SolrQueryRequest solrQueryRequest, SolrQueryResponse solrQueryResponse) { super(coreContainer, solrQueryRequest, solrQueryResponse); } - @PUT + @Override @PermissionName(COLL_EDIT_PERM) - @Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, BINARY_CONTENT_TYPE_V2}) public SolrJerseyResponse createOrUpdateCollectionProperty( - @PathParam("collName") String collName, - @PathParam("propName") String propName, - UpdateCollectionPropertyRequestBody requestBody) + String collName, String propName, UpdateCollectionPropertyRequestBody requestBody) throws Exception { if (requestBody == null) { throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "Missing required request body"); @@ -70,11 +59,9 @@ public class CollectionPropertyAPI extends AdminAPIBase { return response; } - @DELETE + @Override @PermissionName(COLL_EDIT_PERM) - @Produces({"application/json", "application/xml", BINARY_CONTENT_TYPE_V2}) - public SolrJerseyResponse deleteCollectionProperty( - @PathParam("collName") String collName, @PathParam("propName") String propName) + public SolrJerseyResponse deleteCollectionProperty(String collName, String propName) throws Exception { final SolrJerseyResponse response = instantiateJerseyResponse(SolrJerseyResponse.class); recordCollectionForLogAndTracing(collName, solrQueryRequest); @@ -90,15 +77,4 @@ public class CollectionPropertyAPI extends AdminAPIBase { new CollectionProperties(coreContainer.getZkController().getZkClient()); cp.setCollectionProperty(resolvedCollection, propertyName, propertyValue); } - - public static class UpdateCollectionPropertyRequestBody implements JacksonReflectMapWriter { - public UpdateCollectionPropertyRequestBody() {} - - public UpdateCollectionPropertyRequestBody(String value) { - this.value = value; - } - - @JsonProperty(required = true) - public String value; - } } diff --git a/solr/core/src/java/org/apache/solr/handler/admin/api/CoreSnapshotAPI.java b/solr/core/src/java/org/apache/solr/handler/admin/api/CoreSnapshot.java similarity index 54% rename from solr/core/src/java/org/apache/solr/handler/admin/api/CoreSnapshotAPI.java rename to solr/core/src/java/org/apache/solr/handler/admin/api/CoreSnapshot.java index 634c1f105b9..d043894d128 100644 --- a/solr/core/src/java/org/apache/solr/handler/admin/api/CoreSnapshotAPI.java +++ b/solr/core/src/java/org/apache/solr/handler/admin/api/CoreSnapshot.java @@ -16,47 +16,35 @@ */ 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.security.PermissionNameProvider.Name.CORE_EDIT_PERM; import static org.apache.solr.security.PermissionNameProvider.Name.CORE_READ_PERM; -import com.fasterxml.jackson.annotation.JsonProperty; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.media.Schema; import java.io.IOException; -import java.util.Collection; import java.util.HashMap; import java.util.Map; import java.util.Optional; import javax.inject.Inject; -import javax.ws.rs.DELETE; -import javax.ws.rs.GET; -import javax.ws.rs.POST; -import javax.ws.rs.Path; -import javax.ws.rs.PathParam; -import javax.ws.rs.Produces; -import javax.ws.rs.QueryParam; import org.apache.lucene.index.IndexCommit; -import org.apache.solr.client.api.model.SolrJerseyResponse; +import org.apache.solr.client.api.endpoint.CoreSnapshotApi; +import org.apache.solr.client.api.model.CreateCoreSnapshotResponse; +import org.apache.solr.client.api.model.DeleteSnapshotResponse; +import org.apache.solr.client.api.model.ListCoreSnapshotsResponse; +import org.apache.solr.client.api.model.SnapshotInformation; import org.apache.solr.common.SolrException; -import org.apache.solr.common.params.CoreAdminParams; import org.apache.solr.core.CoreContainer; import org.apache.solr.core.IndexDeletionPolicyWrapper; import org.apache.solr.core.SolrCore; -import org.apache.solr.core.snapshots.SolrSnapshotManager; import org.apache.solr.core.snapshots.SolrSnapshotMetaDataManager; import org.apache.solr.handler.admin.CoreAdminHandler; -import org.apache.solr.jersey.JacksonReflectMapWriter; import org.apache.solr.jersey.PermissionName; import org.apache.solr.request.SolrQueryRequest; import org.apache.solr.response.SolrQueryResponse; /** V2 API for Creating, Listing, and Deleting Core Snapshots. */ -@Path("/cores/{coreName}/snapshots") -public class CoreSnapshotAPI extends CoreAdminAPIBase { +public class CoreSnapshot extends CoreAdminAPIBase implements CoreSnapshotApi { @Inject - public CoreSnapshotAPI( + public CoreSnapshot( SolrQueryRequest request, SolrQueryResponse response, CoreContainer coreContainer, @@ -65,21 +53,12 @@ public class CoreSnapshotAPI extends CoreAdminAPIBase { } /** This API is analogous to V1 (POST /solr/admin/cores?action=CREATESNAPSHOT) */ - @POST - @Path("/{snapshotName}") - @Produces({"application/json", "application/xml", BINARY_CONTENT_TYPE_V2}) + @Override @PermissionName(CORE_EDIT_PERM) - public CreateSnapshotResponse createSnapshot( - @Parameter(description = "The name of the core to snapshot.", required = true) - @PathParam("coreName") - String coreName, - @Parameter(description = "The name to associate with the core snapshot.", required = true) - @PathParam("snapshotName") - String snapshotName, - @Parameter(description = "The id to associate with the async task.") @QueryParam("async") - String taskId) - throws Exception { - final CreateSnapshotResponse response = instantiateJerseyResponse(CreateSnapshotResponse.class); + public CreateCoreSnapshotResponse createSnapshot( + String coreName, String snapshotName, String taskId) throws Exception { + final CreateCoreSnapshotResponse response = + instantiateJerseyResponse(CreateCoreSnapshotResponse.class); return handlePotentiallyAsynchronousTask( response, @@ -121,41 +100,12 @@ public class CoreSnapshotAPI extends CoreAdminAPIBase { }); } - /** The Response for {@link CoreSnapshotAPI}'s {@link #createSnapshot(String, String, String)} */ - public static class CreateSnapshotResponse extends SolrJerseyResponse { - @Schema(description = "The name of the core.") - @JsonProperty(CoreAdminParams.CORE) - public String core; - - @Schema(description = "The name of the created snapshot.") - @JsonProperty(CoreAdminParams.SNAPSHOT_NAME) - public String commitName; - - @Schema(description = "The path to the directory containing the index files.") - @JsonProperty(SolrSnapshotManager.INDEX_DIR_PATH) - public String indexDirPath; - - @Schema(description = "The generation value for the created snapshot.") - @JsonProperty(SolrSnapshotManager.GENERATION_NUM) - public Long generation; - - @Schema(description = "The list of index filenames contained within the created snapshot.") - @JsonProperty(SolrSnapshotManager.FILE_LIST) - public Collection<String> files; - } - /** This API is analogous to V1 (GET /solr/admin/cores?action=LISTSNAPSHOTS) */ - @GET - @Produces({"application/json", "application/xml", BINARY_CONTENT_TYPE_V2}) + @Override @PermissionName(CORE_READ_PERM) - public ListSnapshotsResponse listSnapshots( - @Parameter( - description = "The name of the core for which to retrieve snapshots.", - required = true) - @PathParam("coreName") - String coreName) - throws Exception { - final ListSnapshotsResponse response = instantiateJerseyResponse(ListSnapshotsResponse.class); + public ListCoreSnapshotsResponse listSnapshots(String coreName) throws Exception { + final ListCoreSnapshotsResponse response = + instantiateJerseyResponse(ListCoreSnapshotsResponse.class); return handlePotentiallyAsynchronousTask( response, @@ -190,47 +140,10 @@ public class CoreSnapshotAPI extends CoreAdminAPIBase { }); } - /** The Response for {@link CoreSnapshotAPI}'s {@link #listSnapshots(String)} */ - public static class ListSnapshotsResponse extends SolrJerseyResponse { - @Schema(description = "The collection of snapshots found for the requested core.") - @JsonProperty(SolrSnapshotManager.SNAPSHOTS_INFO) - public Map<String, SnapshotInformation> snapshots; - } - - /** - * Contained in {@link ListSnapshotsResponse}, this holds information for a given core's Snapshot - */ - public static class SnapshotInformation implements JacksonReflectMapWriter { - @Schema(description = "The generation value for the snapshot.") - @JsonProperty(SolrSnapshotManager.GENERATION_NUM) - public final long generationNumber; - - @Schema(description = "The path to the directory containing the index files.") - @JsonProperty(SolrSnapshotManager.INDEX_DIR_PATH) - public final String indexDirPath; - - public SnapshotInformation(long generationNumber, String indexDirPath) { - this.generationNumber = generationNumber; - this.indexDirPath = indexDirPath; - } - } - /** This API is analogous to V1 (DELETE /solr/admin/cores?action=DELETESNAPSHOT) */ - @DELETE - @Path("/{snapshotName}") - @Produces({"application/json", "application/xml", BINARY_CONTENT_TYPE_V2}) + @Override @PermissionName(CORE_EDIT_PERM) - public DeleteSnapshotResponse deleteSnapshot( - @Parameter( - description = "The name of the core for which to delete a snapshot.", - required = true) - @PathParam("coreName") - String coreName, - @Parameter(description = "The name of the core snapshot to delete.", required = true) - @PathParam("snapshotName") - String snapshotName, - @Parameter(description = "The id to associate with the async task.") @QueryParam("async") - String taskId) + public DeleteSnapshotResponse deleteSnapshot(String coreName, String snapshotName, String taskId) throws Exception { final DeleteSnapshotResponse response = instantiateJerseyResponse(DeleteSnapshotResponse.class); @@ -264,15 +177,4 @@ public class CoreSnapshotAPI extends CoreAdminAPIBase { return response; }); } - - /** The Response for {@link CoreSnapshotAPI}'s {@link #deleteSnapshot(String, String, String)} */ - public static class DeleteSnapshotResponse extends SolrJerseyResponse { - @Schema(description = "The name of the core.") - @JsonProperty(CoreAdminParams.CORE) - public String coreName; - - @Schema(description = "The name of the deleted snapshot.") - @JsonProperty(CoreAdminParams.SNAPSHOT_NAME) - public String commitName; - } } diff --git a/solr/core/src/java/org/apache/solr/handler/admin/api/MigrateReplicasAPI.java b/solr/core/src/java/org/apache/solr/handler/admin/api/MigrateReplicas.java similarity index 64% rename from solr/core/src/java/org/apache/solr/handler/admin/api/MigrateReplicasAPI.java rename to solr/core/src/java/org/apache/solr/handler/admin/api/MigrateReplicas.java index 6f353707504..4a1e3b657b8 100644 --- a/solr/core/src/java/org/apache/solr/handler/admin/api/MigrateReplicasAPI.java +++ b/solr/core/src/java/org/apache/solr/handler/admin/api/MigrateReplicas.java @@ -16,7 +16,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.common.params.CollectionParams.SOURCE_NODES; import static org.apache.solr.common.params.CollectionParams.TARGET_NODES; @@ -25,17 +24,11 @@ import static org.apache.solr.common.params.CommonAdminParams.WAIT_FOR_FINAL_STA import static org.apache.solr.handler.admin.CollectionsHandler.DEFAULT_COLLECTION_OP_TIMEOUT; import static org.apache.solr.security.PermissionNameProvider.Name.COLL_EDIT_PERM; -import com.fasterxml.jackson.annotation.JsonProperty; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.media.Schema; -import io.swagger.v3.oas.annotations.parameters.RequestBody; import java.util.HashMap; import java.util.Map; -import java.util.Set; import javax.inject.Inject; -import javax.ws.rs.POST; -import javax.ws.rs.Path; -import javax.ws.rs.Produces; +import org.apache.solr.client.api.endpoint.MigrateReplicasApi; +import org.apache.solr.client.api.model.MigrateReplicasRequestBody; import org.apache.solr.client.api.model.SolrJerseyResponse; import org.apache.solr.client.solrj.SolrResponse; import org.apache.solr.common.SolrException; @@ -43,30 +36,24 @@ import org.apache.solr.common.cloud.ZkNodeProps; import org.apache.solr.common.params.CollectionParams.CollectionAction; import org.apache.solr.core.CoreContainer; import org.apache.solr.handler.admin.CollectionsHandler; -import org.apache.solr.jersey.JacksonReflectMapWriter; import org.apache.solr.jersey.PermissionName; import org.apache.solr.request.SolrQueryRequest; import org.apache.solr.response.SolrQueryResponse; /** V2 API for migrating replicas from a set of nodes to another set of nodes. */ -@Path("cluster/replicas/migrate") -public class MigrateReplicasAPI extends AdminAPIBase { +public class MigrateReplicas extends AdminAPIBase implements MigrateReplicasApi { @Inject - public MigrateReplicasAPI( + public MigrateReplicas( CoreContainer coreContainer, SolrQueryRequest solrQueryRequest, SolrQueryResponse solrQueryResponse) { super(coreContainer, solrQueryRequest, solrQueryResponse); } - @POST - @Produces({"application/json", "application/xml", BINARY_CONTENT_TYPE_V2}) + @Override @PermissionName(COLL_EDIT_PERM) - @Operation(summary = "Migrate Replicas from a given set of nodes.") - public SolrJerseyResponse migrateReplicas( - @RequestBody(description = "Contains user provided parameters", required = true) - MigrateReplicasRequestBody requestBody) + public SolrJerseyResponse migrateReplicas(MigrateReplicasRequestBody requestBody) throws Exception { final SolrJerseyResponse response = instantiateJerseyResponse(SolrJerseyResponse.class); final CoreContainer coreContainer = fetchAndValidateZooKeeperAwareCoreContainer(); @@ -108,39 +95,4 @@ public class MigrateReplicasAPI extends AdminAPIBase { return new ZkNodeProps(remoteMessage); } - - public static class MigrateReplicasRequestBody implements JacksonReflectMapWriter { - - public MigrateReplicasRequestBody() {} - - public MigrateReplicasRequestBody( - Set<String> sourceNodes, Set<String> targetNodes, Boolean waitForFinalState, String async) { - this.sourceNodes = sourceNodes; - this.targetNodes = targetNodes; - this.waitForFinalState = waitForFinalState; - this.async = async; - } - - @Schema(description = "The set of nodes which all replicas will be migrated off of.") - @JsonProperty(value = "sourceNodes", required = true) - public Set<String> sourceNodes; - - @Schema( - description = - "A set of nodes to migrate the replicas to. If this is not provided, then the API will use the live data nodes not in 'sourceNodes'.") - @JsonProperty(value = "targetNodes") - public Set<String> targetNodes; - - @Schema( - description = - "If true, the request will complete only when all affected replicas become active. " - + "If false, the API will return the status of the single action, which may be " - + "before the new replicas are online and active.") - @JsonProperty("waitForFinalState") - public Boolean waitForFinalState = false; - - @Schema(description = "Request ID to track this action which will be processed asynchronously.") - @JsonProperty("async") - public String async; - } } diff --git a/solr/core/src/java/org/apache/solr/handler/admin/api/ReloadCoreAPI.java b/solr/core/src/java/org/apache/solr/handler/admin/api/ReloadCore.java similarity index 62% rename from solr/core/src/java/org/apache/solr/handler/admin/api/ReloadCoreAPI.java rename to solr/core/src/java/org/apache/solr/handler/admin/api/ReloadCore.java index b0252b83fa9..2210d43add1 100644 --- a/solr/core/src/java/org/apache/solr/handler/admin/api/ReloadCoreAPI.java +++ b/solr/core/src/java/org/apache/solr/handler/admin/api/ReloadCore.java @@ -17,37 +17,28 @@ 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.security.PermissionNameProvider.Name.CORE_EDIT_PERM; -import com.fasterxml.jackson.annotation.JsonProperty; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.media.Schema; -import io.swagger.v3.oas.annotations.parameters.RequestBody; 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.ReloadCoreApi; +import org.apache.solr.client.api.model.ReloadCoreRequestBody; import org.apache.solr.client.api.model.SolrJerseyResponse; import org.apache.solr.core.CoreContainer; import org.apache.solr.handler.admin.CoreAdminHandler; -import org.apache.solr.jersey.JacksonReflectMapWriter; import org.apache.solr.jersey.PermissionName; import org.apache.solr.request.SolrQueryRequest; import org.apache.solr.response.SolrQueryResponse; /** - * V2 API for reloading an individual core. + * V2 API implementation for reloading an individual core. * * <p>The new API (POST /v2/cores/coreName/reload is analogous to the v1 /admin/cores?action=RELOAD * command. */ -@Path("/cores/{coreName}/reload") -public class ReloadCoreAPI extends CoreAdminAPIBase { +public class ReloadCore extends CoreAdminAPIBase implements ReloadCoreApi { @Inject - public ReloadCoreAPI( + public ReloadCore( SolrQueryRequest solrQueryRequest, SolrQueryResponse solrQueryResponse, CoreContainer coreContainer, @@ -55,15 +46,9 @@ public class ReloadCoreAPI extends CoreAdminAPIBase { super(coreContainer, coreAdminAsyncTracker, solrQueryRequest, solrQueryResponse); } - @POST - @Produces({"application/json", "application/xml", BINARY_CONTENT_TYPE_V2}) + @Override @PermissionName(CORE_EDIT_PERM) - public SolrJerseyResponse reloadCore( - @Parameter(description = "The name of the core to reload.", required = true) - @PathParam("coreName") - String coreName, - @Schema(description = "Additional parameters for reloading the core") @RequestBody - ReloadCoreAPI.ReloadCoreRequestBody reloadCoreRequestBody) + public SolrJerseyResponse reloadCore(String coreName, ReloadCoreRequestBody reloadCoreRequestBody) throws Exception { SolrJerseyResponse solrJerseyResponse = instantiateJerseyResponse(SolrJerseyResponse.class); return handlePotentiallyAsynchronousTask( @@ -76,10 +61,4 @@ public class ReloadCoreAPI extends CoreAdminAPIBase { return solrJerseyResponse; }); } - - public static class ReloadCoreRequestBody implements JacksonReflectMapWriter { - @Schema(description = "Request ID to track this action which will be processed asynchronously.") - @JsonProperty("async") - public String async; - } } diff --git a/solr/core/src/java/org/apache/solr/handler/admin/api/RestoreCoreAPI.java b/solr/core/src/java/org/apache/solr/handler/admin/api/RestoreCore.java similarity index 73% rename from solr/core/src/java/org/apache/solr/handler/admin/api/RestoreCoreAPI.java rename to solr/core/src/java/org/apache/solr/handler/admin/api/RestoreCore.java index 7e8ccf29862..9cfbdf64460 100644 --- a/solr/core/src/java/org/apache/solr/handler/admin/api/RestoreCoreAPI.java +++ b/solr/core/src/java/org/apache/solr/handler/admin/api/RestoreCore.java @@ -16,44 +16,35 @@ */ 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.security.PermissionNameProvider.Name.CORE_EDIT_PERM; -import com.fasterxml.jackson.annotation.JsonProperty; -import io.swagger.v3.oas.annotations.Parameter; import java.net.URI; 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.RestoreCoreApi; +import org.apache.solr.client.api.model.RestoreCoreRequestBody; import org.apache.solr.client.api.model.SolrJerseyResponse; import org.apache.solr.cloud.CloudDescriptor; import org.apache.solr.common.SolrException; import org.apache.solr.common.cloud.Slice; -import org.apache.solr.common.params.CoreAdminParams; import org.apache.solr.core.CoreContainer; import org.apache.solr.core.SolrCore; import org.apache.solr.core.backup.ShardBackupId; import org.apache.solr.core.backup.repository.BackupRepository; -import org.apache.solr.handler.RestoreCore; import org.apache.solr.handler.admin.CoreAdminHandler; -import org.apache.solr.jersey.JacksonReflectMapWriter; import org.apache.solr.jersey.PermissionName; import org.apache.solr.request.SolrQueryRequest; import org.apache.solr.response.SolrQueryResponse; /** - * V2 API for restoring a previously taken backup to a core + * V2 API implementation for restoring a previously taken backup to a core * * <p>Only valid in SolrCloud mode. This API (POST /api/cores/coreName/restore {}) is analogous to * the v1 GET /solr/admin/cores?action=RESTORECORE command. */ -@Path("/cores/{coreName}/restore") -public class RestoreCoreAPI extends CoreAdminAPIBase { +public class RestoreCore extends CoreAdminAPIBase implements RestoreCoreApi { @Inject - public RestoreCoreAPI( + public RestoreCore( CoreContainer coreContainer, SolrQueryRequest solrQueryRequest, SolrQueryResponse solrQueryResponse, @@ -66,20 +57,16 @@ public class RestoreCoreAPI extends CoreAdminAPIBase { return true; } - @POST - @Produces({"application/json", "application/xml", BINARY_CONTENT_TYPE_V2}) + @Override @PermissionName(CORE_EDIT_PERM) - public SolrJerseyResponse restoreCore( - @Parameter(description = "The name of the core to be restored") @PathParam("coreName") - String coreName, - RestoreCoreRequestBody requestBody) + public SolrJerseyResponse restoreCore(String coreName, RestoreCoreRequestBody requestBody) throws Exception { final var response = instantiateJerseyResponse(SolrJerseyResponse.class); ensureRequiredParameterProvided("coreName", coreName); if (requestBody == null) { throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "Missing required request body"); } - requestBody.validate(); + validateRequestBody(requestBody); AdminAPIBase.validateZooKeeperAwareCoreContainer(coreContainer); return handlePotentiallyAsynchronousTask( response, @@ -128,12 +115,16 @@ public class RestoreCoreAPI extends CoreAdminAPIBase { + ", the core must be the only replica in its shard or it must be read only"); } - RestoreCore restoreCore; + org.apache.solr.handler.RestoreCore restoreCore; if (requestBody.shardBackupId != null) { final ShardBackupId shardBackupId = ShardBackupId.from(requestBody.shardBackupId); - restoreCore = RestoreCore.createWithMetaFile(repository, core, locationUri, shardBackupId); + restoreCore = + org.apache.solr.handler.RestoreCore.createWithMetaFile( + repository, core, locationUri, shardBackupId); } else { - restoreCore = RestoreCore.create(repository, core, locationUri, requestBody.name); + restoreCore = + org.apache.solr.handler.RestoreCore.create( + repository, core, locationUri, requestBody.name); } boolean success = restoreCore.doRestore(); if (!success) { @@ -149,25 +140,11 @@ public class RestoreCoreAPI extends CoreAdminAPIBase { } } - public static class RestoreCoreRequestBody implements JacksonReflectMapWriter { - @JsonProperty public String name; - - @JsonProperty public String shardBackupId; - - @JsonProperty(CoreAdminParams.BACKUP_REPOSITORY) - public String backupRepository; - - @JsonProperty(CoreAdminParams.BACKUP_LOCATION) - public String location; - - @JsonProperty public String async; - - public void validate() { - if (shardBackupId == null && name == null) { - throw new SolrException( - SolrException.ErrorCode.BAD_REQUEST, - "Either 'name' or 'shardBackupId' must be specified"); - } + public static void validateRequestBody(RestoreCoreRequestBody requestBody) { + if (requestBody.shardBackupId == null && requestBody.name == null) { + throw new SolrException( + SolrException.ErrorCode.BAD_REQUEST, + "Either 'name' or 'shardBackupId' must be specified"); } } } diff --git a/solr/core/src/test/org/apache/solr/cloud/MigrateReplicasTest.java b/solr/core/src/test/org/apache/solr/cloud/MigrateReplicasTest.java index 0935770b9f5..0be4ca1746b 100644 --- a/solr/core/src/test/org/apache/solr/cloud/MigrateReplicasTest.java +++ b/solr/core/src/test/org/apache/solr/cloud/MigrateReplicasTest.java @@ -36,6 +36,7 @@ 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.MigrateReplicasRequestBody; import org.apache.solr.client.solrj.SolrClient; import org.apache.solr.client.solrj.impl.CloudLegacySolrClient; import org.apache.solr.client.solrj.impl.CloudSolrClient; @@ -49,7 +50,6 @@ import org.apache.solr.common.cloud.ZkStateReader; import org.apache.solr.common.util.StrUtils; import org.apache.solr.common.util.Utils; import org.apache.solr.embedded.JettySolrRunner; -import org.apache.solr.handler.admin.api.MigrateReplicasAPI; import org.apache.solr.metrics.MetricsMap; import org.apache.solr.metrics.SolrMetricManager; import org.junit.Before; @@ -125,7 +125,7 @@ public class MigrateReplicasTest extends SolrCloudTestCase { Map<?, ?> response = callMigrateReplicas( cloudClient, - new MigrateReplicasAPI.MigrateReplicasRequestBody( + new MigrateReplicasRequestBody( Set.of(nodeToBeDecommissioned), Set.of(emptyNode), true, null)); assertEquals( "MigrateReplicas request was unsuccessful", @@ -153,7 +153,7 @@ public class MigrateReplicasTest extends SolrCloudTestCase { response = callMigrateReplicas( cloudClient, - new MigrateReplicasAPI.MigrateReplicasRequestBody( + new MigrateReplicasRequestBody( Set.of(emptyNode), Set.of(nodeToBeDecommissioned), true, null)); assertEquals( "MigrateReplicas request was unsuccessful", @@ -277,7 +277,7 @@ public class MigrateReplicasTest extends SolrCloudTestCase { Map<?, ?> response = callMigrateReplicas( cloudClient, - new MigrateReplicasAPI.MigrateReplicasRequestBody( + new MigrateReplicasRequestBody( new HashSet<>(nodesToBeDecommissioned), Collections.emptySet(), true, null)); assertEquals( "MigrateReplicas request was unsuccessful", @@ -327,8 +327,7 @@ public class MigrateReplicasTest extends SolrCloudTestCase { Map<?, ?> response = callMigrateReplicas( cloudClient, - new MigrateReplicasAPI.MigrateReplicasRequestBody( - Set.of(liveNode), Collections.emptySet(), true, null)); + new MigrateReplicasRequestBody(Set.of(liveNode), Collections.emptySet(), true, null)); assertNotNull( "No error in response, when the request should have failed", response.get("error")); assertEquals( @@ -337,8 +336,7 @@ public class MigrateReplicasTest extends SolrCloudTestCase { ((Map<?, ?>) response.get("error")).get("msg")); } - public Map<?, ?> callMigrateReplicas( - CloudSolrClient cloudClient, MigrateReplicasAPI.MigrateReplicasRequestBody body) + public Map<?, ?> callMigrateReplicas(CloudSolrClient cloudClient, MigrateReplicasRequestBody body) throws IOException { HttpEntityEnclosingRequestBase httpRequest = null; HttpEntity entity; @@ -351,7 +349,9 @@ public class MigrateReplicasTest extends SolrCloudTestCase { try { httpRequest = new HttpPost(uri); - httpRequest.setEntity(new ByteArrayEntity(Utils.toJSON(body), ContentType.APPLICATION_JSON)); + httpRequest.setEntity( + new ByteArrayEntity( + Utils.toJSON(Utils.getReflectWriter(body)), ContentType.APPLICATION_JSON)); httpRequest.setHeader("Accept", "application/json"); entity = ((CloudLegacySolrClient) cloudClient).getHttpClient().execute(httpRequest).getEntity(); diff --git a/solr/core/src/test/org/apache/solr/core/PluginBagTest.java b/solr/core/src/test/org/apache/solr/core/PluginBagTest.java index d3831489edb..b6a24ab366f 100644 --- a/solr/core/src/test/org/apache/solr/core/PluginBagTest.java +++ b/solr/core/src/test/org/apache/solr/core/PluginBagTest.java @@ -26,7 +26,7 @@ import org.apache.solr.api.ApiSupport; import org.apache.solr.api.JerseyResource; import org.apache.solr.handler.RequestHandlerBase; import org.apache.solr.handler.admin.ConfigSetsHandler; -import org.apache.solr.handler.admin.api.CollectionPropertyAPI; +import org.apache.solr.handler.admin.api.CollectionProperty; import org.apache.solr.handler.component.SearchComponent; import org.apache.solr.handler.configsets.ListConfigSets; import org.apache.solr.jersey.APIConfigProvider; @@ -149,7 +149,7 @@ public class PluginBagTest extends SolrTestCaseJ4 { @Override public Collection<Class<? extends JerseyResource>> getJerseyResources() { // random pick of v2 api - return List.of(CollectionPropertyAPI.class); + return List.of(CollectionProperty.class); } @Override diff --git a/solr/core/src/test/org/apache/solr/handler/admin/api/CoreSnapshotAPITest.java b/solr/core/src/test/org/apache/solr/handler/admin/api/CoreSnapshotAPITest.java index 7f3f566bd8b..5ada271d324 100644 --- a/solr/core/src/test/org/apache/solr/handler/admin/api/CoreSnapshotAPITest.java +++ b/solr/core/src/test/org/apache/solr/handler/admin/api/CoreSnapshotAPITest.java @@ -19,6 +19,9 @@ package org.apache.solr.handler.admin.api; import java.util.ArrayList; import java.util.List; import org.apache.solr.SolrTestCaseJ4; +import org.apache.solr.client.api.model.CreateCoreSnapshotResponse; +import org.apache.solr.client.api.model.DeleteSnapshotResponse; +import org.apache.solr.client.api.model.ListCoreSnapshotsResponse; import org.apache.solr.common.SolrException; import org.apache.solr.core.CoreContainer; import org.apache.solr.handler.admin.CoreAdminHandler; @@ -31,7 +34,7 @@ import org.junit.Test; public class CoreSnapshotAPITest extends SolrTestCaseJ4 { - private CoreSnapshotAPI coreSnapshotAPI; + private CoreSnapshot coreSnapshotAPI; @BeforeClass public static void initializeCoreAndRequestFactory() throws Exception { @@ -52,8 +55,7 @@ public class CoreSnapshotAPITest extends SolrTestCaseJ4 { new CoreAdminHandler.CoreAdminAsyncTracker(); coreSnapshotAPI = - new CoreSnapshotAPI( - solrQueryRequest, solrQueryResponse, coreContainer, coreAdminAsyncTracker); + new CoreSnapshot(solrQueryRequest, solrQueryResponse, coreContainer, coreAdminAsyncTracker); } private List<String> snapshotsToCleanup = new ArrayList<>(); @@ -71,7 +73,7 @@ public class CoreSnapshotAPITest extends SolrTestCaseJ4 { public void testCreateSnapshotReturnsValidResponse() throws Exception { final String snapshotName = "my-new-snapshot"; - final CoreSnapshotAPI.CreateSnapshotResponse response = + final CreateCoreSnapshotResponse response = coreSnapshotAPI.createSnapshot(coreName, snapshotName, null); snapshotsToCleanup.add(snapshotName); @@ -108,7 +110,7 @@ public class CoreSnapshotAPITest extends SolrTestCaseJ4 { snapshotsToCleanup.add(snapshotName); } - final CoreSnapshotAPI.ListSnapshotsResponse response = coreSnapshotAPI.listSnapshots(coreName); + final ListCoreSnapshotsResponse response = coreSnapshotAPI.listSnapshots(coreName); assertEquals(5, response.snapshots.size()); } @@ -135,13 +137,13 @@ public class CoreSnapshotAPITest extends SolrTestCaseJ4 { coreSnapshotAPI.createSnapshot(coreName, snapshotName, null); - final CoreSnapshotAPI.DeleteSnapshotResponse deleteResponse = + final DeleteSnapshotResponse deleteResponse = coreSnapshotAPI.deleteSnapshot(coreName, snapshotName, null); assertEquals(coreName, deleteResponse.coreName); assertEquals(snapshotName, deleteResponse.commitName); - final CoreSnapshotAPI.ListSnapshotsResponse response = coreSnapshotAPI.listSnapshots(coreName); + final ListCoreSnapshotsResponse response = coreSnapshotAPI.listSnapshots(coreName); assertEquals(0, response.snapshots.size()); } diff --git a/solr/core/src/test/org/apache/solr/handler/admin/api/MigrateReplicasAPITest.java b/solr/core/src/test/org/apache/solr/handler/admin/api/MigrateReplicasAPITest.java index f9bf865d4e0..f6124c99703 100644 --- a/solr/core/src/test/org/apache/solr/handler/admin/api/MigrateReplicasAPITest.java +++ b/solr/core/src/test/org/apache/solr/handler/admin/api/MigrateReplicasAPITest.java @@ -27,6 +27,7 @@ import java.util.Map; import java.util.Optional; import java.util.Set; import org.apache.solr.SolrTestCaseJ4; +import org.apache.solr.client.api.model.MigrateReplicasRequestBody; import org.apache.solr.cloud.OverseerSolrResponse; import org.apache.solr.cloud.api.collections.DistributedCollectionConfigSetCommandRunner; import org.apache.solr.common.SolrException; @@ -46,7 +47,7 @@ public class MigrateReplicasAPITest extends SolrTestCaseJ4 { private CoreContainer mockCoreContainer; private SolrQueryRequest mockQueryRequest; private SolrQueryResponse queryResponse; - private MigrateReplicasAPI migrateReplicasAPI; + private MigrateReplicas migrateReplicasAPI; private DistributedCollectionConfigSetCommandRunner mockCommandRunner; private ArgumentCaptor<ZkNodeProps> messageCapturer; @@ -68,7 +69,7 @@ public class MigrateReplicasAPITest extends SolrTestCaseJ4 { .thenReturn(new OverseerSolrResponse(new NamedList<>())); mockQueryRequest = mock(SolrQueryRequest.class); queryResponse = new SolrQueryResponse(); - migrateReplicasAPI = new MigrateReplicasAPI(mockCoreContainer, mockQueryRequest, queryResponse); + migrateReplicasAPI = new MigrateReplicas(mockCoreContainer, mockQueryRequest, queryResponse); messageCapturer = ArgumentCaptor.forClass(ZkNodeProps.class); when(mockCoreContainer.isZooKeeperAware()).thenReturn(true); @@ -76,8 +77,8 @@ public class MigrateReplicasAPITest extends SolrTestCaseJ4 { @Test public void testCreatesValidOverseerMessage() throws Exception { - MigrateReplicasAPI.MigrateReplicasRequestBody requestBody = - new MigrateReplicasAPI.MigrateReplicasRequestBody( + MigrateReplicasRequestBody requestBody = + new MigrateReplicasRequestBody( Set.of("demoSourceNode"), Set.of("demoTargetNode"), false, "async"); migrateReplicasAPI.migrateReplicas(requestBody); verify(mockCommandRunner).runCollectionCommand(messageCapturer.capture(), any(), anyLong()); @@ -94,9 +95,8 @@ public class MigrateReplicasAPITest extends SolrTestCaseJ4 { @Test public void testNoTargetNodes() throws Exception { - MigrateReplicasAPI.MigrateReplicasRequestBody requestBody = - new MigrateReplicasAPI.MigrateReplicasRequestBody( - Set.of("demoSourceNode"), null, null, null); + MigrateReplicasRequestBody requestBody = + new MigrateReplicasRequestBody(Set.of("demoSourceNode"), null, null, null); migrateReplicasAPI.migrateReplicas(requestBody); verify(mockCommandRunner).runCollectionCommand(messageCapturer.capture(), any(), anyLong()); @@ -109,13 +109,12 @@ public class MigrateReplicasAPITest extends SolrTestCaseJ4 { @Test public void testNoSourceNodesThrowsError() throws Exception { - MigrateReplicasAPI.MigrateReplicasRequestBody requestBody1 = - new MigrateReplicasAPI.MigrateReplicasRequestBody( + MigrateReplicasRequestBody requestBody1 = + new MigrateReplicasRequestBody( Collections.emptySet(), Set.of("demoTargetNode"), null, null); assertThrows(SolrException.class, () -> migrateReplicasAPI.migrateReplicas(requestBody1)); - MigrateReplicasAPI.MigrateReplicasRequestBody requestBody2 = - new MigrateReplicasAPI.MigrateReplicasRequestBody( - null, Set.of("demoTargetNode"), null, null); + MigrateReplicasRequestBody requestBody2 = + new MigrateReplicasRequestBody(null, Set.of("demoTargetNode"), null, null); assertThrows(SolrException.class, () -> migrateReplicasAPI.migrateReplicas(requestBody2)); } } diff --git a/solr/core/src/test/org/apache/solr/handler/admin/api/ReloadCoreAPITest.java b/solr/core/src/test/org/apache/solr/handler/admin/api/ReloadCoreAPITest.java index cd0fdc32324..304717a167a 100644 --- a/solr/core/src/test/org/apache/solr/handler/admin/api/ReloadCoreAPITest.java +++ b/solr/core/src/test/org/apache/solr/handler/admin/api/ReloadCoreAPITest.java @@ -17,6 +17,7 @@ package org.apache.solr.handler.admin.api; import org.apache.solr.SolrTestCaseJ4; +import org.apache.solr.client.api.model.ReloadCoreRequestBody; import org.apache.solr.client.api.model.SolrJerseyResponse; import org.apache.solr.common.SolrException; import org.apache.solr.core.CoreContainer; @@ -30,7 +31,7 @@ import org.junit.Test; public class ReloadCoreAPITest extends SolrTestCaseJ4 { - private ReloadCoreAPI reloadCoreAPI; + private ReloadCore reloadCoreAPI; private static final String NON_EXISTENT_CORE = "non_existent_core"; @BeforeClass @@ -49,14 +50,12 @@ public class ReloadCoreAPITest extends SolrTestCaseJ4 { CoreAdminHandler.CoreAdminAsyncTracker coreAdminAsyncTracker = new CoreAdminHandler.CoreAdminAsyncTracker(); reloadCoreAPI = - new ReloadCoreAPI( - solrQueryRequest, solrQueryResponse, coreContainer, coreAdminAsyncTracker); + new ReloadCore(solrQueryRequest, solrQueryResponse, coreContainer, coreAdminAsyncTracker); } @Test public void testValidReloadCoreAPIResponse() throws Exception { - SolrJerseyResponse response = - reloadCoreAPI.reloadCore(coreName, new ReloadCoreAPI.ReloadCoreRequestBody()); + SolrJerseyResponse response = reloadCoreAPI.reloadCore(coreName, new ReloadCoreRequestBody()); assertEquals(0, response.responseHeader.status); assertNotNull(response.responseHeader.qTime); } @@ -67,8 +66,7 @@ public class ReloadCoreAPITest extends SolrTestCaseJ4 { expectThrows( SolrException.class, () -> { - reloadCoreAPI.reloadCore( - NON_EXISTENT_CORE, new ReloadCoreAPI.ReloadCoreRequestBody()); + reloadCoreAPI.reloadCore(NON_EXISTENT_CORE, new ReloadCoreRequestBody()); }); assertEquals(400, solrException.code()); assertTrue(solrException.getMessage().contains("No such core: " + NON_EXISTENT_CORE));
