Skip to content

Commit

Permalink
Add user-defined cluster metadata (#33325)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
gwbrown committed Sep 5, 2018
1 parent 1498b7c commit 435bd33
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 0 deletions.
21 changes: 21 additions & 0 deletions docs/reference/modules/cluster/misc.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -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": "[email protected]"
}
}
-------------------------------
// CONSOLE

[[cluster-max-tombstones]]
==== Index Tombstones

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,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;
Expand All @@ -68,6 +71,8 @@ public ClusterService(Settings settings, ClusterSettings clusterSettings, Thread
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.initialClusterStateCustoms = initialClusterStateCustoms;
this.clusterApplierService = new ClusterApplierService(settings, clusterSettings, threadPool, this::newClusterStateBuilder);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,7 @@ public void apply(Settings value, Settings current, Settings previous) {
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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
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;
Expand Down Expand Up @@ -380,4 +381,34 @@ public void testLoggerLevelUpdate() {
}
}

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));
}
}

}

0 comments on commit 435bd33

Please sign in to comment.