Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
title: "v2 GET /api/node/properties is now a JAX-RS API; a single property is fetched at /api/node/properties/{propertyName} (SolrJ: NodeApi.GetNodeProperties / GetNodeProperty)"
type: added
authors:
- name: Prithvi S
nick: iprithv
links:
- name: SOLR-16458
url: https://issues.apache.org/jira/browse/SOLR-16458
Original file line number Diff line number Diff line change
@@ -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 jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.PathParam;
import org.apache.solr.client.api.model.NodePropertiesResponse;

/** V2 API definition for listing JRE system properties on a Solr node. */
@Path("/node/properties")
public interface NodePropertiesApi {

@GET
@Operation(
summary = "List system properties for the target Solr node.",
tags = {"node"})
NodePropertiesResponse getNodeProperties();

@GET
@Path("/{propertyName}")
@Operation(
summary = "Get a single system property for the target Solr node.",
tags = {"node"})
NodePropertiesResponse getNodeProperty(
@Parameter(description = "Name of the system property to return.") @PathParam("propertyName")
String propertyName);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
* 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;

/**
* Response body for {@code GET /api/node/properties} and {@code GET
* /api/node/properties/{propertyName}}.
*/
public class NodePropertiesResponse extends SolrJerseyResponse {

public static final String SYSTEM_PROPERTIES = "system.properties";

@Schema(description = "JRE system properties for the Solr node. Secret values are redacted.")
@JsonProperty(SYSTEM_PROPERTIES)
public Map<String, String> systemProperties;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

is it really as simple as a string/string? Great.

}
Original file line number Diff line number Diff line change
Expand Up @@ -16,24 +16,27 @@
*/
package org.apache.solr.handler.admin;

import static org.apache.solr.client.api.model.NodePropertiesResponse.SYSTEM_PROPERTIES;
import static org.apache.solr.common.params.CommonParams.NAME;

import java.io.IOException;
import java.util.Collection;
import java.util.Enumeration;
import org.apache.solr.api.AnnotatedApi;
import java.util.List;
import java.util.Map;
import org.apache.solr.api.Api;
import org.apache.solr.api.JerseyResource;
import org.apache.solr.common.util.NamedList;
import org.apache.solr.common.util.SimpleOrderedMap;
import org.apache.solr.core.CoreContainer;
import org.apache.solr.core.NodeConfig;
import org.apache.solr.handler.RequestHandlerBase;
import org.apache.solr.handler.admin.api.NodePropertiesAPI;
import org.apache.solr.handler.admin.api.GetNodeProperties;
import org.apache.solr.request.SolrQueryRequest;
import org.apache.solr.response.SolrQueryResponse;
import org.apache.solr.security.AuthorizationContext;

/**
* v1 implementation of {@code GET /admin/info/properties}. Business logic lives in {@link

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

great!

* GetNodeProperties}.
*
* @since solr 1.2
*/
public class PropertiesRequestHandler extends RequestHandlerBase {
Expand All @@ -50,22 +53,14 @@ public PropertiesRequestHandler(CoreContainer cc) {
}

@Override
public void handleRequestBody(SolrQueryRequest req, SolrQueryResponse rsp) throws IOException {
NamedList<String> props = new SimpleOrderedMap<>();
String name = req.getParams().get(NAME);
NodeConfig nodeConfig = getCoreContainer(req).getNodeConfig();
if (name != null) {
String property = nodeConfig.getRedactedSysPropValue(name);
props.add(name, property);
} else {
Enumeration<?> enumeration = System.getProperties().propertyNames();
while (enumeration.hasMoreElements()) {
name = (String) enumeration.nextElement();
props.add(name, nodeConfig.getRedactedSysPropValue(name));
}
}
rsp.add("system.properties", props);
public void handleRequestBody(SolrQueryRequest req, SolrQueryResponse rsp) throws Exception {
rsp.setHttpCaching(false);
String name = req.getParams().get(NAME);
Map<String, String> props =
new GetNodeProperties(getCoreContainer(req)).collectProperties(name);
NamedList<String> values = new SimpleOrderedMap<>();
props.forEach(values::add);
rsp.add(SYSTEM_PROPERTIES, values);
}

//////////////////////// SolrInfoMBeans methods //////////////////////
Expand All @@ -82,7 +77,12 @@ public Category getCategory() {

@Override
public Collection<Api> getApis() {
return AnnotatedApi.getApis(new NodePropertiesAPI(this));
return List.of();
}

@Override
public Collection<Class<? extends JerseyResource>> getJerseyResources() {
return List.of(GetNodeProperties.class);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
/*
* 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.util.Enumeration;
import java.util.LinkedHashMap;
import java.util.Map;
import org.apache.solr.api.JerseyResource;
import org.apache.solr.client.api.endpoint.NodePropertiesApi;
import org.apache.solr.client.api.model.NodePropertiesResponse;
import org.apache.solr.core.CoreContainer;
import org.apache.solr.core.NodeConfig;
import org.apache.solr.jersey.PermissionName;
import org.apache.solr.security.PermissionNameProvider;

/**
* V2 API for listing system properties on the receiving node.
*
* <p>GET /api/node/properties lists all properties. GET /api/node/properties/{propertyName} returns
* a single property. Both are analogous to v1 /admin/info/properties, which still uses a {@code
* name} query parameter for the single-property form.
*
* <p>The v1 {@link org.apache.solr.handler.admin.PropertiesRequestHandler} delegates to this class.
*/
public class GetNodeProperties extends JerseyResource implements NodePropertiesApi {

private final CoreContainer coreContainer;

@Inject
public GetNodeProperties(CoreContainer coreContainer) {
this.coreContainer = coreContainer;
}

@Override
@PermissionName(PermissionNameProvider.Name.CONFIG_READ_PERM)
public NodePropertiesResponse getNodeProperties() {
return buildResponse(null);
}

@Override
@PermissionName(PermissionNameProvider.Name.CONFIG_READ_PERM)
public NodePropertiesResponse getNodeProperty(String propertyName) {
return buildResponse(propertyName);
}

private NodePropertiesResponse buildResponse(String name) {
final NodePropertiesResponse response = instantiateJerseyResponse(NodePropertiesResponse.class);
response.systemProperties = collectProperties(name);
return response;
}

/** Collect redacted system properties, optionally limited to a single named property. */
public Map<String, String> collectProperties(String name) {
final NodeConfig nodeConfig = coreContainer.getNodeConfig();
final Map<String, String> props = new LinkedHashMap<>();
if (name != null) {
props.put(name, nodeConfig.getRedactedSysPropValue(name));
} else {
Enumeration<?> enumeration = System.getProperties().propertyNames();
while (enumeration.hasMoreElements()) {
String propertyName = (String) enumeration.nextElement();
props.put(propertyName, nodeConfig.getRedactedSysPropValue(propertyName));
}
}
return props;
}
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ public static class CountPropertiesRequestHandler extends PropertiesRequestHandl
private int requestCount = 0;

@Override
public void handleRequestBody(SolrQueryRequest req, SolrQueryResponse rsp) throws IOException {
public void handleRequestBody(SolrQueryRequest req, SolrQueryResponse rsp) throws Exception {
++requestCount;
super.handleRequestBody(req, rsp);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import org.apache.solr.client.solrj.SolrRequest;
import org.apache.solr.client.solrj.embedded.EmbeddedSolrServer;
import org.apache.solr.client.solrj.request.GenericSolrRequest;
import org.apache.solr.common.params.ModifiableSolrParams;
import org.apache.solr.common.util.NamedList;
import org.apache.solr.core.NodeConfig;
import org.junit.BeforeClass;
Expand Down Expand Up @@ -54,12 +55,32 @@ public void testRedaction() throws Exception {
}
}

@SuppressWarnings({"unchecked"})
@Test
public void testSingleProperty() throws Exception {
System.setProperty("GetNodeProperties.v1.visible", "hello");
try {
NamedList<Object> properties = readProperties("GetNodeProperties.v1.visible");
assertEquals(1, properties.size());
assertEquals("hello", properties.get("GetNodeProperties.v1.visible"));
} finally {
System.clearProperty("GetNodeProperties.v1.visible");
}
}

private NamedList<Object> readProperties() throws Exception {
SolrClient client = new EmbeddedSolrServer(h.getCore());
return readProperties(null);
}

@SuppressWarnings({"unchecked"})
private NamedList<Object> readProperties(String name) throws Exception {
SolrClient client = new EmbeddedSolrServer(h.getCore());
ModifiableSolrParams params = new ModifiableSolrParams();
if (name != null) {
params.set("name", name);
}
NamedList<Object> properties =
client.request(new GenericSolrRequest(SolrRequest.METHOD.GET, "/admin/info/properties"));
client.request(
new GenericSolrRequest(SolrRequest.METHOD.GET, "/admin/info/properties", params));

return (NamedList<Object>) properties.get("system.properties");
}
Expand Down
Loading