Skip to content

Commit 6e1f8a7

Browse files
Switch to using XContent.Params to indicate whether it is multi-project or not
1 parent 084d605 commit 6e1f8a7

File tree

17 files changed

+153
-125
lines changed

17 files changed

+153
-125
lines changed

server/src/main/java/org/elasticsearch/action/ActionModule.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -846,7 +846,7 @@ public void initRestHandlers(Supplier<DiscoveryNodes> nodesInCluster, Predicate<
846846
registerHandler.accept(new RestNodesInfoAction(settingsFilter));
847847
registerHandler.accept(new RestRemoteClusterInfoAction());
848848
registerHandler.accept(new RestNodesCapabilitiesAction());
849-
registerHandler.accept(new RestNodesStatsAction());
849+
registerHandler.accept(new RestNodesStatsAction(projectIdResolver));
850850
registerHandler.accept(new RestNodesUsageAction());
851851
registerHandler.accept(new RestNodesHotThreadsAction());
852852
registerHandler.accept(new RestClusterAllocationExplainAction());
@@ -981,7 +981,7 @@ public void initRestHandlers(Supplier<DiscoveryNodes> nodesInCluster, Predicate<
981981
registerHandler.accept(new RestShardsAction());
982982
registerHandler.accept(new RestMasterAction());
983983
registerHandler.accept(new RestNodesAction());
984-
registerHandler.accept(new RestClusterInfoAction());
984+
registerHandler.accept(new RestClusterInfoAction(projectIdResolver));
985985
registerHandler.accept(new RestTasksAction(nodesInCluster));
986986
registerHandler.accept(new RestIndicesAction(projectIdResolver));
987987
registerHandler.accept(new RestSegmentsAction());

server/src/main/java/org/elasticsearch/action/admin/cluster/node/stats/NodeStats.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@
5252
*/
5353
public class NodeStats extends BaseNodeResponse implements ChunkedToXContent {
5454

55+
public static final String MULTI_PROJECT_ENABLED_XCONTENT_PARAM_KEY = "multi_project_enabled_node_stats";
56+
5557
private final long timestamp;
5658

5759
@Nullable

server/src/main/java/org/elasticsearch/cluster/project/ProjectIdResolver.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
package org.elasticsearch.cluster.project;
1111

12+
import org.elasticsearch.cluster.metadata.Metadata;
1213
import org.elasticsearch.cluster.metadata.ProjectId;
1314

1415
/**
@@ -27,4 +28,14 @@ public interface ProjectIdResolver {
2728
* @return The identifier of the current project.
2829
*/
2930
ProjectId getProjectId();
31+
32+
/**
33+
* Returns {@code false} if the cluster runs in a setup that always expects only a single default project (see also
34+
* {@link Metadata#DEFAULT_PROJECT_ID}).
35+
* Otherwise, it should return {@code true} to indicate the cluster can accommodate multiple projects regardless
36+
* how many project it current has.
37+
*/
38+
default boolean supportsMultipleProjects() {
39+
return false;
40+
}
3041
}

server/src/main/java/org/elasticsearch/cluster/project/ProjectResolver.java

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -113,14 +113,4 @@ protected <Request extends ActionRequest, Response extends ActionResponse> void
113113
}
114114
};
115115
}
116-
117-
/**
118-
* Returns {@code false} if the cluster runs in a setup that always expects only a single default project (see also
119-
* {@link Metadata#DEFAULT_PROJECT_ID}).
120-
* Otherwise, it should return {@code true} to indicate the cluster can accommodate multiple projects regardless
121-
* how many project it current has.
122-
*/
123-
default boolean supportsMultipleProjects() {
124-
return false;
125-
}
126116
}

server/src/main/java/org/elasticsearch/indices/IndicesService.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -487,7 +487,7 @@ public NodeIndicesStats stats(CommonStatsFlags flags, boolean includeShardsStats
487487
commonStats,
488488
statsByIndex(this, flags),
489489
statsByShard(this, flags),
490-
projectResolver.supportsMultipleProjects() ? projectsByIndex() : null,
490+
projectsByIndex(),
491491
includeShardsStats
492492
);
493493
}

server/src/main/java/org/elasticsearch/indices/NodeIndicesStats.java

Lines changed: 17 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import org.elasticsearch.TransportVersion;
1313
import org.elasticsearch.TransportVersions;
1414
import org.elasticsearch.action.NodeStatsLevel;
15+
import org.elasticsearch.action.admin.cluster.node.stats.NodeStats;
1516
import org.elasticsearch.action.admin.indices.stats.CommonStats;
1617
import org.elasticsearch.action.admin.indices.stats.IndexShardStats;
1718
import org.elasticsearch.action.admin.indices.stats.ShardStats;
@@ -69,7 +70,7 @@ public class NodeIndicesStats implements Writeable, ChunkedToXContent {
6970
private final CommonStats stats;
7071
private final Map<Index, List<IndexShardStats>> statsByShard;
7172
private final Map<Index, CommonStats> statsByIndex;
72-
private final @Nullable Map<Index, ProjectId> projectsByIndex;
73+
private final Map<Index, ProjectId> projectsByIndex;
7374

7475
public NodeIndicesStats(StreamInput in) throws IOException {
7576
stats = new CommonStats(in);
@@ -100,16 +101,11 @@ public NodeIndicesStats(StreamInput in) throws IOException {
100101
}
101102
}
102103

103-
/**
104-
* Constructs an instance. If the {@code projectsByIndex} argument is non-null, the project-to-index map will be stored, and the
105-
* project IDs will be prepended to the index names when converting this instance to XContent. This is appropriate for multi-project
106-
* clusters. If the argument is null, no project IDs will be prepended. This is appropriate for single-project clusters.
107-
*/
108104
public NodeIndicesStats(
109105
CommonStats oldStats,
110106
Map<Index, CommonStats> statsByIndex,
111107
Map<Index, List<IndexShardStats>> statsByShard,
112-
@Nullable Map<Index, ProjectId> projectsByIndex,
108+
Map<Index, ProjectId> projectsByIndex,
113109
boolean includeShardsStats
114110
) {
115111
if (includeShardsStats) {
@@ -131,7 +127,7 @@ public NodeIndicesStats(
131127
for (CommonStats indexStats : statsByIndex.values()) {
132128
stats.add(indexStats);
133129
}
134-
this.projectsByIndex = projectsByIndex;
130+
this.projectsByIndex = requireNonNull(projectsByIndex);
135131
}
136132

137133
@Nullable
@@ -287,7 +283,7 @@ public Iterator<? extends ToXContent> toXContentChunked(ToXContent.Params outerP
287283
case INDICES -> ChunkedToXContentHelper.object(
288284
Fields.INDICES,
289285
Iterators.map(createCommonStatsByIndex().entrySet().iterator(), entry -> (builder, params) -> {
290-
builder.startObject(xContentKey(entry.getKey()));
286+
builder.startObject(xContentKey(entry.getKey(), outerParams));
291287
entry.getValue().toXContent(builder, outerParams);
292288
return builder.endObject();
293289
})
@@ -298,7 +294,7 @@ public Iterator<? extends ToXContent> toXContentChunked(ToXContent.Params outerP
298294
Iterators.flatMap(
299295
statsByShard.entrySet().iterator(),
300296
entry -> ChunkedToXContentHelper.array(
301-
xContentKey(entry.getKey()),
297+
xContentKey(entry.getKey(), outerParams),
302298
Iterators.flatMap(
303299
entry.getValue().iterator(),
304300
indexShardStats -> Iterators.concat(
@@ -318,17 +314,18 @@ public Iterator<? extends ToXContent> toXContentChunked(ToXContent.Params outerP
318314
);
319315
}
320316

321-
private String xContentKey(Index index) {
322-
if (projectsByIndex == null) {
323-
return index.getName();
324-
}
325-
ProjectId projectId = projectsByIndex.get(index);
326-
if (projectId == null) {
327-
// This can happen if the stats were captured after the IndexService was created but before the state was updated.
328-
// The best we can do is handle it gracefully.
329-
return "<unknown>/" + index.getName();
317+
private String xContentKey(Index index, ToXContent.Params outerParams) {
318+
if (outerParams.paramAsBoolean(NodeStats.MULTI_PROJECT_ENABLED_XCONTENT_PARAM_KEY, false)) {
319+
ProjectId projectId = projectsByIndex.get(index);
320+
if (projectId == null) {
321+
// This can happen if the stats were captured after the IndexService was created but before the state was updated.
322+
// The best we can do is handle it gracefully.
323+
return "<unknown>/" + index.getName();
324+
} else {
325+
return projectId + "/" + index.getName();
326+
}
330327
} else {
331-
return projectId + "/" + index.getName();
328+
return index.getName();
332329
}
333330
}
334331

server/src/main/java/org/elasticsearch/ingest/IngestStats.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
package org.elasticsearch.ingest;
1111

1212
import org.elasticsearch.TransportVersions;
13+
import org.elasticsearch.action.admin.cluster.node.stats.NodeStats;
1314
import org.elasticsearch.cluster.metadata.Metadata;
1415
import org.elasticsearch.cluster.metadata.ProjectId;
1516
import org.elasticsearch.common.collect.Iterators;
@@ -146,9 +147,9 @@ public Iterator<? extends ToXContent> toXContentChunked(ToXContent.Params outerP
146147
pipelineStat -> Iterators.concat(
147148

148149
Iterators.single((builder, params) -> {
149-
String key = pipelineStat.projectId().equals(Metadata.DEFAULT_PROJECT_ID)
150-
? pipelineStat.pipelineId()
151-
: pipelineStat.projectId() + "/" + pipelineStat.pipelineId();
150+
String key = outerParams.paramAsBoolean(NodeStats.MULTI_PROJECT_ENABLED_XCONTENT_PARAM_KEY, false)
151+
? pipelineStat.projectId() + "/" + pipelineStat.pipelineId()
152+
: pipelineStat.pipelineId();
152153
builder.startObject(key);
153154
pipelineStat.stats().toXContent(builder, params);
154155
pipelineStat.byteStats().toXContent(builder, params);

server/src/main/java/org/elasticsearch/rest/action/RestRefCountedChunkedToXContentListener.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import org.elasticsearch.core.Releasable;
1515
import org.elasticsearch.core.Releasables;
1616
import org.elasticsearch.rest.RestChannel;
17+
import org.elasticsearch.xcontent.ToXContent;
1718

1819
/**
1920
* Same as {@link RestChunkedToXContentListener} but decrements the ref count on the response it receives by one after serialization of the
@@ -25,6 +26,10 @@ public RestRefCountedChunkedToXContentListener(RestChannel channel) {
2526
super(channel);
2627
}
2728

29+
public RestRefCountedChunkedToXContentListener(RestChannel channel, ToXContent.Params params) {
30+
super(channel, params);
31+
}
32+
2833
@Override
2934
protected Releasable releasableFromResponse(Response response) {
3035
response.mustIncRef();

server/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestNodesStatsAction.java

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,18 +10,21 @@
1010
package org.elasticsearch.rest.action.admin.cluster;
1111

1212
import org.elasticsearch.action.NodeStatsLevel;
13+
import org.elasticsearch.action.admin.cluster.node.stats.NodeStats;
1314
import org.elasticsearch.action.admin.cluster.node.stats.NodesStatsRequest;
1415
import org.elasticsearch.action.admin.cluster.node.stats.NodesStatsRequestParameters.Metric;
1516
import org.elasticsearch.action.admin.indices.stats.CommonStatsFlags;
1617
import org.elasticsearch.action.admin.indices.stats.CommonStatsFlags.Flag;
1718
import org.elasticsearch.client.internal.node.NodeClient;
19+
import org.elasticsearch.cluster.project.ProjectIdResolver;
1820
import org.elasticsearch.common.Strings;
1921
import org.elasticsearch.rest.BaseRestHandler;
2022
import org.elasticsearch.rest.RestRequest;
2123
import org.elasticsearch.rest.Scope;
2224
import org.elasticsearch.rest.ServerlessScope;
2325
import org.elasticsearch.rest.action.RestCancellableNodeClient;
2426
import org.elasticsearch.rest.action.RestRefCountedChunkedToXContentListener;
27+
import org.elasticsearch.xcontent.ToXContent;
2528

2629
import java.io.IOException;
2730
import java.util.Collections;
@@ -41,6 +44,8 @@ public class RestNodesStatsAction extends BaseRestHandler {
4144

4245
private static final Set<String> SUPPORTED_CAPABILITIES = Set.of("dense_vector_off_heap_stats");
4346

47+
private final Map<String, String> xContentParams;
48+
4449
@Override
4550
public List<Route> routes() {
4651
return List.of(
@@ -63,6 +68,13 @@ public List<Route> routes() {
6368
FLAGS = Collections.unmodifiableMap(flags);
6469
}
6570

71+
public RestNodesStatsAction(ProjectIdResolver projectIdResolver) {
72+
this.xContentParams = Map.of(
73+
NodeStats.MULTI_PROJECT_ENABLED_XCONTENT_PARAM_KEY,
74+
Boolean.toString(projectIdResolver.supportsMultipleProjects())
75+
);
76+
}
77+
6678
@Override
6779
public String getName() {
6880
return "nodes_stats_action";
@@ -179,7 +191,10 @@ public RestChannelConsumer prepareRequest(final RestRequest request, final NodeC
179191

180192
return channel -> new RestCancellableNodeClient(client, request.getHttpChannel()).admin()
181193
.cluster()
182-
.nodesStats(nodesStatsRequest, new RestRefCountedChunkedToXContentListener<>(channel));
194+
.nodesStats(
195+
nodesStatsRequest,
196+
new RestRefCountedChunkedToXContentListener<>(channel, new ToXContent.DelegatingMapParams(xContentParams, request))
197+
);
183198
}
184199

185200
private final Set<String> RESPONSE_PARAMS = Collections.singleton("level");

server/src/main/java/org/elasticsearch/rest/action/info/RestClusterInfoAction.java

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import org.elasticsearch.action.admin.cluster.node.stats.NodesStatsRequestParameters.Metric;
1515
import org.elasticsearch.action.admin.cluster.node.stats.NodesStatsResponse;
1616
import org.elasticsearch.client.internal.node.NodeClient;
17+
import org.elasticsearch.cluster.project.ProjectIdResolver;
1718
import org.elasticsearch.common.Strings;
1819
import org.elasticsearch.common.collect.Iterators;
1920
import org.elasticsearch.common.xcontent.ChunkedToXContent;
@@ -31,6 +32,7 @@
3132
import org.elasticsearch.rest.action.RestResponseListener;
3233
import org.elasticsearch.script.ScriptStats;
3334
import org.elasticsearch.threadpool.ThreadPoolStats;
35+
import org.elasticsearch.xcontent.ToXContent;
3436

3537
import java.io.IOException;
3638
import java.util.List;
@@ -47,7 +49,6 @@
4749
import static org.elasticsearch.action.admin.cluster.node.stats.NodesStatsRequestParameters.Metric.INGEST;
4850
import static org.elasticsearch.action.admin.cluster.node.stats.NodesStatsRequestParameters.Metric.SCRIPT;
4951
import static org.elasticsearch.action.admin.cluster.node.stats.NodesStatsRequestParameters.Metric.THREAD_POOL;
50-
import static org.elasticsearch.xcontent.ToXContent.EMPTY_PARAMS;
5152

5253
@ServerlessScope(Scope.PUBLIC)
5354
public class RestClusterInfoAction extends BaseRestHandler {
@@ -77,6 +78,14 @@ public class RestClusterInfoAction extends BaseRestHandler {
7778
static final Set<Metric> AVAILABLE_TARGETS = RESPONSE_MAPPER.keySet();
7879
static final Set<String> AVAILABLE_TARGET_NAMES = AVAILABLE_TARGETS.stream().map(Metric::metricName).collect(toUnmodifiableSet());
7980

81+
private final ToXContent.Params xContentParams;
82+
83+
public RestClusterInfoAction(ProjectIdResolver projectIdResolver) {
84+
this.xContentParams = new ToXContent.MapParams(
85+
Map.of(NodeStats.MULTI_PROJECT_ENABLED_XCONTENT_PARAM_KEY, Boolean.toString(projectIdResolver.supportsMultipleProjects()))
86+
);
87+
}
88+
8089
@Override
8190
public String getName() {
8291
return "cluster_info_action";
@@ -137,7 +146,7 @@ public RestResponse buildResponse(NodesStatsResponse response) throws Exception
137146
Iterators.flatMap(chunkedResponses, chunk -> chunk.toXContentChunked(outerParams)),
138147
ChunkedToXContentHelper.endObject()
139148
),
140-
EMPTY_PARAMS,
149+
xContentParams,
141150
channel
142151
),
143152
null

0 commit comments

Comments
 (0)