Skip to content

Commit 1a11757

Browse files
authored
#104233 Allow Watcher Node Allocation Settings (#115251) (#115330)
* Update settings endpoint modified Now accepts index.routing.allocation.* settings but denies changing the allocation setting that keeps watches on data nodes * Get settings endpoint modified Now returns index.routing.allocation.* settings explicitly filters out the `index.routing.allocation.include._tier_preference` setting * Tests for modified endpoints * Update docs
1 parent bc66d9c commit 1a11757

File tree

5 files changed

+149
-81
lines changed

5 files changed

+149
-81
lines changed

docs/reference/watcher/how-watcher-works.asciidoc

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -146,15 +146,18 @@ add, the more distributed the watches can be executed. If you add or remove
146146
replicas, all watches need to be reloaded. If a shard is relocated, the
147147
primary and all replicas of this particular shard will reload.
148148

149-
Because the watches are executed on the node, where the watch shards are, you can create
150-
dedicated watcher nodes by using shard allocation filtering.
149+
Because the watches are executed on the node, where the watch shards are, you
150+
can create dedicated watcher nodes by using shard allocation filtering. To do this
151+
, configure nodes with a dedicated `node.attr.role: watcher` property.
151152

152-
You could configure nodes with a dedicated `node.attr.role: watcher` property and
153-
then configure the `.watches` index like this:
153+
As the `.watches` index is a system index, you can't use the normal `.watcher/_settings`
154+
endpoint to modify its routing allocation. Instead, you can use the following dedicated
155+
endpoint to adjust the allocation of the `.watches` shards to the nodes with the
156+
`watcher` role attribute:
154157

155158
[source,console]
156159
------------------------
157-
PUT .watches/_settings
160+
PUT _watcher/settings
158161
{
159162
"index.routing.allocation.include.role": "watcher"
160163
}

x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/watcher/transport/actions/put/UpdateWatcherSettingsAction.java

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,13 @@
1616
import org.elasticsearch.cluster.metadata.IndexMetadata;
1717
import org.elasticsearch.common.io.stream.StreamInput;
1818
import org.elasticsearch.common.io.stream.StreamOutput;
19-
import org.elasticsearch.common.util.set.Sets;
2019
import org.elasticsearch.core.TimeValue;
2120
import org.elasticsearch.core.UpdateForV9;
2221

2322
import java.io.IOException;
2423
import java.util.Map;
2524
import java.util.Set;
25+
import java.util.stream.Collectors;
2626

2727
public class UpdateWatcherSettingsAction extends ActionType<AcknowledgedResponse> {
2828

@@ -34,6 +34,16 @@ public class UpdateWatcherSettingsAction extends ActionType<AcknowledgedResponse
3434
IndexMetadata.SETTING_AUTO_EXPAND_REPLICAS
3535
);
3636

37+
public static final Set<String> ALLOWED_SETTINGS_PREFIXES = Set.of(
38+
IndexMetadata.INDEX_ROUTING_EXCLUDE_GROUP_PREFIX,
39+
IndexMetadata.INDEX_ROUTING_INCLUDE_GROUP_PREFIX,
40+
IndexMetadata.INDEX_ROUTING_REQUIRE_GROUP_PREFIX
41+
);
42+
43+
public static final Set<String> EXPLICITLY_DENIED_SETTINGS = Set.of(
44+
IndexMetadata.INDEX_ROUTING_INCLUDE_GROUP_PREFIX + "._tier_preference"
45+
);
46+
3747
public UpdateWatcherSettingsAction() {
3848
super(NAME);
3949
}
@@ -79,13 +89,25 @@ public Map<String, Object> settings() {
7989

8090
@Override
8191
public ActionRequestValidationException validate() {
82-
Set<String> forbiddenSettings = Sets.difference(settings.keySet(), ALLOWED_SETTING_KEYS);
83-
if (forbiddenSettings.size() > 0) {
92+
Set<String> forbiddenSettings = settings.keySet()
93+
.stream()
94+
.filter(
95+
setting -> (ALLOWED_SETTING_KEYS.contains(setting) == false
96+
&& ALLOWED_SETTINGS_PREFIXES.stream().noneMatch(prefix -> setting.startsWith(prefix + ".")))
97+
|| EXPLICITLY_DENIED_SETTINGS.contains(setting)
98+
)
99+
.collect(Collectors.toSet());
100+
101+
if (forbiddenSettings.isEmpty() == false) {
84102
return ValidateActions.addValidationError(
85103
"illegal settings: "
86104
+ forbiddenSettings
87105
+ ", these settings may not be configured. Only the following settings may be configured: "
88-
+ ALLOWED_SETTING_KEYS,
106+
+ ALLOWED_SETTING_KEYS
107+
+ ", "
108+
+ ALLOWED_SETTINGS_PREFIXES.stream().map(s -> s + ".*").collect(Collectors.toSet())
109+
+ " excluding the following explicitly denied settings: "
110+
+ EXPLICITLY_DENIED_SETTINGS,
89111
null
90112
);
91113
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
---
2+
setup:
3+
- do:
4+
cluster.health:
5+
wait_for_status: yellow
6+
- do:
7+
watcher.put_watch:
8+
id: "my_watch"
9+
body: >
10+
{
11+
"trigger": {
12+
"schedule": {
13+
"hourly": {
14+
"minute": [ 0, 5 ]
15+
}
16+
}
17+
},
18+
"input": {
19+
"simple": {
20+
"payload": {
21+
"send": "yes"
22+
}
23+
}
24+
},
25+
"condition": {
26+
"always": {}
27+
},
28+
"actions": {
29+
"test_index": {
30+
"index": {
31+
"index": "test"
32+
}
33+
}
34+
}
35+
}
36+
37+
---
38+
"Test update and get watch settings api":
39+
- do:
40+
watcher.get_settings: { }
41+
42+
- match: { index.auto_expand_replicas: "0-1" }
43+
- match: { index.number_of_replicas: "0" }
44+
45+
- do:
46+
watcher.update_settings:
47+
body:
48+
index.auto_expand_replicas: "0-all"
49+
50+
- do:
51+
watcher.get_settings: { }
52+
53+
- match: { index.auto_expand_replicas: "0-all" }
54+
- is_false: index.routing.allocation.include._tier_preference
55+
56+
- do:
57+
watcher.update_settings:
58+
body:
59+
index.auto_expand_replicas: null
60+
index.number_of_replicas: 1
61+
62+
- do:
63+
watcher.get_settings: { }
64+
65+
- match: { index.number_of_replicas: "1" }
66+
---
67+
"Test disallowed setting name throws error":
68+
- requires:
69+
test_runner_features: regex
70+
- do:
71+
watcher.update_settings:
72+
body:
73+
index.disallowed_setting: "some_invalid_value"
74+
catch: bad_request
75+
- match:
76+
error:
77+
type: "action_request_validation_exception"
78+
reason: '/illegal settings\: \[index.disallowed_setting\].*/'
79+
---
80+
"Test allowed prefix setting name":
81+
- do:
82+
watcher.update_settings:
83+
body:
84+
index.routing.allocation.include.role: "watcher"
85+
index.routing.allocation.exclude.role: "noWatcher"
86+
index.routing.allocation.require.role: "mustWatcher"
87+
- do:
88+
watcher.get_settings: { }
89+
- match: { index.routing.allocation.include.role: "watcher" }
90+
- match: { index.routing.allocation.exclude.role: "noWatcher" }
91+
- match: { index.routing.allocation.require.role: "mustWatcher" }
92+
---
93+
"Test explicitly disallowed prefix setting name throws error":
94+
- requires:
95+
test_runner_features: regex
96+
- do:
97+
watcher.update_settings:
98+
body:
99+
index.routing.allocation.include.disallowed_prefix: "some_invalid_value"
100+
catch: bad_request
101+
- match:
102+
error:
103+
type: "action_request_validation_exception"
104+
reason: '/illegal settings\: \[index.routing.allocation.include.disallowed_prefix\].*/'

x-pack/plugin/watcher/qa/rest/src/yamlRestTest/resources/rest-api-spec/test/watcher/update_settings/10_update_watcher_settings.yml

Lines changed: 0 additions & 66 deletions
This file was deleted.

x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/transport/actions/TransportGetWatcherSettingsAction.java

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,10 @@
2323
import org.elasticsearch.threadpool.ThreadPool;
2424
import org.elasticsearch.transport.TransportService;
2525
import org.elasticsearch.xpack.core.watcher.transport.actions.put.GetWatcherSettingsAction;
26-
import org.elasticsearch.xpack.core.watcher.transport.actions.put.UpdateWatcherSettingsAction;
2726

27+
import static org.elasticsearch.xpack.core.watcher.transport.actions.put.UpdateWatcherSettingsAction.ALLOWED_SETTINGS_PREFIXES;
28+
import static org.elasticsearch.xpack.core.watcher.transport.actions.put.UpdateWatcherSettingsAction.ALLOWED_SETTING_KEYS;
29+
import static org.elasticsearch.xpack.core.watcher.transport.actions.put.UpdateWatcherSettingsAction.EXPLICITLY_DENIED_SETTINGS;
2830
import static org.elasticsearch.xpack.watcher.transport.actions.TransportUpdateWatcherSettingsAction.WATCHER_INDEX_NAME;
2931
import static org.elasticsearch.xpack.watcher.transport.actions.TransportUpdateWatcherSettingsAction.WATCHER_INDEX_REQUEST;
3032

@@ -73,11 +75,14 @@ protected void masterOperation(
7375
*/
7476
private static Settings filterSettableSettings(Settings settings) {
7577
Settings.Builder builder = Settings.builder();
76-
for (String settingName : UpdateWatcherSettingsAction.ALLOWED_SETTING_KEYS) {
77-
if (settings.hasValue(settingName)) {
78-
builder.put(settingName, settings.get(settingName));
79-
}
80-
}
78+
settings.keySet()
79+
.stream()
80+
.filter(
81+
setting -> (ALLOWED_SETTING_KEYS.contains(setting)
82+
|| ALLOWED_SETTINGS_PREFIXES.stream().anyMatch(prefix -> setting.startsWith(prefix + ".")))
83+
&& EXPLICITLY_DENIED_SETTINGS.contains(setting) == false
84+
)
85+
.forEach(setting -> builder.put(setting, settings.get(setting)));
8186
return builder.build();
8287
}
8388

0 commit comments

Comments
 (0)