Skip to content

Commit bd209df

Browse files
committed
Refactor CleanupShrinkIndexStep to CleanupGeneratedIndexStep
By making the step more generic, we can reuse it in other actions (such as the upcoming improved force merge action). We ensure that indices that are in this cleanup step while the cluster upgrades to this version, are still able to progress seamlessly by registering the old step name as a `NoopStep` and forwarding them to the new cleanup step name.
1 parent 5c66eb5 commit bd209df

File tree

4 files changed

+152
-117
lines changed

4 files changed

+152
-117
lines changed
Lines changed: 35 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,28 @@
1919
import org.elasticsearch.core.TimeValue;
2020
import org.elasticsearch.index.IndexNotFoundException;
2121

22+
import java.util.function.BiFunction;
23+
2224
/**
23-
* Deletes the index identified by the shrink index name stored in the lifecycle state of the managed index (if any was generated)
25+
* Deletes the index identified by the index name supplier.
2426
*/
25-
public class CleanupShrinkIndexStep extends AsyncRetryDuringSnapshotActionStep {
26-
public static final String NAME = "cleanup-shrink-index";
27-
private static final Logger logger = LogManager.getLogger(CleanupShrinkIndexStep.class);
27+
public class CleanupGeneratedIndexStep extends AsyncRetryDuringSnapshotActionStep {
28+
29+
public static final String OLD_NAME = "cleanup-shrink-index";
30+
public static final String NAME = "cleanup-prefixed-index";
31+
32+
private static final Logger logger = LogManager.getLogger(CleanupGeneratedIndexStep.class);
2833

29-
public CleanupShrinkIndexStep(StepKey key, StepKey nextStepKey, Client client) {
34+
private final BiFunction<String, LifecycleExecutionState, String> targetIndexNameSupplier;
35+
36+
public CleanupGeneratedIndexStep(
37+
StepKey key,
38+
StepKey nextStepKey,
39+
Client client,
40+
BiFunction<String, LifecycleExecutionState, String> targetIndexNameSupplier
41+
) {
3042
super(key, nextStepKey, client);
43+
this.targetIndexNameSupplier = targetIndexNameSupplier;
3144
}
3245

3346
@Override
@@ -37,40 +50,41 @@ public boolean isRetryable() {
3750

3851
@Override
3952
void performDuringNoSnapshot(IndexMetadata indexMetadata, ProjectMetadata currentProject, ActionListener<Void> listener) {
40-
final String shrunkenIndexSource = IndexMetadata.INDEX_RESIZE_SOURCE_NAME.get(indexMetadata.getSettings());
41-
if (Strings.isNullOrEmpty(shrunkenIndexSource) == false) {
42-
// the current managed index is a shrunk index
43-
if (currentProject.index(shrunkenIndexSource) == null) {
44-
// if the source index does not exist, we'll skip deleting the
45-
// (managed) shrunk index as that will cause data loss
53+
// If the index was generated by a resize operation, and the source inex does not exist anymore, we skip the deletion to avoid
54+
// data loss.
55+
final String generatedIndexSource = IndexMetadata.INDEX_RESIZE_SOURCE_NAME.get(indexMetadata.getSettings());
56+
if (Strings.isNullOrEmpty(generatedIndexSource) == false) {
57+
if (currentProject.index(generatedIndexSource) == null) {
4658
String policyName = indexMetadata.getLifecyclePolicyName();
4759
logger.warn(
4860
"managed index [{}] as part of policy [{}] is a shrunk index and the source index [{}] does not exist "
4961
+ "anymore. will skip the [{}] step",
5062
indexMetadata.getIndex().getName(),
5163
policyName,
52-
shrunkenIndexSource,
64+
generatedIndexSource,
5365
NAME
5466
);
5567
listener.onResponse(null);
5668
return;
5769
}
5870
}
5971

60-
LifecycleExecutionState lifecycleState = indexMetadata.getLifecycleExecutionState();
61-
final String shrinkIndexName = lifecycleState.shrinkIndexName();
62-
// if the shrink index was not generated there is nothing to delete so we move on
63-
if (Strings.hasText(shrinkIndexName) == false) {
72+
final String targetIndexName = targetIndexNameSupplier.apply(
73+
indexMetadata.getIndex().getName(),
74+
indexMetadata.getLifecycleExecutionState()
75+
);
76+
// If no index name was generated, there is nothing for us to delete, so we can move on
77+
if (Strings.hasText(targetIndexName) == false) {
6478
listener.onResponse(null);
6579
return;
6680
}
6781
getClient(currentProject.id()).admin()
6882
.indices()
69-
.delete(new DeleteIndexRequest(shrinkIndexName).masterNodeTimeout(TimeValue.MAX_VALUE), new ActionListener<>() {
83+
.delete(new DeleteIndexRequest(targetIndexName).masterNodeTimeout(TimeValue.MAX_VALUE), new ActionListener<>() {
7084
@Override
7185
public void onResponse(AcknowledgedResponse acknowledgedResponse) {
7286
// even if not all nodes acked the delete request yet we can consider this operation as successful as
73-
// we'll generate a new index name and attempt to shrink into the newly generated name
87+
// we'll generate a new index name and attempt to create a new index with the newly generated name
7488
listener.onResponse(null);
7589
}
7690

@@ -86,4 +100,7 @@ public void onFailure(Exception e) {
86100
});
87101
}
88102

103+
public BiFunction<String, LifecycleExecutionState, String> getTargetIndexNameSupplier() {
104+
return targetIndexNameSupplier;
105+
}
89106
}

x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ilm/ShrinkAction.java

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,8 @@ public List<Step> toSteps(Client client, String phase, Step.StepKey nextStepKey)
168168
StepKey waitTimeSeriesEndTimePassesKey = new StepKey(phase, NAME, WaitUntilTimeSeriesEndTimePassesStep.NAME);
169169
StepKey readOnlyKey = new StepKey(phase, NAME, ReadOnlyAction.NAME);
170170
StepKey checkTargetShardsCountKey = new StepKey(phase, NAME, CheckTargetShardsCountStep.NAME);
171-
StepKey cleanupShrinkIndexKey = new StepKey(phase, NAME, CleanupShrinkIndexStep.NAME);
171+
StepKey oldCleanupShrinkIndexKey = new StepKey(phase, NAME, CleanupGeneratedIndexStep.OLD_NAME);
172+
StepKey cleanupShrinkIndexKey = new StepKey(phase, NAME, CleanupGeneratedIndexStep.NAME);
172173
StepKey generateShrinkIndexNameKey = new StepKey(phase, NAME, GenerateUniqueIndexNameStep.NAME);
173174
StepKey setSingleNodeKey = new StepKey(phase, NAME, SetSingleNodeAllocateStep.NAME);
174175
StepKey allocationRoutedKey = new StepKey(phase, NAME, CheckShrinkReadyStep.NAME);
@@ -240,13 +241,16 @@ public List<Step> toSteps(Client client, String phase, Step.StepKey nextStepKey)
240241
cleanupShrinkIndexKey,
241242
numberOfShards
242243
);
244+
// The cleanup step was renamed, so we need to forward indices in the old step to the new one, i.e. during an upgrade
245+
NoopStep oldCleanupShrinkIndexStep = new NoopStep(oldCleanupShrinkIndexKey, cleanupShrinkIndexKey);
243246
// We generate a unique shrink index name but we also retry if the allocation of the shrunk index is not possible, so we want to
244247
// delete the "previously generated" shrink index (this is a no-op if it's the first run of the action and we haven't generated a
245248
// shrink index name)
246-
CleanupShrinkIndexStep cleanupShrinkIndexStep = new CleanupShrinkIndexStep(
249+
CleanupGeneratedIndexStep cleanupShrinkIndexStep = new CleanupGeneratedIndexStep(
247250
cleanupShrinkIndexKey,
248251
generateShrinkIndexNameKey,
249-
client
252+
client,
253+
ShrinkIndexNameSupplier::getShrinkIndexName
250254
);
251255
// generate a unique shrink index name and store it in the ILM execution state
252256
GenerateUniqueIndexNameStep generateUniqueIndexNameStep = new GenerateUniqueIndexNameStep(
@@ -313,6 +317,7 @@ public List<Step> toSteps(Client client, String phase, Step.StepKey nextStepKey)
313317
waitUntilTimeSeriesEndTimeStep,
314318
readOnlyStep,
315319
checkTargetShardsCountStep,
320+
oldCleanupShrinkIndexStep,
316321
cleanupShrinkIndexStep,
317322
generateUniqueIndexNameStep,
318323
setSingleNodeStep,
Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -28,30 +28,35 @@
2828
import static org.hamcrest.Matchers.arrayContaining;
2929
import static org.hamcrest.Matchers.is;
3030

31-
public class CleanupShrinkIndexStepTests extends AbstractStepTestCase<CleanupShrinkIndexStep> {
31+
public class CleanupGeneratedIndexStepTests extends AbstractStepTestCase<CleanupGeneratedIndexStep> {
3232

3333
@Override
34-
public CleanupShrinkIndexStep createRandomInstance() {
34+
public CleanupGeneratedIndexStep createRandomInstance() {
3535
StepKey stepKey = randomStepKey();
3636
StepKey nextStepKey = randomStepKey();
37-
return new CleanupShrinkIndexStep(stepKey, nextStepKey, client);
37+
return new CleanupGeneratedIndexStep(stepKey, nextStepKey, client, (index, state) -> randomAlphaOfLength(5) + index);
3838
}
3939

4040
@Override
41-
protected CleanupShrinkIndexStep copyInstance(CleanupShrinkIndexStep instance) {
42-
return new CleanupShrinkIndexStep(instance.getKey(), instance.getNextStepKey(), instance.getClientWithoutProject());
41+
protected CleanupGeneratedIndexStep copyInstance(CleanupGeneratedIndexStep instance) {
42+
return new CleanupGeneratedIndexStep(
43+
instance.getKey(),
44+
instance.getNextStepKey(),
45+
instance.getClientWithoutProject(),
46+
instance.getTargetIndexNameSupplier()
47+
);
4348
}
4449

4550
@Override
46-
public CleanupShrinkIndexStep mutateInstance(CleanupShrinkIndexStep instance) {
51+
public CleanupGeneratedIndexStep mutateInstance(CleanupGeneratedIndexStep instance) {
4752
StepKey key = instance.getKey();
4853
StepKey nextKey = instance.getNextStepKey();
4954
switch (between(0, 1)) {
5055
case 0 -> key = new StepKey(key.phase(), key.action(), key.name() + randomAlphaOfLength(5));
5156
case 1 -> nextKey = new StepKey(nextKey.phase(), nextKey.action(), nextKey.name() + randomAlphaOfLength(5));
5257
default -> throw new AssertionError("Illegal randomisation branch");
5358
}
54-
return new CleanupShrinkIndexStep(key, nextKey, instance.getClientWithoutProject());
59+
return new CleanupGeneratedIndexStep(key, nextKey, instance.getClientWithoutProject(), instance.getTargetIndexNameSupplier());
5560
}
5661

5762
public void testPerformActionDoesntFailIfShrinkingIndexNameIsMissing() {
@@ -67,7 +72,7 @@ public void testPerformActionDoesntFailIfShrinkingIndexNameIsMissing() {
6772

6873
ProjectState state = projectStateFromProject(ProjectMetadata.builder(randomProjectIdOrDefault()).put(indexMetadata, true));
6974

70-
CleanupShrinkIndexStep cleanupShrinkIndexStep = createRandomInstance();
75+
CleanupGeneratedIndexStep cleanupShrinkIndexStep = createRandomInstance();
7176
cleanupShrinkIndexStep.performAction(indexMetadata, state, null, new ActionListener<>() {
7277
@Override
7378
public void onResponse(Void unused) {}
@@ -100,7 +105,12 @@ public void testPerformAction() {
100105

101106
try (var threadPool = createThreadPool()) {
102107
final var client = getDeleteIndexRequestAssertingClient(threadPool, shrinkIndexName);
103-
CleanupShrinkIndexStep step = new CleanupShrinkIndexStep(randomStepKey(), randomStepKey(), client);
108+
CleanupGeneratedIndexStep step = new CleanupGeneratedIndexStep(
109+
randomStepKey(),
110+
randomStepKey(),
111+
client,
112+
ShrinkIndexNameSupplier::getShrinkIndexName
113+
);
104114
step.performAction(indexMetadata, state, null, ActionListener.noop());
105115
}
106116
}
@@ -125,7 +135,7 @@ public void testDeleteSkippedIfManagedIndexIsShrunkAndSourceDoesntExist() {
125135

126136
try (var threadPool = createThreadPool()) {
127137
final var client = getFailingIfCalledClient(threadPool);
128-
CleanupShrinkIndexStep step = new CleanupShrinkIndexStep(randomStepKey(), randomStepKey(), client);
138+
CleanupGeneratedIndexStep step = new CleanupGeneratedIndexStep(randomStepKey(), randomStepKey(), client, (index, s) -> index);
129139
step.performAction(shrunkIndexMetadata, state, null, ActionListener.noop());
130140
}
131141
}

0 commit comments

Comments
 (0)