Skip to content

Commit 966b1e0

Browse files
authored
Allow remove alias actions to target both data streams and regular indices. (#74543)
Backporting #74403 to 7.x branch. When removing aliases allow that an alias action's index expression can match both data streams and regular indices. This allows api calls like `DELETE /_all/_alias/my-alias`, which can common in tear down / cleanup logic. In this case `my-alias` just points to regular indices, but `_all` can be expanded to data streams too if exist. This can then trigger validation logic that prevents adding aliases that refer to both indices and data streams. However this api call never adds any alias, only removes it. So failing with this validation error doesn't make much sense. This change adjusts the validation logic so that: 'match with both data streams and regular indices are disallowed' validation is only executed for alias actions that add aliases. Relates to #66163
1 parent cfa2dff commit 966b1e0

File tree

2 files changed

+62
-25
lines changed

2 files changed

+62
-25
lines changed

server/src/main/java/org/elasticsearch/action/admin/indices/alias/TransportIndicesAliasesAction.java

Lines changed: 29 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -97,55 +97,59 @@ protected void masterOperation(final IndicesAliasesRequest request, final Cluste
9797
List<String> concreteDataStreams =
9898
indexNameExpressionResolver.dataStreamNames(state, request.indicesOptions(), action.indices());
9999
if (concreteDataStreams.size() != 0) {
100-
// Fail if parameters are used that data streams don't support:
101-
if (action.filter() != null) {
102-
throw new IllegalArgumentException("aliases that point to data streams don't support filters");
103-
}
104-
if (action.routing() != null) {
105-
throw new IllegalArgumentException("aliases that point to data streams don't support routing");
106-
}
107-
if (action.indexRouting() != null) {
108-
throw new IllegalArgumentException("aliases that point to data streams don't support index_routing");
109-
}
110-
if (action.searchRouting() != null) {
111-
throw new IllegalArgumentException("aliases that point to data streams don't support search_routing");
112-
}
113-
if (action.isHidden() != null) {
114-
throw new IllegalArgumentException("aliases that point to data streams don't support is_hidden");
115-
}
116-
// Fail if expressions match both data streams and regular indices:
117100
String[] concreteIndices =
118101
indexNameExpressionResolver.concreteIndexNames(state, request.indicesOptions(), true, action.indices());
119102
List<String> nonBackingIndices = Arrays.stream(concreteIndices)
120103
.map(resolvedIndex -> state.metadata().getIndicesLookup().get(resolvedIndex))
121104
.filter(ia -> ia.getParentDataStream() == null)
122105
.map(IndexAbstraction::getName)
123106
.collect(Collectors.toList());
124-
if (nonBackingIndices.isEmpty() == false) {
125-
throw new IllegalArgumentException("expressions " + Arrays.toString(action.indices()) +
126-
" that match with both data streams and regular indices are disallowed");
127-
}
128-
129107
switch (action.actionType()) {
130108
case ADD:
109+
// Fail if parameters are used that data stream aliases don't support:
110+
if (action.filter() != null) {
111+
throw new IllegalArgumentException("aliases that point to data streams don't support filters");
112+
}
113+
if (action.routing() != null) {
114+
throw new IllegalArgumentException("aliases that point to data streams don't support routing");
115+
}
116+
if (action.indexRouting() != null) {
117+
throw new IllegalArgumentException("aliases that point to data streams don't support index_routing");
118+
}
119+
if (action.searchRouting() != null) {
120+
throw new IllegalArgumentException("aliases that point to data streams don't support search_routing");
121+
}
122+
if (action.isHidden() != null) {
123+
throw new IllegalArgumentException("aliases that point to data streams don't support is_hidden");
124+
}
125+
// Fail if expressions match both data streams and regular indices:
126+
if (nonBackingIndices.isEmpty() == false) {
127+
throw new IllegalArgumentException("expressions " + Arrays.toString(action.indices()) +
128+
" that match with both data streams and regular indices are disallowed");
129+
}
131130
for (String dataStreamName : concreteDataStreams) {
132131
for (String alias : concreteDataStreamAliases(action, state.metadata(), dataStreamName)) {
133132
finalActions.add(new AliasAction.AddDataStreamAlias(alias, dataStreamName, action.writeIndex()));
134133
}
135134
}
136-
break;
135+
continue;
137136
case REMOVE:
138137
for (String dataStreamName : concreteDataStreams) {
139138
for (String alias : concreteDataStreamAliases(action, state.metadata(), dataStreamName)) {
140139
finalActions.add(
141140
new AliasAction.RemoveDataStreamAlias(alias, dataStreamName, action.mustExist()));
142141
}
143142
}
144-
break;
143+
if (nonBackingIndices.isEmpty() == false) {
144+
// Regular aliases/indices match as well with the provided expression.
145+
// (Only when adding new aliases, matching both data streams and indices is disallowed)
146+
break;
147+
} else {
148+
continue;
149+
}
145150
default:
146151
throw new IllegalArgumentException("Unsupported action [" + action.actionType() + "]");
147152
}
148-
continue;
149153
}
150154

151155
final Index[] concreteIndices = indexNameExpressionResolver.concreteIndices(state, request.indicesOptions(), false,

x-pack/plugin/data-streams/src/internalClusterTest/java/org/elasticsearch/datastreams/DataStreamIT.java

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
import org.elasticsearch.action.update.UpdateRequest;
4444
import org.elasticsearch.cluster.ClusterState;
4545
import org.elasticsearch.cluster.health.ClusterHealthStatus;
46+
import org.elasticsearch.cluster.metadata.AliasMetadata;
4647
import org.elasticsearch.cluster.metadata.ComposableIndexTemplate;
4748
import org.elasticsearch.cluster.metadata.DataStream;
4849
import org.elasticsearch.cluster.metadata.DataStreamAlias;
@@ -754,6 +755,38 @@ public void testAddDataStreamAliasesMixedExpressionValidation() throws Exception
754755
assertThat(e.getMessage(), equalTo("expressions [metrics-*] that match with both data streams and regular indices are disallowed"));
755756
}
756757

758+
public void testRemoveDataStreamAliasesMixedExpression() throws Exception {
759+
createIndex("metrics-myindex");
760+
putComposableIndexTemplate("id1", List.of("metrics-*"));
761+
String dataStreamName = "metrics-foo";
762+
CreateDataStreamAction.Request createDataStreamRequest = new CreateDataStreamAction.Request(dataStreamName);
763+
client().execute(CreateDataStreamAction.INSTANCE, createDataStreamRequest).get();
764+
765+
IndicesAliasesRequest aliasesAddRequest = new IndicesAliasesRequest();
766+
aliasesAddRequest.addAliasAction(new AliasActions(AliasActions.Type.ADD).index("metrics-foo").aliases("my-alias1"));
767+
aliasesAddRequest.addAliasAction(new AliasActions(AliasActions.Type.ADD).index("metrics-myindex").aliases("my-alias2"));
768+
assertAcked(client().admin().indices().aliases(aliasesAddRequest).actionGet());
769+
GetAliasesResponse response = client().admin().indices().getAliases(new GetAliasesRequest()).actionGet();
770+
assertThat(
771+
response.getDataStreamAliases(),
772+
equalTo(Map.of("metrics-foo", List.of(new DataStreamAlias("my-alias1", List.of("metrics-foo"), null))))
773+
);
774+
assertThat(response.getAliases().get("metrics-myindex"), equalTo(List.of(new AliasMetadata.Builder("my-alias2").build())));
775+
776+
aliasesAddRequest = new IndicesAliasesRequest();
777+
if (randomBoolean()) {
778+
aliasesAddRequest.addAliasAction(new AliasActions(AliasActions.Type.REMOVE).index("_all").aliases("my-alias1"));
779+
aliasesAddRequest.addAliasAction(new AliasActions(AliasActions.Type.REMOVE).index("_all").aliases("my-alias2"));
780+
} else {
781+
aliasesAddRequest.addAliasAction(new AliasActions(AliasActions.Type.REMOVE).index("_all").aliases("my-*"));
782+
}
783+
assertAcked(client().admin().indices().aliases(aliasesAddRequest).actionGet());
784+
response = client().admin().indices().getAliases(new GetAliasesRequest()).actionGet();
785+
assertThat(response.getDataStreamAliases(), anEmptyMap());
786+
assertThat(response.getAliases().get("metrics-myindex").size(), equalTo(0));
787+
assertThat(response.getAliases().size(), equalTo(1));
788+
}
789+
757790
public void testUpdateDataStreamsWithWildcards() throws Exception {
758791
putComposableIndexTemplate("id1", List.of("metrics-*"));
759792
String dataStreamName = "metrics-foo";

0 commit comments

Comments
 (0)