Skip to content

Commit 560f706

Browse files
authored
Make ILM ClusterStateActionStep project-aware (#128880)
This is part of an iterative process to make ILM project-aware.
1 parent 140200d commit 560f706

24 files changed

+249
-310
lines changed

server/src/main/java/org/elasticsearch/cluster/ProjectState.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import org.elasticsearch.cluster.metadata.ProjectId;
1414
import org.elasticsearch.cluster.metadata.ProjectMetadata;
1515
import org.elasticsearch.cluster.routing.RoutingTable;
16+
import org.elasticsearch.common.Strings;
1617

1718
import java.util.Objects;
1819
import java.util.function.Consumer;
@@ -74,4 +75,24 @@ public ClusterState updatedState(Consumer<ProjectMetadata.Builder> projectBuilde
7475
projectBuilderConsumer.accept(projectBuilder);
7576
return ClusterState.builder(cluster).putProjectMetadata(projectBuilder).build();
7677
}
78+
79+
/**
80+
* Build a new {@link ProjectState} with the updated {@code project}.
81+
*/
82+
public ProjectState updateProject(ProjectMetadata updatedProject) {
83+
// No need to build a new object if the project is unchanged.
84+
if (metadata() == updatedProject) {
85+
return this;
86+
}
87+
if (project.equals(updatedProject.id()) == false) {
88+
throw new IllegalArgumentException(
89+
Strings.format(
90+
"Unable to update project state with project ID [%s] because updated project has ID [%s]",
91+
project,
92+
updatedProject.id()
93+
)
94+
);
95+
}
96+
return new ProjectState(ClusterState.builder(cluster).putProjectMetadata(updatedProject).build(), project);
97+
}
7798
}

test/framework/src/main/java/org/elasticsearch/test/ESTestCase.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,13 @@
5757
import org.elasticsearch.client.internal.ElasticsearchClient;
5858
import org.elasticsearch.client.internal.Requests;
5959
import org.elasticsearch.cluster.ClusterModule;
60+
import org.elasticsearch.cluster.ClusterName;
61+
import org.elasticsearch.cluster.ClusterState;
62+
import org.elasticsearch.cluster.ProjectState;
6063
import org.elasticsearch.cluster.metadata.IndexMetadata;
6164
import org.elasticsearch.cluster.metadata.Metadata;
6265
import org.elasticsearch.cluster.metadata.ProjectId;
66+
import org.elasticsearch.cluster.metadata.ProjectMetadata;
6367
import org.elasticsearch.common.CheckedSupplier;
6468
import org.elasticsearch.common.UUIDs;
6569
import org.elasticsearch.common.breaker.CircuitBreaker;
@@ -2818,4 +2822,11 @@ public static IndexSearcher newSearcher(IndexReader r, boolean maybeWrap, boolea
28182822
}
28192823
return newSearcher(r, maybeWrap, wrapWithAssertions, Concurrency.NONE);
28202824
}
2825+
2826+
/**
2827+
* Constructs a {@link ProjectState} for the given {@link ProjectMetadata.Builder}.
2828+
*/
2829+
public static ProjectState projectStateFromProject(ProjectMetadata.Builder project) {
2830+
return ClusterState.builder(ClusterName.DEFAULT).putProjectMetadata(project).build().projectState(project.getId());
2831+
}
28212832
}

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

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
import org.apache.logging.log4j.LogManager;
1111
import org.apache.logging.log4j.Logger;
1212
import org.apache.lucene.util.SetOnce;
13-
import org.elasticsearch.cluster.ClusterState;
13+
import org.elasticsearch.cluster.ProjectState;
1414
import org.elasticsearch.cluster.metadata.IndexMetadata;
1515
import org.elasticsearch.cluster.metadata.ProjectMetadata;
1616
import org.elasticsearch.index.Index;
@@ -62,15 +62,15 @@ public boolean isRetryable() {
6262
}
6363

6464
@Override
65-
public ClusterState performAction(Index index, ClusterState clusterState) {
66-
IndexMetadata indexMetadata = clusterState.metadata().getProject().index(index);
65+
public ProjectState performAction(Index index, ProjectState projectState) {
66+
IndexMetadata indexMetadata = projectState.metadata().index(index);
6767
if (indexMetadata == null) {
6868
// Index must have been since deleted, ignore it
6969
logger.debug("[{}] lifecycle action for index [{}] executed but index no longer exists", getKey().action(), index.getName());
70-
return clusterState;
70+
return projectState;
7171
}
72-
predicateValue.set(predicate.test(index, clusterState.metadata().getProject()));
73-
return clusterState;
72+
predicateValue.set(predicate.test(index, projectState.metadata()));
73+
return projectState;
7474
}
7575

7676
/**

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
*/
77
package org.elasticsearch.xpack.core.ilm;
88

9-
import org.elasticsearch.cluster.ClusterState;
9+
import org.elasticsearch.cluster.ProjectState;
1010
import org.elasticsearch.core.Tuple;
1111
import org.elasticsearch.index.Index;
1212

@@ -19,7 +19,7 @@ public ClusterStateActionStep(StepKey key, StepKey nextStepKey) {
1919
super(key, nextStepKey);
2020
}
2121

22-
public abstract ClusterState performAction(Index index, ClusterState clusterState);
22+
public abstract ProjectState performAction(Index index, ProjectState projectState);
2323

2424
/**
2525
* Returns a tuple of index name to step key for an index *other* than the

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

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
import org.apache.logging.log4j.LogManager;
1111
import org.apache.logging.log4j.Logger;
1212
import org.apache.lucene.util.SetOnce;
13-
import org.elasticsearch.cluster.ClusterState;
13+
import org.elasticsearch.cluster.ProjectState;
1414
import org.elasticsearch.cluster.metadata.IndexMetadata;
1515
import org.elasticsearch.cluster.metadata.LifecycleExecutionState;
1616
import org.elasticsearch.core.Tuple;
@@ -66,18 +66,18 @@ public Tuple<String, StepKey> indexForAsyncInvocation() {
6666
}
6767

6868
@Override
69-
public ClusterState performAction(Index index, ClusterState clusterState) {
70-
IndexMetadata indexMetadata = clusterState.metadata().getProject().index(index);
69+
public ProjectState performAction(Index index, ProjectState projectState) {
70+
IndexMetadata indexMetadata = projectState.metadata().index(index);
7171
if (indexMetadata == null) {
7272
// Index must have been since deleted, ignore it
7373
logger.debug("[{}] lifecycle action for index [{}] executed but index no longer exists", getKey().action(), index.getName());
74-
return clusterState;
74+
return projectState;
7575
}
7676
// get target index
7777
LifecycleExecutionState lifecycleState = indexMetadata.getLifecycleExecutionState();
7878
String targetIndexName = targetIndexNameSupplier.apply(index.getName(), lifecycleState);
7979
calculatedTargetIndexName.set(targetIndexName);
80-
IndexMetadata targetIndexMetadata = clusterState.metadata().getProject().index(targetIndexName);
80+
IndexMetadata targetIndexMetadata = projectState.metadata().index(targetIndexName);
8181

8282
if (targetIndexMetadata == null) {
8383
logger.warn(
@@ -101,10 +101,8 @@ public ClusterState performAction(Index index, ClusterState clusterState) {
101101
newLifecycleState.setAction(action);
102102
newLifecycleState.setStep(step);
103103

104-
return LifecycleExecutionStateUtils.newClusterStateWithLifecycleState(
105-
clusterState,
106-
targetIndexMetadata.getIndex(),
107-
newLifecycleState.build()
104+
return projectState.updateProject(
105+
projectState.metadata().withLifecycleState(targetIndexMetadata.getIndex(), newLifecycleState.build())
108106
);
109107
}
110108

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

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
import org.apache.logging.log4j.LogManager;
1010
import org.apache.logging.log4j.Logger;
11-
import org.elasticsearch.cluster.ClusterState;
11+
import org.elasticsearch.cluster.ProjectState;
1212
import org.elasticsearch.cluster.metadata.IndexMetadata;
1313
import org.elasticsearch.cluster.metadata.LifecycleExecutionState;
1414
import org.elasticsearch.cluster.metadata.ProjectMetadata;
@@ -62,21 +62,21 @@ BiFunction<String, LifecycleExecutionState, String> getTargetIndexNameSupplier()
6262
}
6363

6464
@Override
65-
public ClusterState performAction(Index index, ClusterState clusterState) {
65+
public ProjectState performAction(Index index, ProjectState projectState) {
6666
String sourceIndexName = index.getName();
67-
IndexMetadata sourceIndexMetadata = clusterState.metadata().getProject().index(sourceIndexName);
67+
IndexMetadata sourceIndexMetadata = projectState.metadata().index(sourceIndexName);
6868
if (sourceIndexMetadata == null) {
6969
// Index must have been since deleted, ignore it
7070
logger.debug("[{}] lifecycle action for index [{}] executed but index no longer exists", getKey().action(), sourceIndexName);
71-
return clusterState;
71+
return projectState;
7272
}
7373

7474
if (settingsKeys == null || settingsKeys.length == 0) {
75-
return clusterState;
75+
return projectState;
7676
}
7777

7878
String targetIndexName = targetIndexNameSupplier.apply(sourceIndexName, sourceIndexMetadata.getLifecycleExecutionState());
79-
IndexMetadata targetIndexMetadata = clusterState.metadata().getProject().index(targetIndexName);
79+
IndexMetadata targetIndexMetadata = projectState.metadata().index(targetIndexName);
8080
if (targetIndexMetadata == null) {
8181
String errorMessage = Strings.format(
8282
"index [%s] is being referenced by ILM action [%s] on step [%s] but it doesn't exist",
@@ -94,11 +94,10 @@ public ClusterState performAction(Index index, ClusterState clusterState) {
9494
settings.put(key, value);
9595
}
9696

97-
ProjectMetadata.Builder newProject = ProjectMetadata.builder(clusterState.getMetadata().getProject())
98-
.put(
99-
IndexMetadata.builder(targetIndexMetadata).settingsVersion(targetIndexMetadata.getSettingsVersion() + 1).settings(settings)
100-
);
101-
return ClusterState.builder(clusterState).putProjectMetadata(newProject).build();
97+
IndexMetadata.Builder updatedIndex = IndexMetadata.builder(targetIndexMetadata)
98+
.settingsVersion(targetIndexMetadata.getSettingsVersion() + 1)
99+
.settings(settings);
100+
return projectState.updateProject(ProjectMetadata.builder(projectState.metadata()).put(updatedIndex).build());
102101
}
103102

104103
@Override

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

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
import org.apache.logging.log4j.LogManager;
1111
import org.apache.logging.log4j.Logger;
12-
import org.elasticsearch.cluster.ClusterState;
12+
import org.elasticsearch.cluster.ProjectState;
1313
import org.elasticsearch.cluster.metadata.IndexMetadata;
1414
import org.elasticsearch.cluster.metadata.LifecycleExecutionState;
1515
import org.elasticsearch.index.Index;
@@ -35,12 +35,12 @@ public DownsamplePrepareLifeCycleStateStep(StepKey key, StepKey nextStepKey, Dat
3535
}
3636

3737
@Override
38-
public ClusterState performAction(Index index, ClusterState clusterState) {
39-
IndexMetadata indexMetadata = clusterState.metadata().getProject().index(index);
38+
public ProjectState performAction(Index index, ProjectState projectState) {
39+
IndexMetadata indexMetadata = projectState.metadata().index(index);
4040
if (indexMetadata == null) {
4141
// Index must have been since deleted, ignore it
4242
LOGGER.debug("[{}] lifecycle action for index [{}] executed but index no longer exists", getKey().action(), index.getName());
43-
return clusterState;
43+
return projectState;
4444
}
4545

4646
LifecycleExecutionState lifecycleState = indexMetadata.getLifecycleExecutionState();
@@ -49,11 +49,7 @@ public ClusterState performAction(Index index, ClusterState clusterState) {
4949
final String downsampleIndexName = generateDownsampleIndexName(DOWNSAMPLED_INDEX_PREFIX, indexMetadata, fixedInterval);
5050
newLifecycleState.setDownsampleIndexName(downsampleIndexName);
5151

52-
return LifecycleExecutionStateUtils.newClusterStateWithLifecycleState(
53-
clusterState,
54-
indexMetadata.getIndex(),
55-
newLifecycleState.build()
56-
);
52+
return projectState.updateProject(projectState.metadata().withLifecycleState(indexMetadata.getIndex(), newLifecycleState.build()));
5753
}
5854

5955
@Override

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

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
import org.apache.logging.log4j.LogManager;
1010
import org.apache.logging.log4j.Logger;
1111
import org.elasticsearch.action.ActionRequestValidationException;
12-
import org.elasticsearch.cluster.ClusterState;
12+
import org.elasticsearch.cluster.ProjectState;
1313
import org.elasticsearch.cluster.metadata.IndexMetadata;
1414
import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver;
1515
import org.elasticsearch.cluster.metadata.LifecycleExecutionState;
@@ -46,12 +46,12 @@ public String getSnapshotRepository() {
4646
}
4747

4848
@Override
49-
public ClusterState performAction(Index index, ClusterState clusterState) {
50-
IndexMetadata indexMetadata = clusterState.metadata().getProject().index(index);
49+
public ProjectState performAction(Index index, ProjectState projectState) {
50+
IndexMetadata indexMetadata = projectState.metadata().index(index);
5151
if (indexMetadata == null) {
5252
// Index must have been since deleted, ignore it
5353
logger.debug("[{}] lifecycle action for index [{}] executed but index no longer exists", getKey().action(), index.getName());
54-
return clusterState;
54+
return projectState;
5555
}
5656

5757
String policyName = indexMetadata.getLifecyclePolicyName();
@@ -60,7 +60,7 @@ public ClusterState performAction(Index index, ClusterState clusterState) {
6060
// validate that the snapshot repository exists -- because policies are refreshed on later retries, and because
6161
// this fails prior to the snapshot repository being recorded in the ilm metadata, the policy can just be corrected
6262
// and everything will pass on the subsequent retry
63-
if (RepositoriesMetadata.get(clusterState).repository(snapshotRepository) == null) {
63+
if (RepositoriesMetadata.get(projectState.metadata()).repository(snapshotRepository) == null) {
6464
throw new IllegalStateException(
6565
"repository ["
6666
+ snapshotRepository
@@ -95,11 +95,7 @@ public ClusterState performAction(Index index, ClusterState clusterState) {
9595
newLifecycleState.setSnapshotName(snapshotName);
9696
}
9797

98-
return LifecycleExecutionStateUtils.newClusterStateWithLifecycleState(
99-
clusterState,
100-
indexMetadata.getIndex(),
101-
newLifecycleState.build()
102-
);
98+
return projectState.updateProject(projectState.metadata().withLifecycleState(indexMetadata.getIndex(), newLifecycleState.build()));
10399
}
104100

105101
@Override

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

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
import org.apache.logging.log4j.LogManager;
1010
import org.apache.logging.log4j.Logger;
1111
import org.elasticsearch.action.ActionRequestValidationException;
12-
import org.elasticsearch.cluster.ClusterState;
12+
import org.elasticsearch.cluster.ProjectState;
1313
import org.elasticsearch.cluster.metadata.IndexMetadata;
1414
import org.elasticsearch.cluster.metadata.LifecycleExecutionState;
1515
import org.elasticsearch.cluster.metadata.LifecycleExecutionState.Builder;
@@ -61,20 +61,20 @@ BiFunction<String, Builder, Builder> lifecycleStateSetter() {
6161
}
6262

6363
@Override
64-
public ClusterState performAction(Index index, ClusterState clusterState) {
65-
IndexMetadata indexMetadata = clusterState.metadata().getProject().index(index);
64+
public ProjectState performAction(Index index, ProjectState projectState) {
65+
IndexMetadata indexMetadata = projectState.metadata().index(index);
6666
if (indexMetadata == null) {
6767
// Index must have been since deleted, ignore it
6868
logger.debug("[{}] lifecycle action for index [{}] executed but index no longer exists", getKey().action(), index.getName());
69-
return clusterState;
69+
return projectState;
7070
}
7171

7272
LifecycleExecutionState lifecycleState = indexMetadata.getLifecycleExecutionState();
7373

7474
Builder newLifecycleState = LifecycleExecutionState.builder(lifecycleState);
7575
String policyName = indexMetadata.getLifecyclePolicyName();
7676
String generatedIndexName = generateIndexName(prefix, index.getName());
77-
ActionRequestValidationException validationException = validateGeneratedIndexName(generatedIndexName, clusterState.projectState());
77+
ActionRequestValidationException validationException = validateGeneratedIndexName(generatedIndexName, projectState);
7878
if (validationException != null) {
7979
logger.warn(
8080
"unable to generate a valid index name as part of policy [{}] for index [{}] due to [{}]",
@@ -86,11 +86,7 @@ public ClusterState performAction(Index index, ClusterState clusterState) {
8686
}
8787
lifecycleStateSetter.apply(generatedIndexName, newLifecycleState);
8888

89-
return LifecycleExecutionStateUtils.newClusterStateWithLifecycleState(
90-
clusterState,
91-
indexMetadata.getIndex(),
92-
newLifecycleState.build()
93-
);
89+
return projectState.updateProject(projectState.metadata().withLifecycleState(indexMetadata.getIndex(), newLifecycleState.build()));
9490
}
9591

9692
@Override

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

Lines changed: 7 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
import org.apache.logging.log4j.LogManager;
1010
import org.apache.logging.log4j.Logger;
11-
import org.elasticsearch.cluster.ClusterState;
11+
import org.elasticsearch.cluster.ProjectState;
1212
import org.elasticsearch.cluster.metadata.IndexMetadata;
1313
import org.elasticsearch.cluster.metadata.LifecycleExecutionState;
1414
import org.elasticsearch.cluster.metadata.ProjectMetadata;
@@ -33,17 +33,17 @@ public final class InitializePolicyContextStep extends ClusterStateActionStep {
3333
}
3434

3535
@Override
36-
public ClusterState performAction(Index index, ClusterState clusterState) {
37-
IndexMetadata indexMetadata = clusterState.getMetadata().getProject().index(index);
36+
public ProjectState performAction(Index index, ProjectState projectState) {
37+
IndexMetadata indexMetadata = projectState.metadata().index(index);
3838
if (indexMetadata == null) {
3939
logger.debug("[{}] lifecycle action for index [{}] executed but index no longer exists", getKey().action(), index.getName());
4040
// Index must have been since deleted, ignore it
41-
return clusterState;
41+
return projectState;
4242
}
4343

4444
LifecycleExecutionState lifecycleState = indexMetadata.getLifecycleExecutionState();
4545
if (lifecycleState.lifecycleDate() != null) {
46-
return clusterState;
46+
return projectState;
4747
}
4848

4949
LifecycleExecutionState newLifecycleState = LifecycleExecutionState.builder(lifecycleState)
@@ -63,11 +63,7 @@ public ClusterState performAction(Index index, ClusterState clusterState) {
6363

6464
if (parsedOriginationDate == null) {
6565
// we don't need to update the LifecycleSettings.LIFECYCLE_ORIGINATION_DATE, so we can use the fast path
66-
return LifecycleExecutionStateUtils.newClusterStateWithLifecycleState(
67-
clusterState,
68-
indexMetadata.getIndex(),
69-
newLifecycleState
70-
);
66+
return projectState.updateProject(projectState.metadata().withLifecycleState(indexMetadata.getIndex(), newLifecycleState));
7167
} else {
7268
// we do need to update the LifecycleSettings.LIFECYCLE_ORIGINATION_DATE, so we can't use the fast path
7369
IndexMetadata.Builder builder = IndexMetadata.builder(indexMetadata);
@@ -79,9 +75,7 @@ public ClusterState performAction(Index index, ClusterState clusterState) {
7975
.build()
8076
);
8177
builder.putCustom(ILM_CUSTOM_METADATA_KEY, newLifecycleState.asMap());
82-
return ClusterState.builder(clusterState)
83-
.putProjectMetadata(ProjectMetadata.builder(clusterState.metadata().getProject()).put(builder).build())
84-
.build();
78+
return projectState.updateProject(ProjectMetadata.builder(projectState.metadata()).put(builder).build());
8579
}
8680
}
8781

0 commit comments

Comments
 (0)