From 5fc36a84e37902defb4e25ac6e243b6cc0937ecb Mon Sep 17 00:00:00 2001 From: Carlos Ugarte Date: Fri, 4 Oct 2024 16:45:35 -0400 Subject: [PATCH] SOLR-16390: v2 Cluster Property APIs. --- .../endpoint/DeleteClusterPropertyApi.java | 38 ++++++++++++ .../api/endpoint/GetClusterPropertyApi.java | 38 ++++++++++++ .../endpoint/ListClusterPropertiesApi.java | 33 ++++++++++ .../api/endpoint/SetClusterPropertyApi.java | 43 +++++++++++++ .../endpoint/SetNestedClusterPropertyApi.java | 38 ++++++++++++ .../api/model/ClusterPropertyDetails.java | 31 ++++++++++ .../api/model/GetClusterPropertyResponse.java | 27 ++++++++ .../model/ListClusterPropertiesResponse.java | 28 +++++++++ .../model/SetClusterPropertyRequestBody.java | 27 ++++++++ .../SetNestedClusterPropertyRequestBody.java | 28 +++++++++ .../org/apache/solr/core/CoreContainer.java | 10 +++ .../org/apache/solr/handler/ClusterAPI.java | 17 +++--- .../handler/admin/CollectionsHandler.java | 13 ++-- .../admin/api/ClusterPropertiesAPIBase.java | 30 +++++++++ .../admin/api/DeleteClusterProperty.java | 56 +++++++++++++++++ .../handler/admin/api/GetClusterProperty.java | 61 +++++++++++++++++++ .../admin/api/ListClusterProperties.java | 53 ++++++++++++++++ .../handler/admin/api/SetClusterProperty.java | 45 ++++++++++++++ .../admin/api/SetNestedClusterProperty.java | 50 +++++++++++++++ 19 files changed, 653 insertions(+), 13 deletions(-) create mode 100644 solr/api/src/java/org/apache/solr/client/api/endpoint/DeleteClusterPropertyApi.java create mode 100644 solr/api/src/java/org/apache/solr/client/api/endpoint/GetClusterPropertyApi.java create mode 100644 solr/api/src/java/org/apache/solr/client/api/endpoint/ListClusterPropertiesApi.java create mode 100644 solr/api/src/java/org/apache/solr/client/api/endpoint/SetClusterPropertyApi.java create mode 100644 solr/api/src/java/org/apache/solr/client/api/endpoint/SetNestedClusterPropertyApi.java create mode 100644 solr/api/src/java/org/apache/solr/client/api/model/ClusterPropertyDetails.java create mode 100644 solr/api/src/java/org/apache/solr/client/api/model/GetClusterPropertyResponse.java create mode 100644 solr/api/src/java/org/apache/solr/client/api/model/ListClusterPropertiesResponse.java create mode 100644 solr/api/src/java/org/apache/solr/client/api/model/SetClusterPropertyRequestBody.java create mode 100644 solr/api/src/java/org/apache/solr/client/api/model/SetNestedClusterPropertyRequestBody.java create mode 100644 solr/core/src/java/org/apache/solr/handler/admin/api/ClusterPropertiesAPIBase.java create mode 100644 solr/core/src/java/org/apache/solr/handler/admin/api/DeleteClusterProperty.java create mode 100644 solr/core/src/java/org/apache/solr/handler/admin/api/GetClusterProperty.java create mode 100644 solr/core/src/java/org/apache/solr/handler/admin/api/ListClusterProperties.java create mode 100644 solr/core/src/java/org/apache/solr/handler/admin/api/SetClusterProperty.java create mode 100644 solr/core/src/java/org/apache/solr/handler/admin/api/SetNestedClusterProperty.java diff --git a/solr/api/src/java/org/apache/solr/client/api/endpoint/DeleteClusterPropertyApi.java b/solr/api/src/java/org/apache/solr/client/api/endpoint/DeleteClusterPropertyApi.java new file mode 100644 index 00000000000..3a26bbd3adc --- /dev/null +++ b/solr/api/src/java/org/apache/solr/client/api/endpoint/DeleteClusterPropertyApi.java @@ -0,0 +1,38 @@ +/* + * 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 jakarta.ws.rs.DELETE; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.PathParam; +import org.apache.solr.client.api.model.SolrJerseyResponse; + +/** V2 API definition for deleting a cluster property. */ +@Path("/cluster/properties/{propertyName}") +public interface DeleteClusterPropertyApi { + @DELETE + @Operation( + summary = "Delete a cluster property in this Solr cluster", + tags = {"cluster-properties"}) + SolrJerseyResponse deleteClusterProperty( + @Parameter(description = "The name of the property being deleted.", required = true) + @PathParam("propertyName") + String propertyName); +} diff --git a/solr/api/src/java/org/apache/solr/client/api/endpoint/GetClusterPropertyApi.java b/solr/api/src/java/org/apache/solr/client/api/endpoint/GetClusterPropertyApi.java new file mode 100644 index 00000000000..659d1a69029 --- /dev/null +++ b/solr/api/src/java/org/apache/solr/client/api/endpoint/GetClusterPropertyApi.java @@ -0,0 +1,38 @@ +/* + * 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 jakarta.ws.rs.GET; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.PathParam; +import org.apache.solr.client.api.model.SolrJerseyResponse; + +/** V2 API definition for returning the value of a cluster property. */ +@Path("/cluster/properties/{propertyName}") +public interface GetClusterPropertyApi { + @GET + @Operation( + summary = "Get a cluster property in this Solr cluster", + tags = {"cluster-properties"}) + SolrJerseyResponse getClusterProperty( + @Parameter(description = "The name of the property being retrieved.", required = true) + @PathParam("propertyName") + String propertyName); +} diff --git a/solr/api/src/java/org/apache/solr/client/api/endpoint/ListClusterPropertiesApi.java b/solr/api/src/java/org/apache/solr/client/api/endpoint/ListClusterPropertiesApi.java new file mode 100644 index 00000000000..957117d0940 --- /dev/null +++ b/solr/api/src/java/org/apache/solr/client/api/endpoint/ListClusterPropertiesApi.java @@ -0,0 +1,33 @@ +/* + * 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 jakarta.ws.rs.GET; +import jakarta.ws.rs.Path; +import org.apache.solr.client.api.model.ListClusterPropertiesResponse; + +/** V2 API definition for listing cluster properties. */ +@Path("/cluster/properties") +public interface ListClusterPropertiesApi { + @GET + @Operation( + summary = "List all cluster properties in this Solr cluster", + tags = {"cluster-properties"}) + ListClusterPropertiesResponse listClusterProperties(); +} diff --git a/solr/api/src/java/org/apache/solr/client/api/endpoint/SetClusterPropertyApi.java b/solr/api/src/java/org/apache/solr/client/api/endpoint/SetClusterPropertyApi.java new file mode 100644 index 00000000000..660e6ddc633 --- /dev/null +++ b/solr/api/src/java/org/apache/solr/client/api/endpoint/SetClusterPropertyApi.java @@ -0,0 +1,43 @@ +/* + * 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.parameters.RequestBody; +import jakarta.ws.rs.PUT; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.PathParam; +import org.apache.solr.client.api.model.SetClusterPropertyRequestBody; +import org.apache.solr.client.api.model.SolrJerseyResponse; + +@Path("/cluster/properties/{propertyName}") +public interface SetClusterPropertyApi { + + @PUT + @Operation( + summary = "Set a cluster property in this Solr cluster", + tags = {"cluster-properties"}) + SolrJerseyResponse createOrUpdateClusterProperty( + @Parameter(description = "The name of the property being set.", required = true) + @PathParam("propertyName") + String propertyName, + @RequestBody(description = "Value to set for the property", required = true) + SetClusterPropertyRequestBody requestBody) + throws Exception; +} diff --git a/solr/api/src/java/org/apache/solr/client/api/endpoint/SetNestedClusterPropertyApi.java b/solr/api/src/java/org/apache/solr/client/api/endpoint/SetNestedClusterPropertyApi.java new file mode 100644 index 00000000000..28c62caf7f3 --- /dev/null +++ b/solr/api/src/java/org/apache/solr/client/api/endpoint/SetNestedClusterPropertyApi.java @@ -0,0 +1,38 @@ +/* + * 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 jakarta.ws.rs.PUT; +import jakarta.ws.rs.Path; +import org.apache.solr.client.api.model.SetNestedClusterPropertyRequestBody; +import org.apache.solr.client.api.model.SolrJerseyResponse; + +@Path("/cluster/properties") +public interface SetNestedClusterPropertyApi { + + @PUT + @Operation( + summary = "Set nested cluster properties in this Solr cluster", + tags = {"cluster-properties"}) + SolrJerseyResponse createOrUpdateNestedClusterProperty( + @RequestBody(description = "Property/ies to be set", required = true) + SetNestedClusterPropertyRequestBody requestBody) + throws Exception; +} diff --git a/solr/api/src/java/org/apache/solr/client/api/model/ClusterPropertyDetails.java b/solr/api/src/java/org/apache/solr/client/api/model/ClusterPropertyDetails.java new file mode 100644 index 00000000000..9619e96ac1e --- /dev/null +++ b/solr/api/src/java/org/apache/solr/client/api/model/ClusterPropertyDetails.java @@ -0,0 +1,31 @@ +/* + * 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 ClusterPropertyDetails { + @JsonProperty("name") + @Schema(description = "The name of the cluster property.") + public String name; + + @JsonProperty("value") + @Schema(description = "The value of the cluster property.") + public Object value; +} diff --git a/solr/api/src/java/org/apache/solr/client/api/model/GetClusterPropertyResponse.java b/solr/api/src/java/org/apache/solr/client/api/model/GetClusterPropertyResponse.java new file mode 100644 index 00000000000..3ebdd74ef60 --- /dev/null +++ b/solr/api/src/java/org/apache/solr/client/api/model/GetClusterPropertyResponse.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; + +public class GetClusterPropertyResponse extends SolrJerseyResponse { + @JsonProperty("clusterProperty") + @Schema(description = "The requested cluster property.") + public ClusterPropertyDetails clusterProperty; +} diff --git a/solr/api/src/java/org/apache/solr/client/api/model/ListClusterPropertiesResponse.java b/solr/api/src/java/org/apache/solr/client/api/model/ListClusterPropertiesResponse.java new file mode 100644 index 00000000000..46504fb23f1 --- /dev/null +++ b/solr/api/src/java/org/apache/solr/client/api/model/ListClusterPropertiesResponse.java @@ -0,0 +1,28 @@ +/* + * 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; + +public class ListClusterPropertiesResponse extends SolrJerseyResponse { + @JsonProperty("clusterProperties") + @Schema(description = "The list of cluster properties.") + public List clusterProperties; +} diff --git a/solr/api/src/java/org/apache/solr/client/api/model/SetClusterPropertyRequestBody.java b/solr/api/src/java/org/apache/solr/client/api/model/SetClusterPropertyRequestBody.java new file mode 100644 index 00000000000..057f4bcb1d5 --- /dev/null +++ b/solr/api/src/java/org/apache/solr/client/api/model/SetClusterPropertyRequestBody.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; + +public class SetClusterPropertyRequestBody { + @Schema(description = "The value to assign to the property.") + @JsonProperty("value") + public String value; +} diff --git a/solr/api/src/java/org/apache/solr/client/api/model/SetNestedClusterPropertyRequestBody.java b/solr/api/src/java/org/apache/solr/client/api/model/SetNestedClusterPropertyRequestBody.java new file mode 100644 index 00000000000..96380ac2855 --- /dev/null +++ b/solr/api/src/java/org/apache/solr/client/api/model/SetNestedClusterPropertyRequestBody.java @@ -0,0 +1,28 @@ +/* + * 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 SetNestedClusterPropertyRequestBody { + @Schema(description = "Cluster properties and values to be updated.") + @JsonProperty(value = "properties", required = true) + public Map properties; +} diff --git a/solr/core/src/java/org/apache/solr/core/CoreContainer.java b/solr/core/src/java/org/apache/solr/core/CoreContainer.java index a92c73ef496..25d967ffc9e 100644 --- a/solr/core/src/java/org/apache/solr/core/CoreContainer.java +++ b/solr/core/src/java/org/apache/solr/core/CoreContainer.java @@ -126,6 +126,11 @@ import org.apache.solr.handler.admin.ZookeeperInfoHandler; import org.apache.solr.handler.admin.ZookeeperReadAPI; import org.apache.solr.handler.admin.ZookeeperStatusHandler; +import org.apache.solr.handler.admin.api.DeleteClusterProperty; +import org.apache.solr.handler.admin.api.GetClusterProperty; +import org.apache.solr.handler.admin.api.ListClusterProperties; +import org.apache.solr.handler.admin.api.SetClusterProperty; +import org.apache.solr.handler.admin.api.SetNestedClusterProperty; import org.apache.solr.handler.api.V2ApiUtils; import org.apache.solr.handler.component.ShardHandlerFactory; import org.apache.solr.handler.designer.SchemaDesignerAPI; @@ -907,6 +912,11 @@ private void loadInternal() { ClusterAPI clusterAPI = new ClusterAPI(collectionsHandler, configSetsHandler); registerV2ApiIfEnabled(clusterAPI); registerV2ApiIfEnabled(clusterAPI.commands); + registerV2ApiIfEnabled(ListClusterProperties.class); + registerV2ApiIfEnabled(SetClusterProperty.class); + registerV2ApiIfEnabled(SetNestedClusterProperty.class); + registerV2ApiIfEnabled(GetClusterProperty.class); + registerV2ApiIfEnabled(DeleteClusterProperty.class); if (isZooKeeperAware()) { registerV2ApiIfEnabled(new SchemaDesignerAPI(this)); diff --git a/solr/core/src/java/org/apache/solr/handler/ClusterAPI.java b/solr/core/src/java/org/apache/solr/handler/ClusterAPI.java index e161d55e5b3..177d17d28ec 100644 --- a/solr/core/src/java/org/apache/solr/handler/ClusterAPI.java +++ b/solr/core/src/java/org/apache/solr/handler/ClusterAPI.java @@ -42,6 +42,7 @@ import org.apache.solr.api.Command; import org.apache.solr.api.EndPoint; import org.apache.solr.api.PayloadObj; +import org.apache.solr.client.api.model.SetNestedClusterPropertyRequestBody; import org.apache.solr.client.solrj.cloud.DistribStateManager; import org.apache.solr.client.solrj.request.beans.ClusterPropPayload; import org.apache.solr.client.solrj.request.beans.RateLimiterPayload; @@ -59,6 +60,7 @@ import org.apache.solr.core.NodeRoles; import org.apache.solr.handler.admin.CollectionsHandler; import org.apache.solr.handler.admin.ConfigSetsHandler; +import org.apache.solr.handler.admin.api.SetNestedClusterProperty; import org.apache.solr.request.SolrQueryRequest; import org.apache.solr.response.SolrQueryResponse; import org.apache.zookeeper.KeeperException; @@ -278,14 +280,13 @@ public void removeRole(PayloadObj obj) throws Exception { @Command(name = "set-obj-property") public void setObjProperty(PayloadObj obj) { // Not using the object directly here because the API differentiate between {name:null} and {} - Map m = obj.getDataMap(); - ClusterProperties clusterProperties = - new ClusterProperties(getCoreContainer().getZkController().getZkClient()); - try { - clusterProperties.setClusterProperties(m); - } catch (Exception e) { - throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, "Error in API", e); - } + SetNestedClusterPropertyRequestBody setNestedClusterPropertyRequestBody = + new SetNestedClusterPropertyRequestBody(); + setNestedClusterPropertyRequestBody.properties = obj.getDataMap(); + SetNestedClusterProperty setNestedClusterPropertyAPI = + new SetNestedClusterProperty(getCoreContainer()); + setNestedClusterPropertyAPI.createOrUpdateNestedClusterProperty( + setNestedClusterPropertyRequestBody); } @Command(name = "set-property") 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 7ee6da6a0c1..e4a45250489 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 @@ -123,6 +123,7 @@ import org.apache.solr.client.api.model.CreateCollectionSnapshotResponse; import org.apache.solr.client.api.model.InstallShardDataRequestBody; import org.apache.solr.client.api.model.ReplaceNodeRequestBody; +import org.apache.solr.client.api.model.SetClusterPropertyRequestBody; import org.apache.solr.client.api.model.SolrJerseyResponse; import org.apache.solr.client.api.model.UpdateAliasPropertiesRequestBody; import org.apache.solr.client.api.model.UpdateCollectionPropertyRequestBody; @@ -140,7 +141,6 @@ import org.apache.solr.cloud.api.collections.ReindexCollectionCmd; import org.apache.solr.common.SolrException; import org.apache.solr.common.SolrException.ErrorCode; -import org.apache.solr.common.cloud.ClusterProperties; import org.apache.solr.common.cloud.DocCollection; import org.apache.solr.common.cloud.Replica; import org.apache.solr.common.cloud.Replica.State; @@ -201,6 +201,7 @@ import org.apache.solr.handler.admin.api.RenameCollection; import org.apache.solr.handler.admin.api.ReplaceNode; import org.apache.solr.handler.admin.api.RestoreCollectionAPI; +import org.apache.solr.handler.admin.api.SetClusterProperty; import org.apache.solr.handler.admin.api.SplitShardAPI; import org.apache.solr.handler.admin.api.SyncShard; import org.apache.solr.handler.api.V2ApiUtils; @@ -770,11 +771,13 @@ public enum CollectionOperation implements CollectionOp { CLUSTERPROP_OP( CLUSTERPROP, (req, rsp, h) -> { + SetClusterProperty setClusterPropertyAPI = new SetClusterProperty(req.getCoreContainer()); + SetClusterPropertyRequestBody setClusterPropertyRequestBody = + new SetClusterPropertyRequestBody(); String name = req.getParams().required().get(NAME); - String val = req.getParams().get(VALUE_LONG); - ClusterProperties cp = - new ClusterProperties(h.coreContainer.getZkController().getZkClient()); - cp.setClusterProperty(name, val); + setClusterPropertyRequestBody.value = req.getParams().get(VALUE_LONG); + ; + setClusterPropertyAPI.createOrUpdateClusterProperty(name, setClusterPropertyRequestBody); return null; }), COLLECTIONPROP_OP( diff --git a/solr/core/src/java/org/apache/solr/handler/admin/api/ClusterPropertiesAPIBase.java b/solr/core/src/java/org/apache/solr/handler/admin/api/ClusterPropertiesAPIBase.java new file mode 100644 index 00000000000..83bd8ab8303 --- /dev/null +++ b/solr/core/src/java/org/apache/solr/handler/admin/api/ClusterPropertiesAPIBase.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.handler.admin.api; + +import org.apache.solr.api.JerseyResource; +import org.apache.solr.common.cloud.ClusterProperties; +import org.apache.solr.common.cloud.SolrZkClient; + +public abstract class ClusterPropertiesAPIBase extends JerseyResource { + protected final ClusterProperties clusterProperties; + + public ClusterPropertiesAPIBase(SolrZkClient client) { + this.clusterProperties = new ClusterProperties(client); + } +} diff --git a/solr/core/src/java/org/apache/solr/handler/admin/api/DeleteClusterProperty.java b/solr/core/src/java/org/apache/solr/handler/admin/api/DeleteClusterProperty.java new file mode 100644 index 00000000000..82ec5b94604 --- /dev/null +++ b/solr/core/src/java/org/apache/solr/handler/admin/api/DeleteClusterProperty.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.handler.admin.api; + +import static org.apache.solr.security.PermissionNameProvider.Name.COLL_EDIT_PERM; + +import jakarta.inject.Inject; +import java.io.IOException; +import org.apache.solr.client.api.endpoint.DeleteClusterPropertyApi; +import org.apache.solr.client.api.model.SolrJerseyResponse; +import org.apache.solr.core.CoreContainer; +import org.apache.solr.jersey.PermissionName; + +/** + * V2 API for deleting a cluster property. + * + *

This API (DELETE /api/cluster/properties/{propertyName} is equivalent to the v1 GET + * /solr/admin/collections?action=CLUSTERPROP&name={propertyName} API. + */ +public class DeleteClusterProperty extends ClusterPropertiesAPIBase + implements DeleteClusterPropertyApi { + + @Inject + public DeleteClusterProperty(CoreContainer coreContainer) { + super(coreContainer.getZkController().getZkClient()); + } + + @PermissionName(COLL_EDIT_PERM) + @Override + public SolrJerseyResponse deleteClusterProperty(String propertyName) { + final var response = instantiateJerseyResponse(SolrJerseyResponse.class); + + try { + clusterProperties.setClusterProperty(propertyName, null); + } catch (IOException e) { + throw new RuntimeException(e); + } + + return response; + } +} diff --git a/solr/core/src/java/org/apache/solr/handler/admin/api/GetClusterProperty.java b/solr/core/src/java/org/apache/solr/handler/admin/api/GetClusterProperty.java new file mode 100644 index 00000000000..b0a77f180f1 --- /dev/null +++ b/solr/core/src/java/org/apache/solr/handler/admin/api/GetClusterProperty.java @@ -0,0 +1,61 @@ +/* + * 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.handler.admin.api; + +import jakarta.inject.Inject; +import java.io.IOException; +import org.apache.solr.client.api.endpoint.GetClusterPropertyApi; +import org.apache.solr.client.api.model.ClusterPropertyDetails; +import org.apache.solr.client.api.model.GetClusterPropertyResponse; +import org.apache.solr.client.api.model.SolrJerseyResponse; +import org.apache.solr.common.SolrException; +import org.apache.solr.core.CoreContainer; + +/** + * V2 API for returning the value of a cluster property. + * + *

This API (GET /api/cluster/properties/{propertyName}) has no v1 equivalent. + */ +public class GetClusterProperty extends ClusterPropertiesAPIBase implements GetClusterPropertyApi { + + @Inject + public GetClusterProperty(CoreContainer coreContainer) { + super(coreContainer.getZkController().getZkClient()); + } + + @Override + public SolrJerseyResponse getClusterProperty(String propertyName) { + final var response = instantiateJerseyResponse(GetClusterPropertyResponse.class); + + try { + Object value = clusterProperties.getClusterProperties().get(propertyName); + if (value != null) { + response.clusterProperty = new ClusterPropertyDetails(); + response.clusterProperty.name = propertyName; + response.clusterProperty.value = value; + } else { + throw new SolrException( + SolrException.ErrorCode.BAD_REQUEST, "No such cluster property [" + propertyName + "]"); + } + } catch (IOException e) { + throw new RuntimeException(e); + } + + return response; + } +} diff --git a/solr/core/src/java/org/apache/solr/handler/admin/api/ListClusterProperties.java b/solr/core/src/java/org/apache/solr/handler/admin/api/ListClusterProperties.java new file mode 100644 index 00000000000..682cd939da4 --- /dev/null +++ b/solr/core/src/java/org/apache/solr/handler/admin/api/ListClusterProperties.java @@ -0,0 +1,53 @@ +/* + * 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.handler.admin.api; + +import jakarta.inject.Inject; +import java.io.IOException; +import java.util.ArrayList; +import org.apache.solr.client.api.endpoint.ListClusterPropertiesApi; +import org.apache.solr.client.api.model.ListClusterPropertiesResponse; +import org.apache.solr.core.CoreContainer; + +/** + * V2 API for listing cluster properties. + * + *

This API (GET /api/cluster/properties) has no v1 equivalent. + */ +public class ListClusterProperties extends ClusterPropertiesAPIBase + implements ListClusterPropertiesApi { + + @Inject + public ListClusterProperties(CoreContainer coreContainer) { + super(coreContainer.getZkController().getZkClient()); + } + + @Override + public ListClusterPropertiesResponse listClusterProperties() { + final var response = instantiateJerseyResponse(ListClusterPropertiesResponse.class); + + try { + response.clusterProperties = + new ArrayList<>(clusterProperties.getClusterProperties().keySet()); + } catch (IOException e) { + throw new RuntimeException(e); + } + + return response; + } +} diff --git a/solr/core/src/java/org/apache/solr/handler/admin/api/SetClusterProperty.java b/solr/core/src/java/org/apache/solr/handler/admin/api/SetClusterProperty.java new file mode 100644 index 00000000000..fb25954b492 --- /dev/null +++ b/solr/core/src/java/org/apache/solr/handler/admin/api/SetClusterProperty.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.handler.admin.api; + +import static org.apache.solr.security.PermissionNameProvider.Name.COLL_EDIT_PERM; + +import jakarta.inject.Inject; +import java.io.IOException; +import org.apache.solr.client.api.endpoint.SetClusterPropertyApi; +import org.apache.solr.client.api.model.SetClusterPropertyRequestBody; +import org.apache.solr.client.api.model.SolrJerseyResponse; +import org.apache.solr.core.CoreContainer; +import org.apache.solr.jersey.PermissionName; + +public class SetClusterProperty extends ClusterPropertiesAPIBase implements SetClusterPropertyApi { + + @Inject + public SetClusterProperty(CoreContainer coreContainer) { + super(coreContainer.getZkController().getZkClient()); + } + + @Override + @PermissionName(COLL_EDIT_PERM) + public SolrJerseyResponse createOrUpdateClusterProperty( + String propertyName, SetClusterPropertyRequestBody requestBody) throws IOException { + SolrJerseyResponse response = instantiateJerseyResponse(SolrJerseyResponse.class); + clusterProperties.setClusterProperty(propertyName, requestBody.value); + return response; + } +} diff --git a/solr/core/src/java/org/apache/solr/handler/admin/api/SetNestedClusterProperty.java b/solr/core/src/java/org/apache/solr/handler/admin/api/SetNestedClusterProperty.java new file mode 100644 index 00000000000..cc01c847270 --- /dev/null +++ b/solr/core/src/java/org/apache/solr/handler/admin/api/SetNestedClusterProperty.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.handler.admin.api; + +import static org.apache.solr.security.PermissionNameProvider.Name.COLL_EDIT_PERM; + +import jakarta.inject.Inject; +import org.apache.solr.client.api.endpoint.SetNestedClusterPropertyApi; +import org.apache.solr.client.api.model.SetNestedClusterPropertyRequestBody; +import org.apache.solr.client.api.model.SolrJerseyResponse; +import org.apache.solr.common.SolrException; +import org.apache.solr.core.CoreContainer; +import org.apache.solr.jersey.PermissionName; + +public class SetNestedClusterProperty extends ClusterPropertiesAPIBase + implements SetNestedClusterPropertyApi { + + @Inject + public SetNestedClusterProperty(CoreContainer coreContainer) { + super(coreContainer.getZkController().getZkClient()); + } + + @Override + @PermissionName(COLL_EDIT_PERM) + public SolrJerseyResponse createOrUpdateNestedClusterProperty( + SetNestedClusterPropertyRequestBody requestBody) { + SolrJerseyResponse response = instantiateJerseyResponse(SolrJerseyResponse.class); + try { + clusterProperties.setClusterProperties(requestBody.properties); + } catch (Exception e) { + throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, "Error in API", e); + } + return response; + } +}