Skip to content

Commit 959a289

Browse files
colings86jasontedor
authored andcommitted
Adds ability to update a policy (#31361)
* Adds ability to update a policy as long as no indexes are in the shrink action * Address review comments
1 parent 7d211ad commit 959a289

File tree

4 files changed

+298
-2
lines changed

4 files changed

+298
-2
lines changed

x-pack/plugin/index-lifecycle/src/main/java/org/elasticsearch/xpack/indexlifecycle/IndexLifecycleRunner.java

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
*/
66
package org.elasticsearch.xpack.indexlifecycle;
77

8+
import com.carrotsearch.hppc.cursors.ObjectCursor;
9+
810
import org.apache.logging.log4j.Logger;
911
import org.elasticsearch.ElasticsearchException;
1012
import org.elasticsearch.action.admin.indices.shrink.ShrinkAction;
@@ -342,6 +344,36 @@ private static boolean canSetPolicy(StepKey currentStepKey, String currentPolicy
342344
}
343345
}
344346

347+
/**
348+
* Returns <code>true</code> if the provided policy is allowed to be updated
349+
* given the current {@link ClusterState}. In practice this method checks
350+
* that all the indexes using the provided <code>policyName</code> is in a
351+
* state where it is able to deal with the policy being updated to
352+
* <code>newPolicy</code>. If any of these indexes is not in a state wheree
353+
* it can deal with the update the method will return <code>false</code>.
354+
*
355+
* @param policyName
356+
* the name of the policy being updated
357+
* @param newPolicy
358+
* the new version of the {@link LifecyclePolicy}
359+
* @param currentState
360+
* the current {@link ClusterState}
361+
*/
362+
public static boolean canUpdatePolicy(String policyName, LifecyclePolicy newPolicy, ClusterState currentState) {
363+
for (ObjectCursor<IndexMetaData> cursor : currentState.getMetaData().indices().values()) {
364+
IndexMetaData idxMetadata = cursor.value;
365+
Settings idxSettings = idxMetadata.getSettings();
366+
String currentPolicyName = LifecycleSettings.LIFECYCLE_NAME_SETTING.get(idxSettings);
367+
if (policyName.equals(currentPolicyName)) {
368+
StepKey currentStepKey = IndexLifecycleRunner.getCurrentStepKey(idxSettings);
369+
if (canSetPolicy(currentStepKey, policyName, newPolicy) == false) {
370+
return false;
371+
}
372+
}
373+
}
374+
return true;
375+
}
376+
345377
public static ClusterState removePolicyForIndexes(final Index[] indices, ClusterState currentState, List<String> failedIndexes) {
346378
MetaData.Builder newMetadata = MetaData.builder(currentState.getMetaData());
347379
boolean clusterStateChanged = false;

x-pack/plugin/index-lifecycle/src/main/java/org/elasticsearch/xpack/indexlifecycle/action/TransportPutLifecycleAction.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import org.elasticsearch.xpack.core.indexlifecycle.action.PutLifecycleAction;
2828
import org.elasticsearch.xpack.core.indexlifecycle.action.PutLifecycleAction.Request;
2929
import org.elasticsearch.xpack.core.indexlifecycle.action.PutLifecycleAction.Response;
30+
import org.elasticsearch.xpack.indexlifecycle.IndexLifecycleRunner;
3031

3132
import java.util.Map;
3233
import java.util.SortedMap;
@@ -72,7 +73,8 @@ public ClusterState execute(ClusterState currentState) throws Exception {
7273
if (currentMetadata == null) { // first time using index-lifecycle feature, bootstrap metadata
7374
currentMetadata = IndexLifecycleMetadata.EMPTY;
7475
}
75-
if (currentMetadata.getPolicyMetadatas().containsKey(request.getPolicy().getName())) {
76+
if (currentMetadata.getPolicyMetadatas().containsKey(request.getPolicy().getName()) && IndexLifecycleRunner
77+
.canUpdatePolicy(request.getPolicy().getName(), request.getPolicy(), currentState) == false) {
7678
throw new ResourceAlreadyExistsException("Lifecycle policy already exists: {}",
7779
request.getPolicy().getName());
7880
}
@@ -95,4 +97,4 @@ public ClusterState execute(ClusterState currentState) throws Exception {
9597
protected ClusterBlockException checkBlock(Request request, ClusterState state) {
9698
return state.blocks().globalBlockedException(ClusterBlockLevel.METADATA_WRITE);
9799
}
98-
}
100+
}

x-pack/plugin/index-lifecycle/src/test/java/org/elasticsearch/xpack/indexlifecycle/IndexLifecycleRunnerTests.java

Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -911,6 +911,162 @@ public void testSetPolicyForIndexIndexInShrink() {
911911
assertSame(clusterState, newClusterState);
912912
}
913913

914+
public void testCanUpdatePolicy() {
915+
String indexName = randomAlphaOfLength(10);
916+
String oldPolicyName = "old_policy";
917+
String newPolicyName = "new_policy";
918+
LifecyclePolicy newPolicy = new LifecyclePolicy(TestLifecycleType.INSTANCE, newPolicyName, Collections.emptyMap());
919+
StepKey currentStep = AbstractStepTestCase.randomStepKey();
920+
Settings.Builder indexSettingsBuilder = Settings.builder().put(LifecycleSettings.LIFECYCLE_NAME, oldPolicyName)
921+
.put(LifecycleSettings.LIFECYCLE_PHASE, currentStep.getPhase())
922+
.put(LifecycleSettings.LIFECYCLE_ACTION, currentStep.getAction())
923+
.put(LifecycleSettings.LIFECYCLE_STEP, currentStep.getName()).put(LifecycleSettings.LIFECYCLE_SKIP, true);
924+
ClusterState clusterState = buildClusterState(indexName, indexSettingsBuilder);
925+
926+
boolean canUpdatePolicy = IndexLifecycleRunner.canUpdatePolicy(oldPolicyName, newPolicy, clusterState);
927+
928+
assertTrue(canUpdatePolicy);
929+
}
930+
931+
public void testCanUpdatePolicyIndexInShrink() {
932+
String indexName = randomAlphaOfLength(10);
933+
String oldPolicyName = "old_policy";
934+
String newPolicyName = "new_policy";
935+
LifecyclePolicy newPolicy = new LifecyclePolicy(TestLifecycleType.INSTANCE, newPolicyName, Collections.emptyMap());
936+
StepKey currentStep = new StepKey(randomAlphaOfLength(10), ShrinkAction.NAME, randomAlphaOfLength(10));
937+
Settings.Builder indexSettingsBuilder = Settings.builder().put(LifecycleSettings.LIFECYCLE_NAME, oldPolicyName)
938+
.put(LifecycleSettings.LIFECYCLE_PHASE, currentStep.getPhase())
939+
.put(LifecycleSettings.LIFECYCLE_ACTION, currentStep.getAction())
940+
.put(LifecycleSettings.LIFECYCLE_STEP, currentStep.getName()).put(LifecycleSettings.LIFECYCLE_SKIP, true);
941+
ClusterState clusterState = buildClusterState(indexName, indexSettingsBuilder);
942+
943+
boolean canUpdatePolicy = IndexLifecycleRunner.canUpdatePolicy(oldPolicyName, newPolicy, clusterState);
944+
945+
assertFalse(canUpdatePolicy);
946+
}
947+
948+
public void testCanUpdatePolicyIndexNotManaged() {
949+
String indexName = randomAlphaOfLength(10);
950+
String oldPolicyName = "old_policy";
951+
String newPolicyName = "new_policy";
952+
LifecyclePolicy newPolicy = new LifecyclePolicy(TestLifecycleType.INSTANCE, newPolicyName, Collections.emptyMap());
953+
Settings.Builder indexSettingsBuilder = Settings.builder();
954+
ClusterState clusterState = buildClusterState(indexName, indexSettingsBuilder);
955+
956+
boolean canUpdatePolicy = IndexLifecycleRunner.canUpdatePolicy(oldPolicyName, newPolicy, clusterState);
957+
958+
assertTrue(canUpdatePolicy);
959+
}
960+
961+
public void testCanUpdatePolicyDifferentPolicy() {
962+
String indexName = randomAlphaOfLength(10);
963+
String oldPolicyName = "old_policy";
964+
String newPolicyName = "new_policy";
965+
LifecyclePolicy newPolicy = new LifecyclePolicy(TestLifecycleType.INSTANCE, newPolicyName, Collections.emptyMap());
966+
StepKey currentStep = new StepKey(randomAlphaOfLength(10), ShrinkAction.NAME, randomAlphaOfLength(10));
967+
Settings.Builder indexSettingsBuilder = Settings.builder().put(LifecycleSettings.LIFECYCLE_NAME, "different_policy")
968+
.put(LifecycleSettings.LIFECYCLE_PHASE, currentStep.getPhase())
969+
.put(LifecycleSettings.LIFECYCLE_ACTION, currentStep.getAction())
970+
.put(LifecycleSettings.LIFECYCLE_STEP, currentStep.getName()).put(LifecycleSettings.LIFECYCLE_SKIP, true);
971+
ClusterState clusterState = buildClusterState(indexName, indexSettingsBuilder);
972+
973+
boolean canUpdatePolicy = IndexLifecycleRunner.canUpdatePolicy(oldPolicyName, newPolicy, clusterState);
974+
975+
assertTrue(canUpdatePolicy);
976+
}
977+
978+
public void testCanUpdatePolicyMultipleIndexesUpdateAllowed() {
979+
String oldPolicyName = "old_policy";
980+
String newPolicyName = "new_policy";
981+
LifecyclePolicy newPolicy = new LifecyclePolicy(TestLifecycleType.INSTANCE, newPolicyName, Collections.emptyMap());
982+
983+
String index1Name = randomAlphaOfLength(10);
984+
StepKey currentStep1 = AbstractStepTestCase.randomStepKey();
985+
Settings.Builder indexSettingsBuilder1 = Settings.builder().put(IndexMetaData.SETTING_NUMBER_OF_SHARDS, 1)
986+
.put(IndexMetaData.SETTING_NUMBER_OF_REPLICAS, 0).put(IndexMetaData.SETTING_VERSION_CREATED, Version.CURRENT)
987+
.put(LifecycleSettings.LIFECYCLE_NAME, oldPolicyName).put(LifecycleSettings.LIFECYCLE_PHASE, currentStep1.getPhase())
988+
.put(LifecycleSettings.LIFECYCLE_ACTION, currentStep1.getAction())
989+
.put(LifecycleSettings.LIFECYCLE_STEP, currentStep1.getName()).put(LifecycleSettings.LIFECYCLE_SKIP, true);
990+
IndexMetaData indexMetadata1 = IndexMetaData.builder(index1Name).settings(indexSettingsBuilder1).build();
991+
992+
String index2Name = randomAlphaOfLength(10);
993+
StepKey currentStep2 = AbstractStepTestCase.randomStepKey();
994+
Settings.Builder indexSettingsBuilder2 = Settings.builder().put(IndexMetaData.SETTING_NUMBER_OF_SHARDS, 1)
995+
.put(IndexMetaData.SETTING_NUMBER_OF_REPLICAS, 0).put(IndexMetaData.SETTING_VERSION_CREATED, Version.CURRENT)
996+
.put(LifecycleSettings.LIFECYCLE_NAME, oldPolicyName).put(LifecycleSettings.LIFECYCLE_PHASE, currentStep2.getPhase())
997+
.put(LifecycleSettings.LIFECYCLE_ACTION, currentStep2.getAction())
998+
.put(LifecycleSettings.LIFECYCLE_STEP, currentStep2.getName()).put(LifecycleSettings.LIFECYCLE_SKIP, true);
999+
IndexMetaData indexMetadata2 = IndexMetaData.builder(index2Name).settings(indexSettingsBuilder2).build();
1000+
1001+
String index3Name = randomAlphaOfLength(10);
1002+
StepKey currentStep3 = new StepKey(randomAlphaOfLength(10), ShrinkAction.NAME, randomAlphaOfLength(10));
1003+
Settings.Builder indexSettingsBuilder3 = Settings.builder().put(IndexMetaData.SETTING_NUMBER_OF_SHARDS, 1)
1004+
.put(IndexMetaData.SETTING_NUMBER_OF_REPLICAS, 0).put(IndexMetaData.SETTING_VERSION_CREATED, Version.CURRENT)
1005+
.put(LifecycleSettings.LIFECYCLE_NAME, "different_policy").put(LifecycleSettings.LIFECYCLE_PHASE, currentStep3.getPhase())
1006+
.put(LifecycleSettings.LIFECYCLE_ACTION, currentStep3.getAction())
1007+
.put(LifecycleSettings.LIFECYCLE_STEP, currentStep3.getName()).put(LifecycleSettings.LIFECYCLE_SKIP, true);
1008+
IndexMetaData indexMetadata3 = IndexMetaData.builder(index3Name).settings(indexSettingsBuilder3).build();
1009+
1010+
String index4Name = randomAlphaOfLength(10);
1011+
Settings.Builder indexSettingsBuilder4 = Settings.builder().put(IndexMetaData.SETTING_NUMBER_OF_SHARDS, 1)
1012+
.put(IndexMetaData.SETTING_NUMBER_OF_REPLICAS, 0).put(IndexMetaData.SETTING_VERSION_CREATED, Version.CURRENT);
1013+
IndexMetaData indexMetadata4 = IndexMetaData.builder(index4Name).settings(indexSettingsBuilder4).build();
1014+
1015+
MetaData metadata = MetaData.builder().put(indexMetadata1, true).put(indexMetadata2, true).put(indexMetadata3, true)
1016+
.put(indexMetadata4, true).build();
1017+
ClusterState clusterState = ClusterState.builder(new ClusterName("my_cluster")).metaData(metadata).build();
1018+
1019+
boolean canUpdatePolicy = IndexLifecycleRunner.canUpdatePolicy(oldPolicyName, newPolicy, clusterState);
1020+
1021+
assertTrue(canUpdatePolicy);
1022+
}
1023+
1024+
public void testCanUpdatePolicyMultipleIndexesUpdateForbidden() {
1025+
String oldPolicyName = "old_policy";
1026+
String newPolicyName = "new_policy";
1027+
LifecyclePolicy newPolicy = new LifecyclePolicy(TestLifecycleType.INSTANCE, newPolicyName, Collections.emptyMap());
1028+
1029+
String index1Name = randomAlphaOfLength(10);
1030+
StepKey currentStep1 = AbstractStepTestCase.randomStepKey();
1031+
Settings.Builder indexSettingsBuilder1 = Settings.builder().put(IndexMetaData.SETTING_NUMBER_OF_SHARDS, 1)
1032+
.put(IndexMetaData.SETTING_NUMBER_OF_REPLICAS, 0).put(IndexMetaData.SETTING_VERSION_CREATED, Version.CURRENT)
1033+
.put(LifecycleSettings.LIFECYCLE_NAME, oldPolicyName).put(LifecycleSettings.LIFECYCLE_PHASE, currentStep1.getPhase())
1034+
.put(LifecycleSettings.LIFECYCLE_ACTION, currentStep1.getAction())
1035+
.put(LifecycleSettings.LIFECYCLE_STEP, currentStep1.getName()).put(LifecycleSettings.LIFECYCLE_SKIP, true);
1036+
IndexMetaData indexMetadata1 = IndexMetaData.builder(index1Name).settings(indexSettingsBuilder1).build();
1037+
1038+
String index2Name = randomAlphaOfLength(10);
1039+
StepKey currentStep2 = new StepKey(randomAlphaOfLength(10), ShrinkAction.NAME, randomAlphaOfLength(10));
1040+
Settings.Builder indexSettingsBuilder2 = Settings.builder().put(IndexMetaData.SETTING_NUMBER_OF_SHARDS, 1)
1041+
.put(IndexMetaData.SETTING_NUMBER_OF_REPLICAS, 0).put(IndexMetaData.SETTING_VERSION_CREATED, Version.CURRENT)
1042+
.put(LifecycleSettings.LIFECYCLE_NAME, oldPolicyName).put(LifecycleSettings.LIFECYCLE_PHASE, currentStep2.getPhase())
1043+
.put(LifecycleSettings.LIFECYCLE_ACTION, currentStep2.getAction())
1044+
.put(LifecycleSettings.LIFECYCLE_STEP, currentStep2.getName()).put(LifecycleSettings.LIFECYCLE_SKIP, true);
1045+
IndexMetaData indexMetadata2 = IndexMetaData.builder(index2Name).settings(indexSettingsBuilder2).build();
1046+
1047+
String index3Name = randomAlphaOfLength(10);
1048+
StepKey currentStep3 = new StepKey(randomAlphaOfLength(10), ShrinkAction.NAME, randomAlphaOfLength(10));
1049+
Settings.Builder indexSettingsBuilder3 = Settings.builder().put(IndexMetaData.SETTING_NUMBER_OF_SHARDS, 1)
1050+
.put(IndexMetaData.SETTING_NUMBER_OF_REPLICAS, 0).put(IndexMetaData.SETTING_VERSION_CREATED, Version.CURRENT)
1051+
.put(LifecycleSettings.LIFECYCLE_NAME, "different_policy").put(LifecycleSettings.LIFECYCLE_PHASE, currentStep3.getPhase())
1052+
.put(LifecycleSettings.LIFECYCLE_ACTION, currentStep3.getAction())
1053+
.put(LifecycleSettings.LIFECYCLE_STEP, currentStep3.getName()).put(LifecycleSettings.LIFECYCLE_SKIP, true);
1054+
IndexMetaData indexMetadata3 = IndexMetaData.builder(index3Name).settings(indexSettingsBuilder3).build();
1055+
1056+
String index4Name = randomAlphaOfLength(10);
1057+
Settings.Builder indexSettingsBuilder4 = Settings.builder().put(IndexMetaData.SETTING_NUMBER_OF_SHARDS, 1)
1058+
.put(IndexMetaData.SETTING_NUMBER_OF_REPLICAS, 0).put(IndexMetaData.SETTING_VERSION_CREATED, Version.CURRENT);
1059+
IndexMetaData indexMetadata4 = IndexMetaData.builder(index4Name).settings(indexSettingsBuilder4).build();
1060+
1061+
MetaData metadata = MetaData.builder().put(indexMetadata1, true).put(indexMetadata2, true).put(indexMetadata3, true)
1062+
.put(indexMetadata4, true).build();
1063+
ClusterState clusterState = ClusterState.builder(new ClusterName("my_cluster")).metaData(metadata).build();
1064+
1065+
boolean canUpdatePolicy = IndexLifecycleRunner.canUpdatePolicy(oldPolicyName, newPolicy, clusterState);
1066+
1067+
assertFalse(canUpdatePolicy);
1068+
}
1069+
9141070
public void testRemovePolicyForIndex() {
9151071
String indexName = randomAlphaOfLength(10);
9161072
String oldPolicyName = "old_policy";

x-pack/plugin/src/test/resources/rest-api-spec/test/index_lifecycle/10_basic.yml

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,112 @@ setup:
6161
xpack.index_lifecycle.get_lifecycle:
6262
lifecycle: "my_timeseries_lifecycle"
6363

64+
---
65+
"Test Policy Update":
66+
- do:
67+
acknowlege: true
68+
xpack.index_lifecycle.put_lifecycle:
69+
lifecycle: "my_timeseries_lifecycle"
70+
body: |
71+
{
72+
"policy": {
73+
"type": "timeseries",
74+
"phases": {
75+
"warm": {
76+
"after": "10s",
77+
"actions": {
78+
"forcemerge": {
79+
"max_num_segments": 10000
80+
}
81+
}
82+
},
83+
"delete": {
84+
"after": "30s",
85+
"actions": {
86+
"delete": {}
87+
}
88+
}
89+
}
90+
}
91+
}
92+
93+
- do:
94+
acknowledge: true
95+
xpack.index_lifecycle.get_lifecycle:
96+
lifecycle: "my_timeseries_lifecycle"
97+
- match: { my_timeseries_lifecycle.type: "timeseries" }
98+
- match: { my_timeseries_lifecycle.phases.warm.after: "10s" }
99+
- match: { my_timeseries_lifecycle.phases.delete.after: "30s" }
100+
101+
102+
- do:
103+
indices.create:
104+
index: my_index
105+
body:
106+
settings:
107+
index.lifecycle.name: "my_moveable_timeseries_lifecycle"
108+
109+
- do:
110+
indices.create:
111+
index: my_index2
112+
body:
113+
settings:
114+
index.lifecycle.name: "my_moveable_timeseries_lifecycle"
115+
116+
- do:
117+
acknowlege: true
118+
xpack.index_lifecycle.put_lifecycle:
119+
lifecycle: "my_timeseries_lifecycle"
120+
body: |
121+
{
122+
"policy": {
123+
"type": "timeseries",
124+
"phases": {
125+
"warm": {
126+
"after": "300s",
127+
"actions": {
128+
"forcemerge": {
129+
"max_num_segments": 10000
130+
}
131+
}
132+
},
133+
"delete": {
134+
"after": "600s",
135+
"actions": {
136+
"delete": {}
137+
}
138+
}
139+
}
140+
}
141+
}
142+
143+
- do:
144+
acknowledge: true
145+
xpack.index_lifecycle.get_lifecycle:
146+
lifecycle: "my_timeseries_lifecycle"
147+
- match: { my_timeseries_lifecycle.type: "timeseries" }
148+
- match: { my_timeseries_lifecycle.phases.warm.after: "300s" }
149+
- match: { my_timeseries_lifecycle.phases.delete.after: "600s" }
150+
151+
- do:
152+
acknowledge: true
153+
indices.delete:
154+
index: my_index
155+
- do:
156+
acknowledge: true
157+
indices.delete:
158+
index: my_index2
159+
160+
- do:
161+
acknowledge: true
162+
xpack.index_lifecycle.delete_lifecycle:
163+
lifecycle: "my_timeseries_lifecycle"
164+
165+
- do:
166+
catch: missing
167+
xpack.index_lifecycle.get_lifecycle:
168+
lifecycle: "my_timeseries_lifecycle"
169+
64170
---
65171
"Test Undeletable Policy In Use":
66172
- do:

0 commit comments

Comments
 (0)