From c749014ce0fb473dd4da8ff70ab289ee8590cb3a Mon Sep 17 00:00:00 2001 From: Lee Hinman Date: Wed, 27 Feb 2019 11:11:22 -0700 Subject: [PATCH] Use non-ILM template setting up watch history template & ILM disabled (#39421) Backport of #39325 When ILM is disabled and Watcher is setting up the templates and policies for the watch history indices, it will now use a template that does not have the `index.lifecycle.name` setting, so that indices are not created with the setting. This also adds tests for the behavior, and changes the cluster state used in these tests to be real instead of mocked. Resolves #38805 --- .../WatcherIndexTemplateRegistryField.java | 1 + .../main/resources/watch-history-no-ilm.json | 615 ++++++++++++++++++ .../support/WatcherIndexTemplateRegistry.java | 17 +- .../WatcherIndexTemplateRegistryTests.java | 100 ++- 4 files changed, 706 insertions(+), 27 deletions(-) create mode 100644 x-pack/plugin/core/src/main/resources/watch-history-no-ilm.json diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/watcher/support/WatcherIndexTemplateRegistryField.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/watcher/support/WatcherIndexTemplateRegistryField.java index b42506b81b3d4..ac4b950ea0524 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/watcher/support/WatcherIndexTemplateRegistryField.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/watcher/support/WatcherIndexTemplateRegistryField.java @@ -17,6 +17,7 @@ public final class WatcherIndexTemplateRegistryField { // Note: if you change this, also inform the kibana team around the watcher-ui public static final String INDEX_TEMPLATE_VERSION = "9"; public static final String HISTORY_TEMPLATE_NAME = ".watch-history-" + INDEX_TEMPLATE_VERSION; + public static final String HISTORY_TEMPLATE_NAME_NO_ILM = ".watch-history-no-ilm-" + INDEX_TEMPLATE_VERSION; public static final String TRIGGERED_TEMPLATE_NAME = ".triggered_watches"; public static final String WATCHES_TEMPLATE_NAME = ".watches"; public static final String[] TEMPLATE_NAMES = new String[] { diff --git a/x-pack/plugin/core/src/main/resources/watch-history-no-ilm.json b/x-pack/plugin/core/src/main/resources/watch-history-no-ilm.json new file mode 100644 index 0000000000000..8e91e02549c3c --- /dev/null +++ b/x-pack/plugin/core/src/main/resources/watch-history-no-ilm.json @@ -0,0 +1,615 @@ +{ + "index_patterns": [ ".watcher-history-${xpack.watcher.template.version}*" ], + "order": 2147483646, + "settings": { + "index.number_of_shards": 1, + "index.number_of_replicas": 0, + "index.auto_expand_replicas": "0-1", + "index.format": 6 + }, + "mappings": { + "doc": { + "_meta": { + "watcher-history-version": "${xpack.watcher.template.version}" + }, + "dynamic_templates": [ + { + "disabled_payload_fields": { + "path_match": "result\\.(input(\\..+)*|(transform(\\..+)*)|(actions\\.transform(\\..+)*))\\.payload", + "match_pattern": "regex", + "mapping": { + "type": "object", + "enabled": false + } + } + }, + { + "disabled_search_request_body_fields": { + "path_match": "result\\.(input(\\..+)*|(transform(\\..+)*)|(actions\\.transform(\\..+)*))\\.search\\.request\\.(body|template)", + "match_pattern": "regex", + "mapping": { + "type": "object", + "enabled": false + } + } + }, + { + "disabled_exception_fields": { + "path_match": "result\\.(input(\\..+)*|(transform(\\..+)*)|(actions\\.transform(\\..+)*)|actions)\\.error", + "match_pattern": "regex", + "mapping": { + "type": "object", + "enabled": false + } + } + }, + { + "disabled_jira_custom_fields": { + "path_match": "result.actions.jira.fields.customfield_*", + "mapping": { + "type": "object", + "enabled": false + } + } + } + ], + "dynamic": false, + "properties": { + "watch_id": { + "type": "keyword" + }, + "node": { + "type": "keyword" + }, + "trigger_event": { + "type": "object", + "dynamic": true, + "properties": { + "type" : { + "type" : "keyword" + }, + "triggered_time": { + "type": "date" + }, + "manual": { + "type": "object", + "dynamic": true, + "properties": { + "schedule": { + "type": "object", + "dynamic": true, + "properties": { + "scheduled_time": { + "type": "date" + } + } + } + } + }, + "schedule": { + "type": "object", + "dynamic": true, + "properties": { + "scheduled_time": { + "type": "date" + } + } + } + } + }, + "vars" : { + "type" : "object", + "enabled" : false + }, + "input": { + "type": "object", + "enabled": false + }, + "condition": { + "type": "object", + "enabled": false + }, + "state": { + "type": "keyword" + }, + "status": { + "type": "object", + "enabled" : false, + "dynamic" : true + }, + "messages": { + "type": "text" + }, + "user": { + "type": "text" + }, + "exception" : { + "type" : "object", + "enabled" : false + }, + "result": { + "type": "object", + "dynamic": true, + "properties": { + "execution_time": { + "type": "date" + }, + "execution_duration": { + "type": "long" + }, + "input": { + "type": "object", + "dynamic": true, + "properties": { + "type" : { + "type" : "keyword" + }, + "status" : { + "type" : "keyword" + }, + "payload" : { + "type" : "object", + "enabled" : false + }, + "search": { + "type": "object", + "dynamic": true, + "properties": { + "request": { + "type": "object", + "dynamic": true, + "properties": { + "search_type": { + "type": "keyword" + }, + "indices": { + "type": "keyword" + }, + "types": { + "type": "keyword" + } + } + } + } + }, + "http": { + "type": "object", + "dynamic": true, + "properties": { + "request": { + "type": "object", + "dynamic": true, + "properties": { + "path": { + "type": "keyword" + }, + "host": { + "type": "keyword" + } + } + } + } + } + } + }, + "condition" : { + "type" : "object", + "dynamic" : true, + "properties" : { + "type" : { + "type" : "keyword" + }, + "status" : { + "type" : "keyword" + }, + "met" : { + "type" : "boolean" + }, + "compare" : { + "type" : "object", + "enabled" : false + }, + "array_compare" : { + "type" : "object", + "enabled" : false + }, + "script" : { + "type" : "object", + "enabled" : false + } + } + }, + "transform" : { + "type" : "object", + "dynamic" : true, + "properties" : { + "type" : { + "type" : "keyword" + }, + "search" : { + "type" : "object", + "dynamic" : true, + "properties" : { + "request" : { + "type" : "object", + "dynamic" : true, + "properties" : { + "indices" : { + "type" : "keyword" + }, + "types" : { + "type" : "keyword" + } + } + } + } + } + } + }, + "actions": { + "type": "nested", + "include_in_parent": true, + "dynamic": true, + "properties": { + "id" : { + "type" : "keyword" + }, + "type" : { + "type" : "keyword" + }, + "status" : { + "type" : "keyword" + }, + "reason" : { + "type" : "keyword" + }, + "email": { + "type": "object", + "dynamic": true, + "properties": { + "message": { + "type": "object", + "dynamic": true, + "properties": { + "id": { + "type": "keyword" + }, + "from": { + "type": "keyword" + }, + "reply_to": { + "type": "keyword" + }, + "to": { + "type": "keyword" + }, + "cc": { + "type": "keyword" + }, + "bcc": { + "type": "keyword" + } + } + } + } + }, + "webhook": { + "type": "object", + "dynamic": true, + "properties": { + "request": { + "type": "object", + "dynamic": true, + "properties": { + "path": { + "type": "keyword" + }, + "host": { + "type": "keyword" + } + } + } + } + }, + "index": { + "type": "object", + "dynamic": true, + "properties": { + "response": { + "type": "object", + "dynamic": true, + "properties": { + "index": { + "type": "keyword" + }, + "type": { + "type": "keyword" + }, + "id": { + "type": "keyword" + } + } + } + } + }, + "hipchat" : { + "type": "object", + "dynamic": true, + "properties": { + "account": { + "type": "keyword" + }, + "sent_messages": { + "type": "nested", + "include_in_parent": true, + "dynamic": true, + "properties": { + "status": { + "type": "keyword" + }, + "reason": { + "type": "text" + }, + "request" : { + "type" : "object", + "enabled" : false + }, + "response" : { + "type" : "object", + "enabled" : false + }, + "room" : { + "type": "keyword" + }, + "user" : { + "type": "keyword" + }, + "message" : { + "type" : "object", + "dynamic" : true, + "properties" : { + "message_format" : { + "type" : "keyword" + }, + "color" : { + "type" : "keyword" + }, + "notify" : { + "type" : "boolean" + }, + "message" : { + "type" : "text" + }, + "from" : { + "type" : "text" + } + } + } + } + } + } + }, + "jira" : { + "type": "object", + "dynamic": true, + "properties": { + "account": { + "type": "keyword" + }, + "reason": { + "type": "text" + }, + "request" : { + "type" : "object", + "enabled" : false + }, + "response" : { + "type" : "object", + "enabled" : false + }, + "fields": { + "type": "object", + "dynamic": true, + "properties": { + "summary": { + "type": "text" + }, + "description": { + "type": "text" + }, + "labels" : { + "type": "text" + }, + "project" : { + "type" : "object", + "dynamic" : true, + "properties" : { + "key" : { + "type" : "keyword" + }, + "id" : { + "type" : "keyword" + } + } + }, + "issuetype" : { + "type" : "object", + "dynamic" : true, + "properties" : { + "name" : { + "type": "keyword" + }, + "id" : { + "type" : "keyword" + } + } + } + } + }, + "result": { + "type": "object", + "dynamic": true, + "properties" : { + "id" : { + "type" : "keyword" + }, + "key" : { + "type" : "keyword" + }, + "self" : { + "type" : "keyword" + } + } + } + } + }, + "slack" : { + "type": "object", + "dynamic": true, + "properties": { + "account": { + "type": "keyword" + }, + "sent_messages": { + "type": "nested", + "include_in_parent": true, + "dynamic": true, + "properties": { + "status": { + "type": "keyword" + }, + "reason": { + "type": "text" + }, + "request" : { + "type" : "object", + "enabled" : false + }, + "response" : { + "type" : "object", + "enabled" : false + }, + "to" : { + "type": "keyword" + }, + "message" : { + "type" : "object", + "dynamic" : true, + "properties" : { + "from" : { + "type" : "text" + }, + "icon" : { + "type" : "keyword" + }, + "text" : { + "type" : "text" + }, + "attachments" : { + "type" : "nested", + "include_in_parent": true, + "dynamic" : true, + "properties" : { + "color" : { + "type" : "keyword" + }, + "fields" : { + "properties" : { + "value" : { + "type" : "text" + } + } + } + } + } + } + } + } + } + } + }, + "pagerduty" : { + "type": "object", + "dynamic": true, + "properties": { + "account": { + "type": "keyword" + }, + "sent_event": { + "type": "nested", + "include_in_parent": true, + "dynamic": true, + "properties": { + "reason": { + "type": "text" + }, + "request" : { + "type" : "object", + "enabled" : false + }, + "response" : { + "type" : "object", + "enabled" : false + }, + "event" : { + "type" : "object", + "dynamic" : true, + "properties" : { + "type" : { + "type" : "keyword" + }, + "client" : { + "type" : "text" + }, + "client_url" : { + "type" : "keyword" + }, + "account" : { + "type" : "keyword" + }, + "attach_payload" : { + "type" : "boolean" + }, + "incident_key" : { + "type" : "keyword" + }, + "description" : { + "type" : "text" + }, + "context" : { + "type" : "nested", + "include_in_parent": true, + "dynamic" : true, + "properties" : { + "type" : { + "type" : "keyword" + }, + "href" : { + "type" : "keyword" + }, + "src" : { + "type" : "keyword" + }, + "alt" : { + "type" : "text" + } + } + } + } + } + } + } + } + } + } + } + } + }, + "metadata": { + "type": "object", + "dynamic": true + } + } + } + } +} diff --git a/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/support/WatcherIndexTemplateRegistry.java b/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/support/WatcherIndexTemplateRegistry.java index 0fdb2b3a17d13..735bf04c7216f 100644 --- a/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/support/WatcherIndexTemplateRegistry.java +++ b/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/support/WatcherIndexTemplateRegistry.java @@ -23,6 +23,7 @@ import org.elasticsearch.gateway.GatewayService; import org.elasticsearch.threadpool.ThreadPool; import org.elasticsearch.xpack.core.XPackClient; +import org.elasticsearch.xpack.core.XPackSettings; import org.elasticsearch.xpack.core.indexlifecycle.IndexLifecycleMetadata; import org.elasticsearch.xpack.core.indexlifecycle.LifecyclePolicy; import org.elasticsearch.xpack.core.indexlifecycle.LifecyclePolicyUtils; @@ -46,11 +47,16 @@ public class WatcherIndexTemplateRegistry implements ClusterStateListener { public static final TemplateConfig TEMPLATE_CONFIG_TRIGGERED_WATCHES = new TemplateConfig( WatcherIndexTemplateRegistryField.TRIGGERED_TEMPLATE_NAME, "triggered-watches"); public static final TemplateConfig TEMPLATE_CONFIG_WATCH_HISTORY = new TemplateConfig( - WatcherIndexTemplateRegistryField.HISTORY_TEMPLATE_NAME, "watch-history"); + WatcherIndexTemplateRegistryField.HISTORY_TEMPLATE_NAME, "watch-history"); + public static final TemplateConfig TEMPLATE_CONFIG_WATCH_HISTORY_NO_ILM = new TemplateConfig( + WatcherIndexTemplateRegistryField.HISTORY_TEMPLATE_NAME_NO_ILM, "watch-history-no-ilm"); public static final TemplateConfig TEMPLATE_CONFIG_WATCHES = new TemplateConfig( WatcherIndexTemplateRegistryField.WATCHES_TEMPLATE_NAME, "watches"); public static final TemplateConfig[] TEMPLATE_CONFIGS = new TemplateConfig[]{ - TEMPLATE_CONFIG_TRIGGERED_WATCHES, TEMPLATE_CONFIG_WATCH_HISTORY, TEMPLATE_CONFIG_WATCHES + TEMPLATE_CONFIG_TRIGGERED_WATCHES, TEMPLATE_CONFIG_WATCH_HISTORY, TEMPLATE_CONFIG_WATCHES + }; + public static final TemplateConfig[] TEMPLATE_CONFIGS_NO_ILM = new TemplateConfig[]{ + TEMPLATE_CONFIG_TRIGGERED_WATCHES, TEMPLATE_CONFIG_WATCH_HISTORY_NO_ILM, TEMPLATE_CONFIG_WATCHES }; public static final PolicyConfig POLICY_WATCH_HISTORY = new PolicyConfig("watch-history-ilm-policy", "/watch-history-ilm-policy.json"); @@ -59,7 +65,6 @@ public class WatcherIndexTemplateRegistry implements ClusterStateListener { private final Client client; private final ThreadPool threadPool; - private final TemplateConfig[] indexTemplates; private final NamedXContentRegistry xContentRegistry; private final ConcurrentMap templateCreationsInProgress = new ConcurrentHashMap<>(); private final AtomicBoolean historyPolicyCreationInProgress = new AtomicBoolean(); @@ -68,7 +73,6 @@ public WatcherIndexTemplateRegistry(ClusterService clusterService, ThreadPool th NamedXContentRegistry xContentRegistry) { this.client = client; this.threadPool = threadPool; - this.indexTemplates = TEMPLATE_CONFIGS; this.xContentRegistry = xContentRegistry; clusterService.addListener(this); } @@ -100,6 +104,8 @@ public void clusterChanged(ClusterChangedEvent event) { } private void addTemplatesIfMissing(ClusterState state) { + boolean ilmSupported = XPackSettings.INDEX_LIFECYCLE_ENABLED.get(state.metaData().settings()); + final TemplateConfig[] indexTemplates = ilmSupported ? TEMPLATE_CONFIGS : TEMPLATE_CONFIGS_NO_ILM; for (TemplateConfig template : indexTemplates) { final String templateName = template.getTemplateName(); final AtomicBoolean creationCheck = templateCreationsInProgress.computeIfAbsent(templateName, key -> new AtomicBoolean(false)); @@ -147,7 +153,8 @@ LifecyclePolicy loadWatcherHistoryPolicy() { } private void addIndexLifecyclePolicyIfMissing(ClusterState state) { - if (historyPolicyCreationInProgress.compareAndSet(false, true)) { + boolean ilmSupported = XPackSettings.INDEX_LIFECYCLE_ENABLED.get(state.metaData().settings()); + if (ilmSupported && historyPolicyCreationInProgress.compareAndSet(false, true)) { final LifecyclePolicy policyOnDisk = loadWatcherHistoryPolicy(); Optional maybeMeta = Optional.ofNullable(state.metaData().custom(IndexLifecycleMetadata.TYPE)); diff --git a/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/support/WatcherIndexTemplateRegistryTests.java b/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/support/WatcherIndexTemplateRegistryTests.java index 60ca2b83b2f85..7ede531305348 100644 --- a/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/support/WatcherIndexTemplateRegistryTests.java +++ b/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/support/WatcherIndexTemplateRegistryTests.java @@ -31,14 +31,16 @@ import org.elasticsearch.common.xcontent.NamedXContentRegistry; import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.common.xcontent.XContentType; -import org.elasticsearch.gateway.GatewayService; import org.elasticsearch.test.ESTestCase; import org.elasticsearch.threadpool.ThreadPool; +import org.elasticsearch.xpack.core.XPackSettings; import org.elasticsearch.xpack.core.indexlifecycle.DeleteAction; import org.elasticsearch.xpack.core.indexlifecycle.IndexLifecycleMetadata; import org.elasticsearch.xpack.core.indexlifecycle.LifecycleAction; import org.elasticsearch.xpack.core.indexlifecycle.LifecyclePolicy; +import org.elasticsearch.xpack.core.indexlifecycle.LifecyclePolicyMetadata; import org.elasticsearch.xpack.core.indexlifecycle.LifecycleType; +import org.elasticsearch.xpack.core.indexlifecycle.OperationMode; import org.elasticsearch.xpack.core.indexlifecycle.TimeseriesLifecycleType; import org.elasticsearch.xpack.core.indexlifecycle.action.PutLifecycleAction; import org.elasticsearch.xpack.core.watcher.support.WatcherIndexTemplateRegistryField; @@ -52,15 +54,18 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.stream.Collectors; import static org.elasticsearch.mock.orig.Mockito.verify; import static org.elasticsearch.mock.orig.Mockito.when; +import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.is; import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyObject; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.spy; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verifyZeroInteractions; @@ -110,9 +115,35 @@ public void testThatNonExistingTemplatesAreAddedImmediately() { // now delete one template from the cluster state and lets retry ClusterChangedEvent newEvent = createClusterChangedEvent(Arrays.asList(WatcherIndexTemplateRegistryField.HISTORY_TEMPLATE_NAME, - WatcherIndexTemplateRegistryField.TRIGGERED_TEMPLATE_NAME), nodes); + WatcherIndexTemplateRegistryField.TRIGGERED_TEMPLATE_NAME), nodes); registry.clusterChanged(newEvent); - verify(client.admin().indices(), times(4)).putTemplate(argumentCaptor.capture(), anyObject()); + ArgumentCaptor captor = ArgumentCaptor.forClass(PutIndexTemplateRequest.class); + verify(client.admin().indices(), times(4)).putTemplate(captor.capture(), anyObject()); + PutIndexTemplateRequest req = captor.getAllValues().stream() + .filter(r -> r.name().equals(WatcherIndexTemplateRegistryField.HISTORY_TEMPLATE_NAME)) + .findFirst() + .orElseThrow(() -> new AssertionError("expected the watch history template to be put")); + assertThat(req.settings().get("index.lifecycle.name"), equalTo("watch-history-ilm-policy")); + } + + public void testThatNonExistingTemplatesAreAddedEvenWithILMDisabled() { + DiscoveryNode node = new DiscoveryNode("node", ESTestCase.buildNewFakeTransportAddress(), Version.CURRENT); + DiscoveryNodes nodes = DiscoveryNodes.builder().localNodeId("node").masterNodeId("node").add(node).build(); + + ClusterChangedEvent event = createClusterChangedEvent(Settings.builder() + .put(XPackSettings.INDEX_LIFECYCLE_ENABLED.getKey(), false).build(), + Collections.emptyList(), Collections.emptyMap(), nodes); + registry.clusterChanged(event); + ArgumentCaptor argumentCaptor = ArgumentCaptor.forClass(PutIndexTemplateRequest.class); + verify(client.admin().indices(), times(3)).putTemplate(argumentCaptor.capture(), anyObject()); + + // now delete one template from the cluster state and lets retry + ClusterChangedEvent newEvent = createClusterChangedEvent(Arrays.asList(WatcherIndexTemplateRegistryField.HISTORY_TEMPLATE_NAME, + WatcherIndexTemplateRegistryField.TRIGGERED_TEMPLATE_NAME), nodes); + registry.clusterChanged(newEvent); + ArgumentCaptor captor = ArgumentCaptor.forClass(PutIndexTemplateRequest.class); + verify(client.admin().indices(), times(4)).putTemplate(captor.capture(), anyObject()); + captor.getAllValues().forEach(req -> assertNull(req.settings().get("index.lifecycle.name"))); } public void testThatNonExistingPoliciesAreAddedImmediately() { @@ -136,6 +167,17 @@ public void testPolicyAlreadyExists() { verify(client, times(0)).execute(eq(PutLifecycleAction.INSTANCE), anyObject(), anyObject()); } + public void testNoPolicyButILMDisabled() { + DiscoveryNode node = new DiscoveryNode("node", ESTestCase.buildNewFakeTransportAddress(), Version.CURRENT); + DiscoveryNodes nodes = DiscoveryNodes.builder().localNodeId("node").masterNodeId("node").add(node).build(); + + ClusterChangedEvent event = createClusterChangedEvent(Settings.builder() + .put(XPackSettings.INDEX_LIFECYCLE_ENABLED.getKey(), false).build(), + Collections.emptyList(), Collections.emptyMap(), nodes); + registry.clusterChanged(event); + verify(client, times(0)).execute(eq(PutLifecycleAction.INSTANCE), anyObject(), anyObject()); + } + public void testPolicyAlreadyExistsButDiffers() throws IOException { DiscoveryNode node = new DiscoveryNode("node", ESTestCase.buildNewFakeTransportAddress(), Version.CURRENT); DiscoveryNodes nodes = DiscoveryNodes.builder().localNodeId("node").masterNodeId("node").add(node).build(); @@ -206,31 +248,45 @@ private ClusterChangedEvent createClusterChangedEvent(List existingTempl return createClusterChangedEvent(existingTemplateNames, Collections.emptyMap(), nodes); } - private ClusterChangedEvent createClusterChangedEvent(List existingTemplateNames, - Map existingPolicies, - DiscoveryNodes nodes) { - ClusterChangedEvent event = mock(ClusterChangedEvent.class); - when(event.localNodeMaster()).thenReturn(nodes.isLocalNodeElectedMaster()); - ClusterState cs = mock(ClusterState.class); - ClusterBlocks clusterBlocks = mock(ClusterBlocks.class); - when(clusterBlocks.hasGlobalBlock(eq(GatewayService.STATE_NOT_RECOVERED_BLOCK))).thenReturn(false); - when(cs.blocks()).thenReturn(clusterBlocks); - when(event.state()).thenReturn(cs); - - when(cs.getNodes()).thenReturn(nodes); - - MetaData metaData = mock(MetaData.class); + private ClusterState createClusterState(Settings nodeSettings, + List existingTemplateNames, + Map existingPolicies, + DiscoveryNodes nodes) { ImmutableOpenMap.Builder indexTemplates = ImmutableOpenMap.builder(); for (String name : existingTemplateNames) { indexTemplates.put(name, mock(IndexTemplateMetaData.class)); } - when(metaData.getTemplates()).thenReturn(indexTemplates.build()); + Map existingILMMeta = existingPolicies.entrySet().stream() + .collect(Collectors.toMap(Map.Entry::getKey, e -> new LifecyclePolicyMetadata(e.getValue(), Collections.emptyMap(), 1, 1))); + IndexLifecycleMetadata ilmMeta = new IndexLifecycleMetadata(existingILMMeta, OperationMode.RUNNING); + + return ClusterState.builder(new ClusterName("test")) + .metaData(MetaData.builder() + .templates(indexTemplates.build()) + .transientSettings(nodeSettings) + .putCustom(IndexLifecycleMetadata.TYPE, ilmMeta) + .build()) + .blocks(new ClusterBlocks.Builder().build()) + .nodes(nodes) + .build(); + } - IndexLifecycleMetadata ilmMeta = mock(IndexLifecycleMetadata.class); - when(ilmMeta.getPolicies()).thenReturn(existingPolicies); - when(metaData.custom(anyObject())).thenReturn(ilmMeta); - when(cs.metaData()).thenReturn(metaData); + private ClusterChangedEvent createClusterChangedEvent(List existingTemplateNames, + Map existingPolicies, + DiscoveryNodes nodes) { + return createClusterChangedEvent(Settings.EMPTY, existingTemplateNames, existingPolicies, nodes); + } + + private ClusterChangedEvent createClusterChangedEvent(Settings nodeSettings, + List existingTemplateNames, + Map existingPolicies, + DiscoveryNodes nodes) { + ClusterState cs = createClusterState(nodeSettings, existingTemplateNames, existingPolicies, nodes); + ClusterChangedEvent realEvent = new ClusterChangedEvent("created-from-test", cs, + ClusterState.builder(new ClusterName("test")).build()); + ClusterChangedEvent event = spy(realEvent); + when(event.localNodeMaster()).thenReturn(nodes.isLocalNodeElectedMaster()); return event; }