Skip to content

Commit 2e08efe

Browse files
authored
Make ILM IndexNameGenerator project-aware (elastic#127811)
Since this method needs to access both the routing table and the metadata, we need to make use of the `ProjectState` here.
1 parent 37f3412 commit 2e08efe

File tree

3 files changed

+110
-89
lines changed

3 files changed

+110
-89
lines changed

server/src/main/java/org/elasticsearch/common/IndexNameGenerator.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
package org.elasticsearch.common;
1111

1212
import org.elasticsearch.action.ActionRequestValidationException;
13-
import org.elasticsearch.cluster.ClusterState;
13+
import org.elasticsearch.cluster.ProjectState;
1414
import org.elasticsearch.cluster.metadata.MetadataCreateIndexService;
1515
import org.elasticsearch.core.Nullable;
1616
import org.elasticsearch.indices.InvalidIndexNameException;
@@ -60,17 +60,17 @@ public static String generateValidIndexSuffix(Supplier<String> randomGenerator)
6060
* Returns null for valid indices.
6161
*/
6262
@Nullable
63-
public static ActionRequestValidationException validateGeneratedIndexName(String generatedIndexName, ClusterState state) {
63+
public static ActionRequestValidationException validateGeneratedIndexName(String generatedIndexName, ProjectState projectState) {
6464
ActionRequestValidationException err = new ActionRequestValidationException();
6565
try {
6666
MetadataCreateIndexService.validateIndexOrAliasName(generatedIndexName, InvalidIndexNameException::new);
6767
} catch (InvalidIndexNameException e) {
6868
err.addValidationError(e.getMessage());
6969
}
70-
if (state.routingTable().hasIndex(generatedIndexName) || state.metadata().getProject().hasIndex(generatedIndexName)) {
70+
if (projectState.routingTable().hasIndex(generatedIndexName) || projectState.metadata().hasIndex(generatedIndexName)) {
7171
err.addValidationError("the index name we generated [" + generatedIndexName + "] already exists");
7272
}
73-
if (state.metadata().getProject().hasAlias(generatedIndexName)) {
73+
if (projectState.metadata().hasAlias(generatedIndexName)) {
7474
err.addValidationError("the index name we generated [" + generatedIndexName + "] already exists as alias");
7575
}
7676

server/src/test/java/org/elasticsearch/common/IndexNameGeneratorTests.java

Lines changed: 105 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,12 @@
1212
import org.elasticsearch.action.ActionRequestValidationException;
1313
import org.elasticsearch.cluster.ClusterName;
1414
import org.elasticsearch.cluster.ClusterState;
15+
import org.elasticsearch.cluster.ProjectState;
1516
import org.elasticsearch.cluster.TestShardRoutingRoleStrategies;
1617
import org.elasticsearch.cluster.metadata.AliasMetadata;
1718
import org.elasticsearch.cluster.metadata.IndexMetadata;
18-
import org.elasticsearch.cluster.metadata.Metadata;
1919
import org.elasticsearch.cluster.metadata.MetadataCreateIndexService;
20+
import org.elasticsearch.cluster.metadata.ProjectMetadata;
2021
import org.elasticsearch.cluster.routing.RoutingTable;
2122
import org.elasticsearch.index.IndexVersion;
2223
import org.elasticsearch.indices.InvalidIndexNameException;
@@ -73,95 +74,115 @@ public void testGenerateValidIndexSuffix() {
7374
}
7475
}
7576

76-
public void testValidateGeneratedIndexName() {
77-
{
78-
assertThat(
79-
validateGeneratedIndexName(
80-
generateValidIndexName(randomAlphaOfLengthBetween(5, 10), randomAlphaOfLengthBetween(5, 150)),
81-
ClusterState.EMPTY_STATE
82-
),
83-
nullValue()
84-
);
85-
}
77+
public void testValidateGeneratedIndexName_valid() {
78+
String generatedIndexName = generateValidIndexName(randomAlphaOfLengthBetween(5, 10), randomAlphaOfLengthBetween(5, 150));
79+
assertThat(
80+
validateGeneratedIndexName(generatedIndexName, createProjectState(generatedIndexName, false, false, false)),
81+
nullValue()
82+
);
83+
}
8684

87-
{
88-
// index name is validated (invalid chars etc)
89-
String generatedIndexName = generateValidIndexName("_prefix-", randomAlphaOfLengthBetween(5, 150));
90-
assertThat(
91-
validateGeneratedIndexName(generatedIndexName, ClusterState.EMPTY_STATE).validationErrors(),
92-
containsInAnyOrder("Invalid index name [" + generatedIndexName + "], must not start with '_', '-', or '+'")
93-
);
94-
}
85+
public void testValidateGeneratedIndexName_invalidChars() {
86+
// index name is validated (invalid chars etc)
87+
String generatedIndexName = generateValidIndexName("_prefix-", randomAlphaOfLengthBetween(5, 150));
88+
assertThat(
89+
validateGeneratedIndexName(generatedIndexName, createProjectState(generatedIndexName, false, false, false)).validationErrors(),
90+
containsInAnyOrder("Invalid index name [" + generatedIndexName + "], must not start with '_', '-', or '+'")
91+
);
92+
}
9593

96-
{
97-
// index name is validated (invalid chars etc)
98-
String generatedIndexName = generateValidIndexName("shrink-", "shrink-indexName-random###");
99-
assertThat(
100-
validateGeneratedIndexName(generatedIndexName, ClusterState.EMPTY_STATE).validationErrors(),
101-
containsInAnyOrder("Invalid index name [" + generatedIndexName + "], must not contain '#'")
102-
);
103-
}
94+
public void testValidateGeneratedIndexName_invalidPound() {
95+
// index name is validated (invalid chars etc)
96+
String generatedIndexName = generateValidIndexName("shrink-", "shrink-indexName-random###");
97+
assertThat(
98+
validateGeneratedIndexName(generatedIndexName, createProjectState(generatedIndexName, false, false, false)).validationErrors(),
99+
containsInAnyOrder("Invalid index name [" + generatedIndexName + "], must not contain '#'")
100+
);
101+
}
104102

105-
{
106-
// generated index already exists as a standalone index
107-
String generatedIndexName = generateValidIndexName(randomAlphaOfLengthBetween(5, 10), randomAlphaOfLengthBetween(5, 150));
108-
IndexMetadata indexMetadata = IndexMetadata.builder(generatedIndexName)
109-
.settings(settings(IndexVersion.current()))
110-
.numberOfShards(randomIntBetween(1, 5))
111-
.numberOfReplicas(randomIntBetween(1, 5))
112-
.build();
113-
ClusterState clusterState = ClusterState.builder(ClusterName.DEFAULT)
114-
.metadata(Metadata.builder().put(indexMetadata, false))
115-
.build();
116-
117-
ActionRequestValidationException validationException = validateGeneratedIndexName(generatedIndexName, clusterState);
118-
assertThat(validationException, notNullValue());
119-
assertThat(
120-
validationException.validationErrors(),
121-
containsInAnyOrder("the index name we generated [" + generatedIndexName + "] already exists")
122-
);
123-
}
103+
public void testValidateGeneratedIndexName_alreadyExistsAsIndex() {
104+
// generated index already exists as a standalone index
105+
String generatedIndexName = generateValidIndexName(randomAlphaOfLengthBetween(5, 10), randomAlphaOfLengthBetween(5, 150));
106+
ActionRequestValidationException validationException = validateGeneratedIndexName(
107+
generatedIndexName,
108+
createProjectState(generatedIndexName, true, false, false)
109+
);
110+
assertThat(validationException, notNullValue());
111+
assertThat(
112+
validationException.validationErrors(),
113+
containsInAnyOrder("the index name we generated [" + generatedIndexName + "] already exists")
114+
);
115+
}
124116

125-
{
126-
// generated index name already exists as an index (cluster state routing table is also populated)
127-
String generatedIndexName = generateValidIndexName(randomAlphaOfLengthBetween(5, 10), randomAlphaOfLengthBetween(5, 150));
128-
IndexMetadata indexMetadata = IndexMetadata.builder(generatedIndexName)
129-
.settings(settings(IndexVersion.current()))
130-
.numberOfShards(randomIntBetween(1, 5))
131-
.numberOfReplicas(randomIntBetween(1, 5))
132-
.build();
133-
ClusterState clusterState = ClusterState.builder(ClusterName.DEFAULT)
134-
.routingTable(RoutingTable.builder(TestShardRoutingRoleStrategies.DEFAULT_ROLE_ONLY).addAsNew(indexMetadata).build())
135-
.metadata(Metadata.builder().put(indexMetadata, false))
136-
.build();
137-
138-
ActionRequestValidationException validationException = validateGeneratedIndexName(generatedIndexName, clusterState);
139-
assertThat(validationException, notNullValue());
140-
assertThat(
141-
validationException.validationErrors(),
142-
containsInAnyOrder("the index name we generated [" + generatedIndexName + "] already exists")
143-
);
144-
}
117+
public void testValidateGeneratedIndexName_alreadyExistsAlsoRoutingTable() {
118+
// generated index name already exists as an index (cluster state routing table is also populated)
119+
String generatedIndexName = generateValidIndexName(randomAlphaOfLengthBetween(5, 10), randomAlphaOfLengthBetween(5, 150));
120+
ActionRequestValidationException validationException = validateGeneratedIndexName(
121+
generatedIndexName,
122+
createProjectState(generatedIndexName, true, true, false)
123+
);
124+
assertThat(validationException, notNullValue());
125+
assertThat(
126+
validationException.validationErrors(),
127+
containsInAnyOrder("the index name we generated [" + generatedIndexName + "] already exists")
128+
);
129+
}
145130

146-
{
147-
// generated index name already exists as an alias to another index
148-
String generatedIndexName = generateValidIndexName(randomAlphaOfLengthBetween(5, 10), randomAlphaOfLengthBetween(5, 150));
149-
IndexMetadata indexMetadata = IndexMetadata.builder(randomAlphaOfLengthBetween(10, 30))
150-
.settings(settings(IndexVersion.current()))
151-
.numberOfShards(randomIntBetween(1, 5))
152-
.numberOfReplicas(randomIntBetween(1, 5))
153-
.putAlias(AliasMetadata.builder(generatedIndexName).build())
154-
.build();
155-
ClusterState clusterState = ClusterState.builder(ClusterName.DEFAULT)
156-
.metadata(Metadata.builder().put(indexMetadata, false))
157-
.build();
158-
159-
ActionRequestValidationException validationException = validateGeneratedIndexName(generatedIndexName, clusterState);
160-
assertThat(validationException, notNullValue());
161-
assertThat(
162-
validationException.validationErrors(),
163-
containsInAnyOrder("the index name we generated [" + generatedIndexName + "] already exists as alias")
131+
public void testValidateGeneratedIndexName_alreadyExistsOnlyRoutingTable() {
132+
// generated index name already exists as an index but only in routing table
133+
String generatedIndexName = generateValidIndexName(randomAlphaOfLengthBetween(5, 10), randomAlphaOfLengthBetween(5, 150));
134+
ActionRequestValidationException validationException = validateGeneratedIndexName(
135+
generatedIndexName,
136+
createProjectState(generatedIndexName, false, true, false)
137+
);
138+
assertThat(validationException, notNullValue());
139+
assertThat(
140+
validationException.validationErrors(),
141+
containsInAnyOrder("the index name we generated [" + generatedIndexName + "] already exists")
142+
);
143+
}
144+
145+
public void testValidateGeneratedIndexName_alreadyExistsAsAlias() {
146+
// generated index name already exists as an alias to another index
147+
String generatedIndexName = generateValidIndexName(randomAlphaOfLengthBetween(5, 10), randomAlphaOfLengthBetween(5, 150));
148+
ActionRequestValidationException validationException = validateGeneratedIndexName(
149+
generatedIndexName,
150+
createProjectState(generatedIndexName, true, false, true)
151+
);
152+
assertThat(validationException, notNullValue());
153+
assertThat(
154+
validationException.validationErrors(),
155+
containsInAnyOrder("the index name we generated [" + generatedIndexName + "] already exists as alias")
156+
);
157+
}
158+
159+
private ProjectState createProjectState(
160+
String generatedName,
161+
boolean addIndexToMetadata,
162+
boolean addIndexToRoutingTable,
163+
boolean addAlias
164+
) {
165+
final var indexName = addAlias ? randomAlphaOfLengthBetween(10, 30) : generatedName;
166+
final var indexMetadataBuilder = IndexMetadata.builder(indexName)
167+
.settings(settings(IndexVersion.current()))
168+
.numberOfShards(randomIntBetween(1, 5))
169+
.numberOfReplicas(randomIntBetween(1, 5));
170+
if (addAlias) {
171+
indexMetadataBuilder.putAlias(AliasMetadata.builder(generatedName).build());
172+
}
173+
final var indexMetadata = indexMetadataBuilder.build();
174+
final var projectId = randomProjectIdOrDefault();
175+
final var projectBuilder = ProjectMetadata.builder(projectId);
176+
final var clusterStateBuilder = ClusterState.builder(ClusterName.DEFAULT);
177+
if (addIndexToMetadata) {
178+
projectBuilder.put(indexMetadata, false);
179+
}
180+
if (addIndexToRoutingTable) {
181+
clusterStateBuilder.putRoutingTable(
182+
projectId,
183+
RoutingTable.builder(TestShardRoutingRoleStrategies.DEFAULT_ROLE_ONLY).addAsNew(indexMetadata).build()
164184
);
165185
}
186+
return clusterStateBuilder.putProjectMetadata(projectBuilder).build().projectState(projectId);
166187
}
167188
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ public ClusterState performAction(Index index, ClusterState clusterState) {
7474
Builder newLifecycleState = LifecycleExecutionState.builder(lifecycleState);
7575
String policyName = indexMetadata.getLifecyclePolicyName();
7676
String generatedIndexName = generateIndexName(prefix, index.getName());
77-
ActionRequestValidationException validationException = validateGeneratedIndexName(generatedIndexName, clusterState);
77+
ActionRequestValidationException validationException = validateGeneratedIndexName(generatedIndexName, clusterState.projectState());
7878
if (validationException != null) {
7979
logger.warn(
8080
"unable to generate a valid index name as part of policy [{}] for index [{}] due to [{}]",

0 commit comments

Comments
 (0)