Skip to content

Commit 74afe1e

Browse files
Adding support to register settings dynamically (#5495)
* Adding support to register settings dynamically Signed-off-by: Ryan Bogan <rbogan@amazon.com> * Update CHANGELOG Signed-off-by: Ryan Bogan <rbogan@amazon.com> * Removed unnecessary registerSetting methods Signed-off-by: Ryan Bogan <rbogan@amazon.com> * Change setting registration order Signed-off-by: Ryan Bogan <rbogan@amazon.com> * Add unregisterSettings method Signed-off-by: Ryan Bogan <rbogan@amazon.com> * Remove unnecessary feature flag Signed-off-by: Ryan Bogan <rbogan@amazon.com> Signed-off-by: Ryan Bogan <rbogan@amazon.com> (cherry picked from commit 08cd06f) Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
1 parent 816e12c commit 74afe1e

5 files changed

Lines changed: 104 additions & 2 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
1414
- Add max_shard_size parameter for shrink API ([#5229](https://github.com/opensearch-project/OpenSearch/pull/5229))
1515
- Added jackson dependency to server ([#5366] (https://github.com/opensearch-project/OpenSearch/pull/5366))
1616
- Added experimental extensions to main ([#5347](https://github.com/opensearch-project/OpenSearch/pull/5347))
17+
- Adding support to register settings dynamically ([#5495](https://github.com/opensearch-project/OpenSearch/pull/5495))
1718

1819
### Dependencies
1920
- Bump bcpg-fips from 1.0.5.1 to 1.0.7.1 ([#5148](https://github.com/opensearch-project/OpenSearch/pull/5148))

server/src/main/java/org/opensearch/common/settings/AbstractScopedSettings.java

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -121,8 +121,8 @@ protected AbstractScopedSettings(
121121
keySettings.putIfAbsent(setting.getKey(), setting);
122122
}
123123
}
124-
this.complexMatchers = Collections.unmodifiableMap(complexMatchers);
125-
this.keySettings = Collections.unmodifiableMap(keySettings);
124+
this.complexMatchers = complexMatchers;
125+
this.keySettings = keySettings;
126126
}
127127

128128
protected void validateSettingKey(Setting<?> setting) {
@@ -144,6 +144,23 @@ protected AbstractScopedSettings(Settings nodeSettings, Settings scopeSettings,
144144
settingUpdaters.addAll(other.settingUpdaters);
145145
}
146146

147+
public boolean registerSetting(Setting<?> setting) {
148+
validateSettingKey(setting);
149+
if (setting.hasComplexMatcher()) {
150+
return setting != complexMatchers.putIfAbsent(setting.getKey(), setting);
151+
} else {
152+
return setting != keySettings.putIfAbsent(setting.getKey(), setting);
153+
}
154+
}
155+
156+
public boolean unregisterSetting(Setting<?> setting) {
157+
if (setting.hasComplexMatcher()) {
158+
return setting != complexMatchers.remove(setting.getKey());
159+
} else {
160+
return setting != keySettings.remove(setting.getKey());
161+
}
162+
}
163+
147164
/**
148165
* Returns <code>true</code> iff the given key is a valid settings key otherwise <code>false</code>
149166
*/

server/src/main/java/org/opensearch/common/settings/SettingsModule.java

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,45 @@ public void configure(Binder binder) {
179179
binder.bind(IndexScopedSettings.class).toInstance(indexScopedSettings);
180180
}
181181

182+
/**
183+
* Dynamically registers a new Setting at Runtime. This method is mostly used by plugins/extensions
184+
* to register new settings at runtime. Settings can be of Node Scope or Index Scope.
185+
* @param setting which is being registered in the cluster.
186+
* @return boolean value is set to true when successfully registered, else returns false
187+
*/
188+
public boolean registerDynamicSetting(Setting<?> setting) {
189+
boolean onNodeSetting = false;
190+
boolean onIndexSetting = false;
191+
try {
192+
if (setting.hasNodeScope()) {
193+
onNodeSetting = clusterSettings.registerSetting(setting);
194+
}
195+
if (setting.hasIndexScope()) {
196+
onIndexSetting = indexScopedSettings.registerSetting(setting);
197+
}
198+
try {
199+
registerSetting(setting);
200+
if (onNodeSetting || onIndexSetting) {
201+
logger.info("Registered new Setting: " + setting.getKey() + " successfully ");
202+
return true;
203+
}
204+
} catch (IllegalArgumentException ex) {
205+
if (onNodeSetting) {
206+
clusterSettings.unregisterSetting(setting);
207+
}
208+
209+
if (onIndexSetting) {
210+
indexScopedSettings.unregisterSetting(setting);
211+
}
212+
throw ex;
213+
}
214+
} catch (Exception e) {
215+
logger.error("Could not register setting " + setting.getKey());
216+
throw new SettingsException("Could not register setting:" + setting.getKey());
217+
}
218+
return false;
219+
}
220+
182221
/**
183222
* Registers a new setting. This method should be used by plugins in order to expose any custom settings the plugin defines.
184223
* Unless a setting is registered the setting is unusable. If a setting is never the less specified the node will reject

server/src/test/java/org/opensearch/common/settings/SettingsModuleTests.java

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434

3535
import org.opensearch.common.inject.ModuleTestCase;
3636
import org.opensearch.common.settings.Setting.Property;
37+
import org.opensearch.common.util.FeatureFlagTests;
3738
import org.hamcrest.Matchers;
3839

3940
import java.util.Arrays;
@@ -237,4 +238,47 @@ public void testOldMaxClauseCountSetting() {
237238
ex.getMessage()
238239
);
239240
}
241+
242+
public void testDynamicNodeSettingsRegistration() {
243+
FeatureFlagTests.enableFeature();
244+
Settings settings = Settings.builder().put("some.custom.setting", "2.0").build();
245+
SettingsModule module = new SettingsModule(settings, Setting.floatSetting("some.custom.setting", 1.0f, Property.NodeScope));
246+
assertNotNull(module.getClusterSettings().get("some.custom.setting"));
247+
// For unregistered setting the value is expected to be null
248+
assertNull(module.getClusterSettings().get("some.custom.setting2"));
249+
assertInstanceBinding(module, Settings.class, (s) -> s == settings);
250+
251+
assertTrue(module.registerDynamicSetting(Setting.floatSetting("some.custom.setting2", 1.0f, Property.NodeScope)));
252+
assertNotNull(module.getClusterSettings().get("some.custom.setting2"));
253+
// verify if some.custom.setting still exists
254+
assertNotNull(module.getClusterSettings().get("some.custom.setting"));
255+
256+
// verify exception is thrown when setting registration fails
257+
expectThrows(
258+
SettingsException.class,
259+
() -> module.registerDynamicSetting(Setting.floatSetting("some.custom.setting", 1.0f, Property.NodeScope))
260+
);
261+
}
262+
263+
public void testDynamicIndexSettingsRegistration() {
264+
FeatureFlagTests.enableFeature();
265+
Settings settings = Settings.builder().put("some.custom.setting", "2.0").build();
266+
SettingsModule module = new SettingsModule(settings, Setting.floatSetting("some.custom.setting", 1.0f, Property.NodeScope));
267+
assertNotNull(module.getClusterSettings().get("some.custom.setting"));
268+
// For unregistered setting the value is expected to be null
269+
assertNull(module.getIndexScopedSettings().get("index.custom.setting2"));
270+
assertInstanceBinding(module, Settings.class, (s) -> s == settings);
271+
272+
assertTrue(module.registerDynamicSetting(Setting.floatSetting("index.custom.setting2", 1.0f, Property.IndexScope)));
273+
assertNotNull(module.getIndexScopedSettings().get("index.custom.setting2"));
274+
275+
// verify if some.custom.setting still exists
276+
assertNotNull(module.getClusterSettings().get("some.custom.setting"));
277+
278+
// verify exception is thrown when setting registration fails
279+
expectThrows(
280+
SettingsException.class,
281+
() -> module.registerDynamicSetting(Setting.floatSetting("index.custom.setting2", 1.0f, Property.IndexScope))
282+
);
283+
}
240284
}

server/src/test/java/org/opensearch/common/util/FeatureFlagTests.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,4 +48,5 @@ public void testRemoteStoreFeatureFlag() {
4848
assertNotNull(System.getProperty(remoteStoreFlag));
4949
assertTrue(FeatureFlags.isEnabled(remoteStoreFlag));
5050
}
51+
5152
}

0 commit comments

Comments
 (0)