Skip to content

Commit 432f578

Browse files
committed
Internal: refactor settings filtering
Refactor how settings filters are handled. Instead of specifying settings filters as filtering class, settings filters are now specified as list of settings that needs to be filtered out. Regex syntax is supported. This is breaking change and will require small change in plugins that are using settingsFilters. This change is needed in order to simplify cluster state diff implementation. Contributes to #6295
1 parent ff8fd67 commit 432f578

File tree

11 files changed

+337
-50
lines changed

11 files changed

+337
-50
lines changed

src/main/java/org/elasticsearch/action/admin/cluster/node/info/NodesInfoResponse.java

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,6 @@
3737
*/
3838
public class NodesInfoResponse extends NodesOperationResponse<NodeInfo> implements ToXContent {
3939

40-
private SettingsFilter settingsFilter;
41-
4240
public NodesInfoResponse() {
4341
}
4442

@@ -64,11 +62,6 @@ public void writeTo(StreamOutput out) throws IOException {
6462
}
6563
}
6664

67-
public NodesInfoResponse settingsFilter(SettingsFilter settingsFilter) {
68-
this.settingsFilter = settingsFilter;
69-
return this;
70-
}
71-
7265
@Override
7366
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
7467
builder.field("cluster_name", getClusterName().value(), XContentBuilder.FieldCaseConversion.NONE);
@@ -102,7 +95,7 @@ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws
10295

10396
if (nodeInfo.getSettings() != null) {
10497
builder.startObject("settings");
105-
Settings settings = settingsFilter != null ? settingsFilter.filterSettings(nodeInfo.getSettings()) : nodeInfo.getSettings();
98+
Settings settings = nodeInfo.getSettings();
10699
settings.toXContent(builder, params);
107100
builder.endObject();
108101
}

src/main/java/org/elasticsearch/action/admin/indices/settings/get/TransportGetSettingsAction.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ protected void masterOperation(GetSettingsRequest request, ClusterState state, A
8686
continue;
8787
}
8888

89-
Settings settings = settingsFilter.filterSettings(indexMetaData.settings());
89+
Settings settings = SettingsFilter.filterSettings(settingsFilter.getPatterns(), indexMetaData.settings());
9090
if (!CollectionUtils.isEmpty(request.names())) {
9191
ImmutableSettings.Builder settingsBuilder = ImmutableSettings.builder();
9292
for (Map.Entry<String, String> entry : settings.getAsMap().entrySet()) {

src/main/java/org/elasticsearch/cluster/ClusterState.java

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
import org.elasticsearch.cluster.node.DiscoveryNode;
3434
import org.elasticsearch.cluster.node.DiscoveryNodes;
3535
import org.elasticsearch.cluster.routing.*;
36-
import org.elasticsearch.cluster.routing.allocation.AllocationExplanation;
36+
3737
import org.elasticsearch.cluster.routing.allocation.RoutingAllocation;
3838
import org.elasticsearch.common.Nullable;
3939
import org.elasticsearch.common.Strings;
@@ -44,7 +44,6 @@
4444
import org.elasticsearch.common.io.stream.StreamInput;
4545
import org.elasticsearch.common.io.stream.StreamOutput;
4646
import org.elasticsearch.common.settings.Settings;
47-
import org.elasticsearch.common.settings.SettingsFilter;
4847
import org.elasticsearch.common.xcontent.ToXContent;
4948
import org.elasticsearch.common.xcontent.XContentBuilder;
5049
import org.elasticsearch.common.xcontent.XContentFactory;
@@ -134,8 +133,6 @@ public static <T extends Custom> Custom.Factory<T> lookupFactorySafe(String type
134133
// built on demand
135134
private volatile RoutingNodes routingNodes;
136135

137-
private SettingsFilter settingsFilter;
138-
139136
private volatile ClusterStateStatus status;
140137

141138
public ClusterState(long version, ClusterState state) {
@@ -234,11 +231,6 @@ public RoutingNodes readOnlyRoutingNodes() {
234231
return routingNodes;
235232
}
236233

237-
public ClusterState settingsFilter(SettingsFilter settingsFilter) {
238-
this.settingsFilter = settingsFilter;
239-
return this;
240-
}
241-
242234
public String prettyPrint() {
243235
StringBuilder sb = new StringBuilder();
244236
sb.append("version: ").append(version).append("\n");
@@ -385,9 +377,6 @@ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws
385377

386378
builder.startObject("settings");
387379
Settings settings = templateMetaData.settings();
388-
if (settingsFilter != null) {
389-
settings = settingsFilter.filterSettings(settings);
390-
}
391380
settings.toXContent(builder, params);
392381
builder.endObject();
393382

@@ -418,9 +407,6 @@ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws
418407

419408
builder.startObject("settings");
420409
Settings settings = indexMetaData.settings();
421-
if (settingsFilter != null) {
422-
settings = settingsFilter.filterSettings(settings);
423-
}
424410
settings.toXContent(builder, params);
425411
builder.endObject();
426412

src/main/java/org/elasticsearch/common/settings/ImmutableSettings.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -648,12 +648,13 @@ public static Builder settingsBuilder() {
648648

649649
@Override
650650
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
651+
Settings settings = SettingsFilter.filterSettings(params, this);
651652
if (!params.paramAsBoolean("flat_settings", false)) {
652-
for (Map.Entry<String, Object> entry : getAsStructuredMap().entrySet()) {
653+
for (Map.Entry<String, Object> entry : settings.getAsStructuredMap().entrySet()) {
653654
builder.field(entry.getKey(), entry.getValue());
654655
}
655656
} else {
656-
for (Map.Entry<String, String> entry : getAsMap().entrySet()) {
657+
for (Map.Entry<String, String> entry : settings.getAsMap().entrySet()) {
657658
builder.field(entry.getKey(), entry.getValue(), XContentBuilder.FieldCaseConversion.NONE);
658659
}
659660
}

src/main/java/org/elasticsearch/common/settings/SettingsFilter.java

Lines changed: 68 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -18,41 +18,95 @@
1818
*/
1919
package org.elasticsearch.common.settings;
2020

21+
import org.elasticsearch.common.Strings;
2122
import org.elasticsearch.common.component.AbstractComponent;
2223
import org.elasticsearch.common.inject.Inject;
24+
import org.elasticsearch.common.regex.Regex;
25+
import org.elasticsearch.common.xcontent.ToXContent.Params;
26+
import org.elasticsearch.rest.RestRequest;
2327

28+
import java.util.Iterator;
29+
import java.util.List;
30+
import java.util.Map;
31+
import java.util.Map.Entry;
2432
import java.util.concurrent.CopyOnWriteArrayList;
2533

34+
import static com.google.common.collect.Lists.newArrayList;
35+
2636
/**
2737
*
2838
*/
2939
public class SettingsFilter extends AbstractComponent {
40+
/**
41+
* Can be used to specify settings filter that will be used to filter out matching settings in toXContent method
42+
*/
43+
public static String SETTINGS_FILTER_PARAM = "settings_filter";
3044

31-
public static interface Filter {
32-
33-
void filter(ImmutableSettings.Builder settings);
34-
}
35-
36-
private final CopyOnWriteArrayList<Filter> filters = new CopyOnWriteArrayList<>();
45+
private final CopyOnWriteArrayList<String> patterns = new CopyOnWriteArrayList<>();
3746

3847
@Inject
3948
public SettingsFilter(Settings settings) {
4049
super(settings);
4150
}
4251

43-
public void addFilter(Filter filter) {
44-
filters.add(filter);
52+
/**
53+
* Adds a new simple pattern to the list of filters
54+
*
55+
* @param pattern
56+
*/
57+
public void addFilter(String pattern) {
58+
patterns.add(pattern);
4559
}
4660

47-
public void removeFilter(Filter filter) {
48-
filters.remove(filter);
61+
/**
62+
* Removes a simple pattern from the list of filters
63+
*
64+
* @param pattern
65+
*/
66+
public void removeFilter(String pattern) {
67+
patterns.remove(pattern);
4968
}
5069

51-
public Settings filterSettings(Settings settings) {
70+
public String getPatterns() {
71+
return Strings.collectionToDelimitedString(patterns, ",");
72+
}
73+
74+
public void addFilterSettingParams(RestRequest request) {
75+
if (patterns.isEmpty() == false) {
76+
request.params().put(SETTINGS_FILTER_PARAM, getPatterns());
77+
}
78+
}
79+
80+
public static Settings filterSettings(Params params, Settings settings) {
81+
String patterns = params.param(SETTINGS_FILTER_PARAM);
82+
Settings filteredSettings = settings;
83+
if (patterns != null && patterns.isEmpty() == false) {
84+
filteredSettings = SettingsFilter.filterSettings(patterns, filteredSettings);
85+
}
86+
return filteredSettings;
87+
}
88+
89+
public static Settings filterSettings(String patterns, Settings settings) {
90+
String[] patternArray = Strings.delimitedListToStringArray(patterns, ",");
5291
ImmutableSettings.Builder builder = ImmutableSettings.settingsBuilder().put(settings);
53-
for (Filter filter : filters) {
54-
filter.filter(builder);
92+
List<String> simpleMatchPatternList = newArrayList();
93+
for (String pattern : patternArray) {
94+
if (Regex.isSimpleMatchPattern(pattern)) {
95+
simpleMatchPatternList.add(pattern);
96+
} else {
97+
builder.remove(pattern);
98+
}
99+
}
100+
if (!simpleMatchPatternList.isEmpty()) {
101+
String[] simpleMatchPatterns = simpleMatchPatternList.toArray(new String[simpleMatchPatternList.size()]);
102+
Iterator<Entry<String, String>> iterator = builder.internalMap().entrySet().iterator();
103+
while (iterator.hasNext()) {
104+
Map.Entry<String, String> current = iterator.next();
105+
if (Regex.simpleMatch(simpleMatchPatterns, current.getKey())) {
106+
iterator.remove();
107+
}
108+
}
55109
}
56110
return builder.build();
57111
}
58-
}
112+
}

src/main/java/org/elasticsearch/rest/action/admin/cluster/node/info/RestNodesInfoAction.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,11 +99,12 @@ public void handleRequest(final RestRequest request, final RestChannel channel,
9999
nodesInfoRequest.plugins(metrics.contains("plugins"));
100100
}
101101

102+
settingsFilter.addFilterSettingParams(request);
103+
102104
client.admin().cluster().nodesInfo(nodesInfoRequest, new RestBuilderListener<NodesInfoResponse>(channel) {
103105

104106
@Override
105107
public RestResponse buildResponse(NodesInfoResponse response, XContentBuilder builder) throws Exception {
106-
response.settingsFilter(settingsFilter);
107108
builder.startObject();
108109
response.toXContent(builder, request);
109110
builder.endObject();

src/main/java/org/elasticsearch/rest/action/admin/cluster/reroute/RestClusterRerouteAction.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,8 @@ protected void addCustomFields(XContentBuilder builder, ClusterRerouteResponse r
7171
if (request.param("metric") == null) {
7272
request.params().put("metric", DEFAULT_METRICS);
7373
}
74-
response.getState().settingsFilter(settingsFilter).toXContent(builder, request);
74+
settingsFilter.addFilterSettingParams(request);
75+
response.getState().toXContent(builder, request);
7576
builder.endObject();
7677
if (clusterRerouteRequest.explain()) {
7778
assert response.getExplanations() != null;

src/main/java/org/elasticsearch/rest/action/admin/cluster/state/RestClusterStateAction.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,13 +76,14 @@ public void handleRequest(final RestRequest request, final RestChannel channel,
7676
clusterStateRequest.metaData(metrics.contains(ClusterState.Metric.METADATA));
7777
clusterStateRequest.blocks(metrics.contains(ClusterState.Metric.BLOCKS));
7878
}
79+
settingsFilter.addFilterSettingParams(request);
7980

8081
client.admin().cluster().state(clusterStateRequest, new RestBuilderListener<ClusterStateResponse>(channel) {
8182
@Override
8283
public RestResponse buildResponse(ClusterStateResponse response, XContentBuilder builder) throws Exception {
8384
builder.startObject();
8485
builder.field(Fields.CLUSTER_NAME, response.getClusterName().value());
85-
response.getState().settingsFilter(settingsFilter).toXContent(builder, request);
86+
response.getState().toXContent(builder, request);
8687
builder.endObject();
8788
return new BytesRestResponse(RestStatus.OK, builder);
8889
}
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
/*
2+
* Licensed to Elasticsearch under one or more contributor
3+
* license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright
5+
* ownership. Elasticsearch licenses this file to you under
6+
* the Apache License, Version 2.0 (the "License"); you may
7+
* not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
package org.elasticsearch.cluster.settings;
21+
22+
import org.elasticsearch.action.admin.indices.settings.get.GetSettingsResponse;
23+
import org.elasticsearch.common.inject.AbstractModule;
24+
import org.elasticsearch.common.inject.Inject;
25+
import org.elasticsearch.common.inject.Module;
26+
import org.elasticsearch.common.settings.ImmutableSettings;
27+
import org.elasticsearch.common.settings.Settings;
28+
import org.elasticsearch.common.settings.SettingsFilter;
29+
import org.elasticsearch.plugins.AbstractPlugin;
30+
import org.elasticsearch.test.ElasticsearchIntegrationTest;
31+
import org.elasticsearch.test.ElasticsearchIntegrationTest.ClusterScope;
32+
import org.junit.Test;
33+
34+
import java.util.Collection;
35+
36+
import static com.google.common.collect.Lists.newArrayList;
37+
import static org.elasticsearch.test.ElasticsearchIntegrationTest.Scope.SUITE;
38+
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked;
39+
import static org.hamcrest.Matchers.equalTo;
40+
import static org.hamcrest.Matchers.nullValue;
41+
42+
@ClusterScope(scope = SUITE, numDataNodes = 1)
43+
public class SettingsFilteringTests extends ElasticsearchIntegrationTest {
44+
45+
@Override
46+
protected Settings nodeSettings(int nodeOrdinal) {
47+
return ImmutableSettings.settingsBuilder()
48+
.put(super.nodeSettings(nodeOrdinal))
49+
.put("plugin.types", SettingsFilteringPlugin.class.getName())
50+
.build();
51+
}
52+
53+
public static class SettingsFilteringPlugin extends AbstractPlugin {
54+
/**
55+
* The name of the plugin.
56+
*/
57+
@Override
58+
public String name() {
59+
return "settings-filtering";
60+
}
61+
62+
/**
63+
* The description of the plugin.
64+
*/
65+
@Override
66+
public String description() {
67+
return "Settings Filtering Plugin";
68+
}
69+
70+
@Override
71+
public Collection<Class<? extends Module>> indexModules() {
72+
Collection<Class<? extends Module>> modules = newArrayList();
73+
modules.add(SettingsFilteringModule.class);
74+
return modules;
75+
}
76+
}
77+
78+
public static class SettingsFilteringModule extends AbstractModule {
79+
80+
@Override
81+
protected void configure() {
82+
bind(SettingsFilteringService.class).asEagerSingleton();
83+
}
84+
}
85+
86+
public static class SettingsFilteringService {
87+
@Inject
88+
public SettingsFilteringService(SettingsFilter settingsFilter) {
89+
settingsFilter.addFilter("index.filter_test.foo");
90+
settingsFilter.addFilter("index.filter_test.bar*");
91+
}
92+
}
93+
94+
95+
@Test
96+
public void testSettingsFiltering() {
97+
98+
assertAcked(client().admin().indices().prepareCreate("test-idx").setSettings(ImmutableSettings.builder()
99+
.put("filter_test.foo", "test")
100+
.put("filter_test.bar1", "test")
101+
.put("filter_test.bar2", "test")
102+
.put("filter_test.notbar", "test")
103+
.put("filter_test.notfoo", "test")
104+
.build()).get());
105+
GetSettingsResponse response = client().admin().indices().prepareGetSettings("test-idx").get();
106+
Settings settings = response.getIndexToSettings().get("test-idx");
107+
108+
assertThat(settings.get("index.filter_test.foo"), nullValue());
109+
assertThat(settings.get("index.filter_test.bar1"), nullValue());
110+
assertThat(settings.get("index.filter_test.bar2"), nullValue());
111+
assertThat(settings.get("index.filter_test.notbar"), equalTo("test"));
112+
assertThat(settings.get("index.filter_test.notfoo"), equalTo("test"));
113+
}
114+
115+
}

0 commit comments

Comments
 (0)