Add user-defined cluster metadata (#33325)
Adds a place for users to store cluster-wide data they wish to associate with the cluster via the Cluster Settings API. This is strictly for user-defined data, Elasticsearch makes no other other use of these settings.
This commit is contained in:
parent
48790b0aad
commit
cfd3fa72ed
|
@ -22,6 +22,27 @@ user with access to the <<cluster-update-settings,cluster-update-settings>>
|
|||
API can make the cluster read-write again.
|
||||
|
||||
|
||||
[[user-defined-data]]
|
||||
==== User Defined Cluster Metadata
|
||||
|
||||
User-defined metadata can be stored and retrieved using the Cluster Settings API.
|
||||
This can be used to store arbitrary, infrequently-changing data about the cluster
|
||||
without the need to create an index to store it. This data may be stored using
|
||||
any key prefixed with `cluster.metadata.`. For example, to store the email
|
||||
address of the administrator of a cluster under the key `cluster.metadata.administrator`,
|
||||
issue this request:
|
||||
|
||||
[source,js]
|
||||
-------------------------------
|
||||
PUT /_cluster/settings
|
||||
{
|
||||
"persistent": {
|
||||
"cluster.metadata.administrator": "sysadmin@example.com"
|
||||
}
|
||||
}
|
||||
-------------------------------
|
||||
// CONSOLE
|
||||
|
||||
[[cluster-max-tombstones]]
|
||||
==== Index Tombstones
|
||||
|
||||
|
|
|
@ -53,6 +53,9 @@ public class ClusterService extends AbstractLifecycleComponent {
|
|||
Setting.positiveTimeSetting("cluster.service.slow_task_logging_threshold", TimeValue.timeValueSeconds(30),
|
||||
Property.Dynamic, Property.NodeScope);
|
||||
|
||||
public static final org.elasticsearch.common.settings.Setting.AffixSetting<String> USER_DEFINED_META_DATA =
|
||||
Setting.prefixKeySetting("cluster.metadata.", (key) -> Setting.simpleString(key, Property.Dynamic, Property.NodeScope));
|
||||
|
||||
private final ClusterName clusterName;
|
||||
|
||||
private final OperationRouting operationRouting;
|
||||
|
@ -67,6 +70,8 @@ public class ClusterService extends AbstractLifecycleComponent {
|
|||
this.clusterName = ClusterName.CLUSTER_NAME_SETTING.get(settings);
|
||||
this.clusterSettings.addSettingsUpdateConsumer(CLUSTER_SERVICE_SLOW_TASK_LOGGING_THRESHOLD_SETTING,
|
||||
this::setSlowTaskLoggingThreshold);
|
||||
// Add a no-op update consumer so changes are logged
|
||||
this.clusterSettings.addAffixUpdateConsumer(USER_DEFINED_META_DATA, (first, second) -> {}, (first, second) -> {});
|
||||
this.clusterApplierService = new ClusterApplierService(settings, clusterSettings, threadPool);
|
||||
}
|
||||
|
||||
|
|
|
@ -267,6 +267,7 @@ public final class ClusterSettings extends AbstractScopedSettings {
|
|||
HierarchyCircuitBreakerService.ACCOUNTING_CIRCUIT_BREAKER_OVERHEAD_SETTING,
|
||||
IndexModule.NODE_STORE_ALLOW_MMAPFS,
|
||||
ClusterService.CLUSTER_SERVICE_SLOW_TASK_LOGGING_THRESHOLD_SETTING,
|
||||
ClusterService.USER_DEFINED_META_DATA,
|
||||
SearchService.DEFAULT_SEARCH_TIMEOUT_SETTING,
|
||||
SearchService.DEFAULT_ALLOW_PARTIAL_SEARCH_RESULTS,
|
||||
ElectMasterService.DISCOVERY_ZEN_MINIMUM_MASTER_NODES_SETTING,
|
||||
|
|
|
@ -22,6 +22,7 @@ package org.elasticsearch.cluster.settings;
|
|||
import org.apache.logging.log4j.Level;
|
||||
import org.elasticsearch.action.admin.cluster.settings.ClusterUpdateSettingsRequestBuilder;
|
||||
import org.elasticsearch.action.admin.cluster.settings.ClusterUpdateSettingsResponse;
|
||||
import org.elasticsearch.action.admin.cluster.state.ClusterStateResponse;
|
||||
import org.elasticsearch.cluster.metadata.MetaData;
|
||||
import org.elasticsearch.cluster.routing.allocation.decider.EnableAllocationDecider;
|
||||
import org.elasticsearch.common.logging.ESLoggerFactory;
|
||||
|
@ -380,4 +381,34 @@ public class ClusterSettingsIT extends ESIntegTestCase {
|
|||
}
|
||||
}
|
||||
|
||||
public void testUserMetadata() {
|
||||
String key = "cluster.metadata." + randomAlphaOfLengthBetween(5, 20);
|
||||
String value = randomRealisticUnicodeOfCodepointLengthBetween(5, 50);
|
||||
String updatedValue = randomRealisticUnicodeOfCodepointLengthBetween(5, 50);
|
||||
logger.info("Attempting to store [{}]: [{}], then update to [{}]", key, value, updatedValue);
|
||||
|
||||
final Settings settings = Settings.builder().put(key, value).build();
|
||||
final Settings updatedSettings = Settings.builder().put(key, updatedValue).build();
|
||||
if (randomBoolean()) {
|
||||
logger.info("Using persistent settings");
|
||||
|
||||
client().admin().cluster().prepareUpdateSettings().setPersistentSettings(settings).execute().actionGet();
|
||||
ClusterStateResponse state = client().admin().cluster().prepareState().execute().actionGet();
|
||||
assertEquals(value, state.getState().getMetaData().persistentSettings().get(key));
|
||||
|
||||
client().admin().cluster().prepareUpdateSettings().setPersistentSettings(updatedSettings).execute().actionGet();
|
||||
ClusterStateResponse updatedState = client().admin().cluster().prepareState().execute().actionGet();
|
||||
assertEquals(updatedValue, updatedState.getState().getMetaData().persistentSettings().get(key));
|
||||
} else {
|
||||
logger.info("Using transient settings");
|
||||
client().admin().cluster().prepareUpdateSettings().setTransientSettings(settings).execute().actionGet();
|
||||
ClusterStateResponse state = client().admin().cluster().prepareState().execute().actionGet();
|
||||
assertEquals(value, state.getState().getMetaData().transientSettings().get(key));
|
||||
|
||||
client().admin().cluster().prepareUpdateSettings().setTransientSettings(updatedSettings).execute().actionGet();
|
||||
ClusterStateResponse updatedState = client().admin().cluster().prepareState().execute().actionGet();
|
||||
assertEquals(updatedValue, updatedState.getState().getMetaData().transientSettings().get(key));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue