Skip to content

Commit 3e3d974

Browse files
authored
Filtering setting deprecation info API messages based on a setting (elastic#78725)
This commit adds the ability to configure a list of settings that will be ignored by the deprecation info API. Any deprecation messages for any of the settings given will be suppressed.
1 parent 83f57c3 commit 3e3d974

File tree

8 files changed

+269
-12
lines changed

8 files changed

+269
-12
lines changed

docs/reference/migration/apis/deprecation.asciidoc

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,19 @@ expressions are supported.
3939
When you specify this parameter, only deprecations for the specified
4040
data streams or indices are returned.
4141

42+
[[migration-api-settings]]
43+
==== Settings
44+
45+
You can use the following settings to control the behavior of the deprecation info API:
46+
47+
[[skip_deprecated_settings]]
48+
// tag::skip_deprecated_settings-tag[]
49+
`deprecation.skip_deprecated_settings`
50+
(<<dynamic-cluster-setting,Dynamic>>)
51+
Defaults to an empty list. Set to a list of setting names to be ignored by the deprecation info API. Any
52+
deprecations related to settings in this list will not be returned by the API. Simple wildcard matching is supported.
53+
// end::skip_deprecated_settings-tag[]
54+
4255
[[migration-api-example]]
4356
==== {api-examples-title}
4457

x-pack/plugin/deprecation/src/main/java/org/elasticsearch/xpack/deprecation/Deprecation.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
import java.util.List;
4141
import java.util.function.Supplier;
4242

43+
import static org.elasticsearch.xpack.deprecation.DeprecationChecks.SKIP_DEPRECATIONS_SETTING;
4344
import static org.elasticsearch.xpack.deprecation.logging.DeprecationIndexingComponent.WRITE_DEPRECATION_LOGS_TO_INDEX;
4445

4546
/**
@@ -94,6 +95,8 @@ public Collection<Object> createComponents(
9495

9596
@Override
9697
public List<Setting<?>> getSettings() {
97-
return org.elasticsearch.core.List.of(WRITE_DEPRECATION_LOGS_TO_INDEX);
98+
return org.elasticsearch.core.List.of(
99+
WRITE_DEPRECATION_LOGS_TO_INDEX,
100+
SKIP_DEPRECATIONS_SETTING);
98101
}
99102
}

x-pack/plugin/deprecation/src/main/java/org/elasticsearch/xpack/deprecation/DeprecationChecks.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import org.elasticsearch.cluster.ClusterState;
1111
import org.elasticsearch.cluster.metadata.IndexMetadata;
1212
import org.elasticsearch.cluster.node.DiscoveryNode;
13+
import org.elasticsearch.common.settings.Setting;
1314
import org.elasticsearch.common.settings.Settings;
1415
import org.elasticsearch.license.XPackLicenseState;
1516
import org.elasticsearch.xpack.core.deprecation.DeprecationIssue;
@@ -30,6 +31,15 @@
3031
*/
3132
public class DeprecationChecks {
3233

34+
public static final Setting<List<String>> SKIP_DEPRECATIONS_SETTING =
35+
Setting.listSetting(
36+
"deprecation.skip_deprecated_settings",
37+
Collections.emptyList(),
38+
Function.identity(),
39+
Setting.Property.NodeScope,
40+
Setting.Property.Dynamic
41+
);
42+
3343
private DeprecationChecks() {
3444
}
3545

x-pack/plugin/deprecation/src/main/java/org/elasticsearch/xpack/deprecation/DeprecationInfoAction.java

Lines changed: 40 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,12 @@
1818
import org.elasticsearch.cluster.ClusterState;
1919
import org.elasticsearch.cluster.metadata.IndexMetadata;
2020
import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver;
21+
import org.elasticsearch.cluster.metadata.Metadata;
22+
import org.elasticsearch.common.collect.ImmutableOpenMap;
2123
import org.elasticsearch.common.io.stream.StreamInput;
2224
import org.elasticsearch.common.io.stream.StreamOutput;
25+
import org.elasticsearch.common.regex.Regex;
26+
import org.elasticsearch.common.settings.Settings;
2327
import org.elasticsearch.common.util.set.Sets;
2428
import org.elasticsearch.common.xcontent.ToXContentObject;
2529
import org.elasticsearch.common.xcontent.XContentBuilder;
@@ -200,17 +204,18 @@ public static DeprecationInfoAction.Response from(ClusterState state,
200204
NodesDeprecationCheckResponse nodeDeprecationResponse,
201205
List<Function<IndexMetadata, DeprecationIssue>> indexSettingsChecks,
202206
List<Function<ClusterState, DeprecationIssue>> clusterSettingsChecks,
203-
Map<String, List<DeprecationIssue>> pluginSettingIssues) {
204-
List<DeprecationIssue> clusterSettingsIssues = filterChecks(clusterSettingsChecks,
205-
(c) -> c.apply(state));
206-
List<DeprecationIssue> nodeSettingsIssues = mergeNodeIssues(nodeDeprecationResponse);
207-
207+
Map<String, List<DeprecationIssue>> pluginSettingIssues,
208+
List<String> skipTheseDeprecatedSettings) {
208209
// Allow system index access here to prevent deprecation warnings when we call this API
209210
String[] concreteIndexNames = indexNameExpressionResolver.concreteIndexNamesWithSystemIndexAccess(state, request);
211+
ClusterState stateWithSkippedSettingsRemoved = removeSkippedSettings(state, concreteIndexNames, skipTheseDeprecatedSettings);
212+
List<DeprecationIssue> clusterSettingsIssues = filterChecks(clusterSettingsChecks,
213+
(c) -> c.apply(stateWithSkippedSettingsRemoved));
214+
List<DeprecationIssue> nodeSettingsIssues = mergeNodeIssues(nodeDeprecationResponse);
210215

211216
Map<String, List<DeprecationIssue>> indexSettingsIssues = new HashMap<>();
212217
for (String concreteIndex : concreteIndexNames) {
213-
IndexMetadata indexMetadata = state.getMetadata().index(concreteIndex);
218+
IndexMetadata indexMetadata = stateWithSkippedSettingsRemoved.getMetadata().index(concreteIndex);
214219
List<DeprecationIssue> singleIndexIssues = filterChecks(indexSettingsChecks,
215220
c -> c.apply(indexMetadata));
216221
if (singleIndexIssues.size() > 0) {
@@ -230,6 +235,35 @@ public static DeprecationInfoAction.Response from(ClusterState state,
230235
}
231236
}
232237

238+
/**
239+
*
240+
* @param state The cluster state to modify
241+
* @param indexNames The names of the indexes whose settings need to be filtered
242+
* @param skipTheseDeprecatedSettings The settings that will be removed from cluster metadata and the index metadata of all the
243+
* indexes specified by indexNames
244+
* @return A modified cluster state with the given settings removed
245+
*/
246+
private static ClusterState removeSkippedSettings(ClusterState state, String[] indexNames, List<String> skipTheseDeprecatedSettings) {
247+
ClusterState.Builder clusterStateBuilder = new ClusterState.Builder(state);
248+
Metadata.Builder metadataBuilder = new Metadata.Builder(state.metadata());
249+
metadataBuilder.transientSettings(
250+
metadataBuilder.transientSettings().filter(setting -> Regex.simpleMatch(skipTheseDeprecatedSettings, setting) == false));
251+
metadataBuilder.persistentSettings(
252+
metadataBuilder.persistentSettings().filter(setting -> Regex.simpleMatch(skipTheseDeprecatedSettings, setting) == false));
253+
ImmutableOpenMap.Builder<String, IndexMetadata> indicesBuilder = ImmutableOpenMap.builder(state.getMetadata().indices());
254+
for (String indexName : indexNames) {
255+
IndexMetadata indexMetadata = state.getMetadata().index(indexName);
256+
IndexMetadata.Builder filteredIndexMetadataBuilder = new IndexMetadata.Builder(indexMetadata);
257+
Settings filteredSettings =
258+
indexMetadata.getSettings().filter(setting -> Regex.simpleMatch(skipTheseDeprecatedSettings, setting) == false);
259+
filteredIndexMetadataBuilder.settings(filteredSettings);
260+
indicesBuilder.put(indexName, filteredIndexMetadataBuilder.build());
261+
}
262+
metadataBuilder.indices(indicesBuilder.build());
263+
clusterStateBuilder.metadata(metadataBuilder);
264+
return clusterStateBuilder.build();
265+
}
266+
233267
public static class Request extends MasterNodeReadRequest<Request> implements IndicesRequest.Replaceable {
234268

235269
private static final IndicesOptions INDICES_OPTIONS = IndicesOptions.fromOptions(false, true, true, true);

x-pack/plugin/deprecation/src/main/java/org/elasticsearch/xpack/deprecation/TransportDeprecationInfoAction.java

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ public class TransportDeprecationInfoAction extends TransportMasterNodeReadActio
4747
private final IndexNameExpressionResolver indexNameExpressionResolver;
4848
private final Settings settings;
4949
private final NamedXContentRegistry xContentRegistry;
50+
private volatile List<String> skipTheseDeprecations;
5051

5152
@Inject
5253
public TransportDeprecationInfoAction(Settings settings, TransportService transportService, ClusterService clusterService,
@@ -59,6 +60,14 @@ public TransportDeprecationInfoAction(Settings settings, TransportService transp
5960
this.indexNameExpressionResolver = indexNameExpressionResolver;
6061
this.settings = settings;
6162
this.xContentRegistry = xContentRegistry;
63+
skipTheseDeprecations = DeprecationChecks.SKIP_DEPRECATIONS_SETTING.get(settings);
64+
// Safe to register this here because it happens synchronously before the cluster service is started:
65+
clusterService.getClusterSettings().addSettingsUpdateConsumer(DeprecationChecks.SKIP_DEPRECATIONS_SETTING,
66+
this::setSkipDeprecations);
67+
}
68+
69+
private <T> void setSkipDeprecations(List<String> skipDeprecations) {
70+
this.skipTheseDeprecations = Collections.unmodifiableList(skipDeprecations);
6271
}
6372

6473
@Override
@@ -100,7 +109,8 @@ protected final void masterOperation(final DeprecationInfoAction.Request request
100109
response,
101110
INDEX_SETTINGS_CHECKS,
102111
CLUSTER_SETTINGS_CHECKS,
103-
deprecationIssues
112+
deprecationIssues,
113+
skipTheseDeprecations
104114
)
105115
);
106116
},

x-pack/plugin/deprecation/src/main/java/org/elasticsearch/xpack/deprecation/TransportNodeDeprecationCheckAction.java

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,15 @@
88
package org.elasticsearch.xpack.deprecation;
99

1010
import org.elasticsearch.action.FailedNodeException;
11+
import org.elasticsearch.action.admin.cluster.node.info.PluginsAndModules;
1112
import org.elasticsearch.action.support.ActionFilters;
1213
import org.elasticsearch.action.support.nodes.TransportNodesAction;
14+
import org.elasticsearch.cluster.ClusterState;
1315
import org.elasticsearch.cluster.node.DiscoveryNode;
1416
import org.elasticsearch.cluster.service.ClusterService;
1517
import org.elasticsearch.common.inject.Inject;
1618
import org.elasticsearch.common.io.stream.StreamInput;
19+
import org.elasticsearch.common.regex.Regex;
1720
import org.elasticsearch.common.settings.Settings;
1821
import org.elasticsearch.license.XPackLicenseState;
1922
import org.elasticsearch.plugins.PluginsService;
@@ -22,6 +25,7 @@
2225
import org.elasticsearch.xpack.core.deprecation.DeprecationIssue;
2326

2427
import java.io.IOException;
28+
import java.util.Collections;
2529
import java.util.List;
2630

2731
public class TransportNodeDeprecationCheckAction extends TransportNodesAction<NodesDeprecationCheckRequest,
@@ -32,6 +36,7 @@ public class TransportNodeDeprecationCheckAction extends TransportNodesAction<No
3236
private final Settings settings;
3337
private final XPackLicenseState licenseState;
3438
private final PluginsService pluginsService;
39+
private volatile List<String> skipTheseDeprecations;
3540

3641
@Inject
3742
public TransportNodeDeprecationCheckAction(Settings settings, ThreadPool threadPool, XPackLicenseState licenseState,
@@ -45,6 +50,14 @@ public TransportNodeDeprecationCheckAction(Settings settings, ThreadPool threadP
4550
this.settings = settings;
4651
this.pluginsService = pluginsService;
4752
this.licenseState = licenseState;
53+
skipTheseDeprecations = DeprecationChecks.SKIP_DEPRECATIONS_SETTING.get(settings);
54+
// Safe to register this here because it happens synchronously before the cluster service is started:
55+
clusterService.getClusterSettings().addSettingsUpdateConsumer(DeprecationChecks.SKIP_DEPRECATIONS_SETTING,
56+
this::setSkipDeprecations);
57+
}
58+
59+
private <T> void setSkipDeprecations(List<String> skipDeprecations) {
60+
this.skipTheseDeprecations = Collections.unmodifiableList(skipDeprecations);
4861
}
4962

5063
@Override
@@ -66,11 +79,17 @@ protected NodesDeprecationCheckAction.NodeResponse newNodeResponse(StreamInput i
6679

6780
@Override
6881
protected NodesDeprecationCheckAction.NodeResponse nodeOperation(NodesDeprecationCheckAction.NodeRequest request) {
69-
List<DeprecationIssue> issues = DeprecationInfoAction.filterChecks(DeprecationChecks.NODE_SETTINGS_CHECKS,
70-
(c) -> c.apply(settings, pluginsService.info(), clusterService.state(), licenseState));
82+
return nodeOperation(request, DeprecationChecks.NODE_SETTINGS_CHECKS);
83+
}
84+
85+
NodesDeprecationCheckAction.NodeResponse nodeOperation(NodesDeprecationCheckAction.NodeRequest request,
86+
List<DeprecationChecks.NodeDeprecationCheck<Settings, PluginsAndModules,
87+
ClusterState, XPackLicenseState, DeprecationIssue>> nodeSettingsChecks) {
88+
Settings filteredSettings = settings.filter(setting -> Regex.simpleMatch(skipTheseDeprecations, setting) == false);
89+
List<DeprecationIssue> issues = DeprecationInfoAction.filterChecks(nodeSettingsChecks,
90+
(c) -> c.apply(filteredSettings, pluginsService.info(), clusterService.state(), licenseState));
7191

7292
return new NodesDeprecationCheckAction.NodeResponse(transportService.getLocalNode(), issues);
7393
}
7494

75-
7695
}

x-pack/plugin/deprecation/src/test/java/org/elasticsearch/xpack/deprecation/DeprecationInfoActionResponseTests.java

Lines changed: 69 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import org.elasticsearch.test.AbstractWireSerializingTestCase;
2626
import org.elasticsearch.xpack.core.deprecation.DeprecationIssue;
2727
import org.elasticsearch.xpack.core.deprecation.DeprecationIssue.Level;
28+
import org.junit.Assert;
2829

2930
import java.io.IOException;
3031
import java.util.Arrays;
@@ -34,6 +35,7 @@
3435
import java.util.List;
3536
import java.util.Map;
3637
import java.util.Set;
38+
import java.util.concurrent.atomic.AtomicReference;
3739
import java.util.function.Function;
3840
import java.util.stream.Collectors;
3941
import java.util.stream.Stream;
@@ -115,7 +117,8 @@ public void testFrom() throws IOException {
115117
nodeDeprecationIssues,
116118
indexSettingsChecks,
117119
clusterSettingsChecks,
118-
Collections.emptyMap());
120+
Collections.emptyMap(),
121+
Collections.emptyList());
119122

120123
if (clusterIssueFound) {
121124
assertThat(response.getClusterSettingsIssues(), equalTo(Collections.singletonList(foundIssue)));
@@ -141,6 +144,71 @@ public void testFrom() throws IOException {
141144
}
142145
}
143146

147+
public void testRemoveSkippedSettings() throws IOException {
148+
149+
Settings.Builder settingsBuilder = settings(Version.CURRENT);
150+
settingsBuilder.put("some.deprecated.property", "someValue1");
151+
settingsBuilder.put("some.other.bad.deprecated.property", "someValue2");
152+
settingsBuilder.put("some.undeprecated.property", "someValue3");
153+
settingsBuilder.putList("some.undeprecated.list.property", org.elasticsearch.core.List.of("someValue4", "someValue5"));
154+
Settings inputSettings = settingsBuilder.build();
155+
Metadata metadata = Metadata.builder().put(IndexMetadata.builder("test")
156+
.settings(inputSettings)
157+
.numberOfShards(1)
158+
.numberOfReplicas(0))
159+
.persistentSettings(inputSettings)
160+
.build();
161+
162+
ClusterState state = ClusterState.builder(ClusterName.DEFAULT).metadata(metadata).build();
163+
IndexNameExpressionResolver resolver = TestIndexNameExpressionResolver.newInstance();
164+
AtomicReference<Settings> visibleClusterSettings = new AtomicReference<>();
165+
List<Function<ClusterState, DeprecationIssue>> clusterSettingsChecks =
166+
Collections.unmodifiableList(Arrays.asList(
167+
(s) -> {
168+
visibleClusterSettings.set(s.getMetadata().settings());
169+
return null;
170+
}
171+
));
172+
AtomicReference<Settings> visibleIndexSettings = new AtomicReference<>();
173+
List<Function<IndexMetadata, DeprecationIssue>> indexSettingsChecks =
174+
Collections.unmodifiableList(Arrays.asList(
175+
(idx) -> {
176+
visibleIndexSettings.set(idx.getSettings());
177+
return null;
178+
}
179+
));
180+
181+
NodesDeprecationCheckResponse nodeDeprecationIssues = new NodesDeprecationCheckResponse(
182+
new ClusterName(randomAlphaOfLength(5)),
183+
emptyList(),
184+
emptyList());
185+
186+
DeprecationInfoAction.Request request = new DeprecationInfoAction.Request(Strings.EMPTY_ARRAY);
187+
DeprecationInfoAction.Response.from(state,
188+
resolver,
189+
request,
190+
nodeDeprecationIssues,
191+
indexSettingsChecks,
192+
clusterSettingsChecks,
193+
Collections.emptyMap(),
194+
org.elasticsearch.core.List.of("some.deprecated.property", "some.other.*.deprecated.property"));
195+
196+
settingsBuilder = settings(Version.CURRENT);
197+
settingsBuilder.put("some.undeprecated.property", "someValue3");
198+
settingsBuilder.putList("some.undeprecated.list.property", org.elasticsearch.core.List.of("someValue4", "someValue5"));
199+
Settings expectedSettings = settingsBuilder.build();
200+
Settings resultClusterSettings = visibleClusterSettings.get();
201+
Assert.assertNotNull(resultClusterSettings);
202+
Assert.assertEquals(expectedSettings, visibleClusterSettings.get());
203+
Settings resultIndexSettings = visibleIndexSettings.get();
204+
Assert.assertNotNull(resultIndexSettings);
205+
Assert.assertTrue(resultIndexSettings.get("some.undeprecated.property").equals("someValue3"));
206+
Assert.assertTrue(resultIndexSettings.getAsList("some.undeprecated.list.property")
207+
.equals(org.elasticsearch.core.List.of("someValue4", "someValue5")));
208+
Assert.assertFalse(resultIndexSettings.hasValue("some.deprecated.property"));
209+
Assert.assertFalse(resultIndexSettings.hasValue("some.other.bad.deprecated.property"));
210+
}
211+
144212
public void testCtorFailure() {
145213
Map<String, List<DeprecationIssue>> indexNames = Stream.generate(() -> randomAlphaOfLength(10))
146214
.limit(10)

0 commit comments

Comments
 (0)