Skip to content

Commit d7ba942

Browse files
[7.11] require master node for watcher template (#69859)
Backporting #69147 to 7.11 branch. This commit requires Watcher to install composable index templates only from the master node since during a rolling upgrade it could try to talk to a master node that predates composable index templates. Some tests have also been adjusted to that allows for this change. Those test changes have been discussed offline and can generally be summarized as the things they are testing is an edge case where if that edge case (breaking changes to the mappings of watcher history index) between versions then there would be other concerns beyond the need for which node installs the watcher templates. closes #66837 Co-authored-by: Martijn van Groningen <[email protected]> Co-authored-by: Jake Landis <[email protected]>
1 parent ce1c84f commit d7ba942

File tree

3 files changed

+19
-75
lines changed

3 files changed

+19
-75
lines changed

x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/support/WatcherIndexTemplateRegistry.java

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import java.util.Arrays;
2323
import java.util.Collections;
2424
import java.util.List;
25+
import java.util.stream.Stream;
2526

2627
import static org.elasticsearch.xpack.core.ClientHelper.WATCHER_ORIGIN;
2728

@@ -135,22 +136,23 @@ protected String getOrigin() {
135136
}
136137

137138
public static boolean validate(ClusterState state) {
138-
if(state.nodes().getMinNodeVersion().onOrAfter(Version.V_7_9_0)){
139-
return (state.getMetadata().templatesV2().containsKey(WatcherIndexTemplateRegistryField.HISTORY_TEMPLATE_NAME) ||
140-
state.getMetadata().templatesV2().containsKey(WatcherIndexTemplateRegistryField.HISTORY_TEMPLATE_NAME_NO_ILM)) &&
141-
state.getMetadata().templatesV2().containsKey(WatcherIndexTemplateRegistryField.TRIGGERED_TEMPLATE_NAME) &&
142-
state.getMetadata().templatesV2().containsKey(WatcherIndexTemplateRegistryField.WATCHES_TEMPLATE_NAME);
143-
} else if (state.nodes().getMinNodeVersion().onOrAfter(Version.V_7_7_0)) {
144-
return (state.getMetadata().getTemplates().containsKey(WatcherIndexTemplateRegistryField.HISTORY_TEMPLATE_NAME_11) ||
145-
state.getMetadata().getTemplates().containsKey(WatcherIndexTemplateRegistryField.HISTORY_TEMPLATE_NAME_NO_ILM_11)) &&
146-
state.getMetadata().getTemplates().containsKey(WatcherIndexTemplateRegistryField.TRIGGERED_TEMPLATE_NAME_11) &&
147-
state.getMetadata().getTemplates().containsKey(WatcherIndexTemplateRegistryField.WATCHES_TEMPLATE_NAME_11);
139+
final Stream<String> watcherHistoryTemplateIds;
140+
if (state.nodes().getMinNodeVersion().onOrAfter(Version.V_7_9_0)){
141+
watcherHistoryTemplateIds = state.getMetadata().templatesV2().keySet().stream();
148142
} else {
149-
return (state.getMetadata().getTemplates().containsKey(WatcherIndexTemplateRegistryField.HISTORY_TEMPLATE_NAME_10) ||
150-
state.getMetadata().getTemplates().containsKey(WatcherIndexTemplateRegistryField.HISTORY_TEMPLATE_NAME_NO_ILM_10)) &&
151-
state.getMetadata().getTemplates().containsKey(WatcherIndexTemplateRegistryField.TRIGGERED_TEMPLATE_NAME_11) &&
152-
state.getMetadata().getTemplates().containsKey(WatcherIndexTemplateRegistryField.WATCHES_TEMPLATE_NAME_11);
143+
watcherHistoryTemplateIds = Arrays.stream(state.getMetadata().getTemplates().keys().toArray(String.class));
153144
}
145+
return watcherHistoryTemplateIds.filter(s -> s.startsWith(".watch-history-"))
146+
.map(s -> Integer.valueOf(s.substring(s.lastIndexOf('-') + 1)))
147+
.anyMatch(version -> version >= 9);
154148
}
155149

150+
151+
@Override
152+
protected boolean requiresMasterNode() {
153+
// These installs a composable index template which is only supported in early versions of 7.x
154+
// In mixed cluster without this set to true can result in errors in the logs during rolling upgrades.
155+
// If these template(s) are only installed via elected master node then composable templates are available.
156+
return true;
157+
}
156158
}

x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/support/WatcherIndexTemplateRegistryTests.java

Lines changed: 0 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,6 @@
5757
import java.util.HashMap;
5858
import java.util.List;
5959
import java.util.Map;
60-
import java.util.Set;
6160
import java.util.stream.Collectors;
6261

6362
import static org.elasticsearch.mock.orig.Mockito.verify;
@@ -70,7 +69,6 @@
7069
import static org.mockito.Matchers.anyObject;
7170
import static org.mockito.Matchers.eq;
7271
import static org.mockito.Matchers.same;
73-
import static org.mockito.Mockito.atLeastOnce;
7472
import static org.mockito.Mockito.doAnswer;
7573
import static org.mockito.Mockito.mock;
7674
import static org.mockito.Mockito.spy;
@@ -256,64 +254,6 @@ public void testThatTemplatesExist() {
256254
}
257255
}
258256

259-
// if a node is newer than the master node, the template needs to be applied as well
260-
// otherwise a rolling upgrade would not work as expected, when the node has a .watches shard on it
261-
public void testThatTemplatesAreAppliedOnNewerNodes() {
262-
DiscoveryNode localNode = new DiscoveryNode("node", ESTestCase.buildNewFakeTransportAddress(), Version.CURRENT);
263-
DiscoveryNode masterNode = new DiscoveryNode("master", ESTestCase.buildNewFakeTransportAddress(), Version.V_6_0_0);
264-
DiscoveryNodes nodes = DiscoveryNodes.builder().localNodeId("node").masterNodeId("master").add(localNode).add(masterNode).build();
265-
266-
Map<String, Integer> existingTemplates = new HashMap<>();
267-
existingTemplates.put(WatcherIndexTemplateRegistryField.TRIGGERED_TEMPLATE_NAME, INDEX_TEMPLATE_VERSION);
268-
existingTemplates.put(WatcherIndexTemplateRegistryField.WATCHES_TEMPLATE_NAME, INDEX_TEMPLATE_VERSION);
269-
existingTemplates.put(".watch-history-6", 6);
270-
ClusterChangedEvent event = createClusterChangedEvent(existingTemplates, nodes);
271-
registry.clusterChanged(event);
272-
273-
ArgumentCaptor<PutComposableIndexTemplateAction.Request> argumentCaptor =
274-
ArgumentCaptor.forClass(PutComposableIndexTemplateAction.Request.class);
275-
verify(client, times(3)).execute(same(PutComposableIndexTemplateAction.INSTANCE), argumentCaptor.capture(), anyObject());
276-
assertTrue(argumentCaptor.getAllValues().stream()
277-
.anyMatch(r -> r.name().equals(WatcherIndexTemplateRegistryField.HISTORY_TEMPLATE_NAME)));
278-
}
279-
280-
public void testThatTemplatesWithHiddenAreAppliedOnNewerNodes() {
281-
DiscoveryNode node = new DiscoveryNode("node", ESTestCase.buildNewFakeTransportAddress(), Version.CURRENT);
282-
DiscoveryNode masterNode = new DiscoveryNode("master", ESTestCase.buildNewFakeTransportAddress(), Version.V_6_0_0);
283-
DiscoveryNodes nodes = DiscoveryNodes.builder().localNodeId("master").masterNodeId("master").add(node).add(masterNode).build();
284-
285-
Map<String, Integer> existingTemplates = new HashMap<>();
286-
existingTemplates.put(WatcherIndexTemplateRegistryField.TRIGGERED_TEMPLATE_NAME, INDEX_TEMPLATE_VERSION);
287-
existingTemplates.put(WatcherIndexTemplateRegistryField.WATCHES_TEMPLATE_NAME, INDEX_TEMPLATE_VERSION);
288-
existingTemplates.put(".watch-history-6", 6);
289-
ClusterChangedEvent event = createClusterChangedEvent(existingTemplates, nodes);
290-
registry.clusterChanged(event);
291-
292-
ArgumentCaptor<PutIndexTemplateRequest> argumentCaptor = ArgumentCaptor.forClass(PutIndexTemplateRequest.class);
293-
verify(client.admin().indices(), atLeastOnce()).putTemplate(argumentCaptor.capture(), anyObject());
294-
assertTrue(argumentCaptor.getAllValues().stream()
295-
.anyMatch(i -> i.name().equals(WatcherIndexTemplateRegistryField.HISTORY_TEMPLATE_NAME_10)));
296-
297-
existingTemplates.remove(".watch-history-6");
298-
existingTemplates.put(".watch-history-10", 10);
299-
masterNode = new DiscoveryNode("master", ESTestCase.buildNewFakeTransportAddress(), Version.CURRENT);
300-
nodes = DiscoveryNodes.builder().localNodeId("master").masterNodeId("master").add(masterNode).add(node).build();
301-
event = createClusterChangedEvent(existingTemplates, nodes);
302-
registry.clusterChanged(event);
303-
304-
argumentCaptor = ArgumentCaptor.forClass(PutIndexTemplateRequest.class);
305-
verify(client.admin().indices(), atLeastOnce()).putTemplate(argumentCaptor.capture(), anyObject());
306-
assertTrue(argumentCaptor.getAllValues().stream()
307-
.anyMatch(i -> i.name().equals(WatcherIndexTemplateRegistryField.HISTORY_TEMPLATE_NAME_10)));
308-
ArgumentCaptor<PutComposableIndexTemplateAction.Request> captor =
309-
ArgumentCaptor.forClass(PutComposableIndexTemplateAction.Request.class);
310-
verify(client, atLeastOnce()).execute(same(PutComposableIndexTemplateAction.INSTANCE), captor.capture(), anyObject());
311-
Set<String> templateNames =
312-
captor.getAllValues().stream().map(PutComposableIndexTemplateAction.Request::name).collect(Collectors.toSet());
313-
assertTrue(templateNames.contains(WatcherIndexTemplateRegistryField.HISTORY_TEMPLATE_NAME));
314-
assertFalse(templateNames.contains(WatcherIndexTemplateRegistryField.HISTORY_TEMPLATE_NAME_10));
315-
}
316-
317257
public void testThatTemplatesAreNotAppliedOnSameVersionNodes() {
318258
DiscoveryNode localNode = new DiscoveryNode("node", ESTestCase.buildNewFakeTransportAddress(), Version.CURRENT);
319259
DiscoveryNode masterNode = new DiscoveryNode("master", ESTestCase.buildNewFakeTransportAddress(), Version.CURRENT);

x-pack/qa/rolling-upgrade/src/test/java/org/elasticsearch/upgrades/WatcherRestartIT.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,9 @@ public void testWatcherRestart() throws Exception {
3939
client().performRequest(new Request("POST", "/_watcher/_start"));
4040
ensureWatcherStarted();
4141

42-
validateHistoryTemplate();
42+
if (CLUSTER_TYPE.equals(ClusterType.UPGRADED)) {
43+
validateHistoryTemplate();
44+
}
4345
}
4446

4547
private void validateHistoryTemplate() throws Exception {

0 commit comments

Comments
 (0)