Skip to content

Commit

Permalink
[7.x] Migrate aliased indices to data stream (#66176)
Browse files Browse the repository at this point in the history
  • Loading branch information
danhermann authored Dec 10, 2020
1 parent 22bdecd commit 6830b7a
Show file tree
Hide file tree
Showing 16 changed files with 1,088 additions and 47 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,12 @@ public ComposableIndexTemplate(List<String> indexPatterns, @Nullable Template te
this(indexPatterns, template, componentTemplates, priority, version, metadata, null, null);
}

public ComposableIndexTemplate(List<String> indexPatterns, @Nullable Template template, @Nullable List<String> componentTemplates,
@Nullable Long priority, @Nullable Long version, @Nullable Map<String, Object> metadata,
@Nullable DataStreamTemplate dataStreamTemplate) {
this(indexPatterns, template, componentTemplates, priority, version, metadata, dataStreamTemplate, null);
}

public ComposableIndexTemplate(List<String> indexPatterns, @Nullable Template template, @Nullable List<String> componentTemplates,
@Nullable Long priority, @Nullable Long version, @Nullable Map<String, Object> metadata,
@Nullable DataStreamTemplate dataStreamTemplate, @Nullable Boolean allowAutoCreate) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,6 @@ public DataStream(String name, TimestampField timeStampField, List<Index> indice
this.hidden = hidden;
this.replicated = replicated;
assert indices.size() > 0;
assert indices.get(indices.size() - 1).getName().equals(getDefaultBackingIndexName(name, generation));
}

public DataStream(String name, TimestampField timeStampField, List<Index> indices) {
Expand All @@ -94,6 +93,10 @@ public long getGeneration() {
return generation;
}

public Index getWriteIndex() {
return indices.get(indices.size() - 1);
}

@Nullable
public Map<String, Object> getMetadata() {
return metadata;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@
import java.util.Objects;
import java.util.stream.Collectors;

import static org.elasticsearch.cluster.metadata.DataStream.getDefaultBackingIndexName;
import static org.elasticsearch.cluster.metadata.IndexMetadata.INDEX_HIDDEN_SETTING;
import static org.elasticsearch.common.collect.List.copyOf;

Expand Down Expand Up @@ -309,7 +308,6 @@ public DataStream(org.elasticsearch.cluster.metadata.DataStream dataStream, List
this.dataStream = dataStream;
this.dataStreamIndices = copyOf(dataStreamIndices);
this.writeIndex = dataStreamIndices.get(dataStreamIndices.size() - 1);
assert writeIndex.getIndex().getName().equals(getDefaultBackingIndexName(dataStream.getName(), dataStream.getGeneration()));
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,21 +33,24 @@
import org.elasticsearch.cluster.ack.ClusterStateUpdateRequest;
import org.elasticsearch.cluster.service.ClusterService;
import org.elasticsearch.common.Priority;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.xcontent.NamedXContentRegistry;
import org.elasticsearch.common.xcontent.ObjectPath;
import org.elasticsearch.index.Index;
import org.elasticsearch.index.mapper.MapperService;
import org.elasticsearch.index.mapper.MetadataFieldMapper;
import org.elasticsearch.rest.RestStatus;
import org.elasticsearch.threadpool.ThreadPool;

import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;

public class MetadataCreateDataStreamService {

Expand Down Expand Up @@ -116,54 +119,81 @@ public CreateDataStreamClusterStateUpdateRequest(String name,
static ClusterState createDataStream(MetadataCreateIndexService metadataCreateIndexService,
ClusterState currentState,
CreateDataStreamClusterStateUpdateRequest request) throws Exception {
return createDataStream(metadataCreateIndexService, currentState, request.name, org.elasticsearch.common.collect.List.of(), null);
}

/**
* Creates a data stream with the specified properties.
*
* @param metadataCreateIndexService Used if a new write index must be created
* @param currentState Cluster state
* @param dataStreamName Name of the data stream
* @param backingIndices List of backing indices. May be empty
* @param writeIndex Write index for the data stream. If null, a new write index will be created.
* @return Cluster state containing the new data stream
*/
static ClusterState createDataStream(MetadataCreateIndexService metadataCreateIndexService,
ClusterState currentState,
String dataStreamName,
List<IndexMetadata> backingIndices,
IndexMetadata writeIndex) throws Exception
{
if (currentState.nodes().getMinNodeVersion().before(Version.V_7_9_0)) {
throw new IllegalStateException("data streams require minimum node version of " + Version.V_7_9_0);
}

if (currentState.metadata().dataStreams().containsKey(request.name)) {
throw new ResourceAlreadyExistsException("data_stream [" + request.name + "] already exists");
if (writeIndex == null) {
Objects.requireNonNull(metadataCreateIndexService);
}
Objects.requireNonNull(currentState);
Objects.requireNonNull(backingIndices);
if (currentState.metadata().dataStreams().containsKey(dataStreamName)) {
throw new ResourceAlreadyExistsException("data_stream [" + dataStreamName + "] already exists");
}

MetadataCreateIndexService.validateIndexOrAliasName(request.name,
MetadataCreateIndexService.validateIndexOrAliasName(dataStreamName,
(s1, s2) -> new IllegalArgumentException("data_stream [" + s1 + "] " + s2));

if (request.name.toLowerCase(Locale.ROOT).equals(request.name) == false) {
throw new IllegalArgumentException("data_stream [" + request.name + "] must be lowercase");
if (dataStreamName.toLowerCase(Locale.ROOT).equals(dataStreamName) == false) {
throw new IllegalArgumentException("data_stream [" + dataStreamName + "] must be lowercase");
}
if (request.name.startsWith(DataStream.BACKING_INDEX_PREFIX)) {
throw new IllegalArgumentException("data_stream [" + request.name + "] must not start with '"
if (dataStreamName.startsWith(DataStream.BACKING_INDEX_PREFIX)) {
throw new IllegalArgumentException("data_stream [" + dataStreamName + "] must not start with '"
+ DataStream.BACKING_INDEX_PREFIX + "'");
}

ComposableIndexTemplate template = lookupTemplateForDataStream(request.name, currentState.metadata());

String firstBackingIndexName = DataStream.getDefaultBackingIndexName(request.name, 1);
CreateIndexClusterStateUpdateRequest createIndexRequest =
new CreateIndexClusterStateUpdateRequest("initialize_data_stream", firstBackingIndexName, firstBackingIndexName)
.dataStreamName(request.name)
.settings(Settings.builder().put("index.hidden", true).build());
try {
currentState = metadataCreateIndexService.applyCreateIndexRequest(currentState, createIndexRequest, false);
} catch (ResourceAlreadyExistsException e) {
// Rethrow as ElasticsearchStatusException, so that bulk transport action doesn't ignore it during
// auto index/data stream creation.
// (otherwise bulk execution fails later, because data stream will also not have been created)
throw new ElasticsearchStatusException("data stream could not be created because backing index [{}] already exists",
RestStatus.BAD_REQUEST, e, firstBackingIndexName);
ComposableIndexTemplate template = lookupTemplateForDataStream(dataStreamName, currentState.metadata());

if (writeIndex == null) {
String firstBackingIndexName = DataStream.getDefaultBackingIndexName(dataStreamName, 1);
CreateIndexClusterStateUpdateRequest createIndexRequest =
new CreateIndexClusterStateUpdateRequest("initialize_data_stream", firstBackingIndexName, firstBackingIndexName)
.dataStreamName(dataStreamName)
.settings(Settings.builder().put("index.hidden", true).build());
try {
currentState = metadataCreateIndexService.applyCreateIndexRequest(currentState, createIndexRequest, false);
} catch (ResourceAlreadyExistsException e) {
// Rethrow as ElasticsearchStatusException, so that bulk transport action doesn't ignore it during
// auto index/data stream creation.
// (otherwise bulk execution fails later, because data stream will also not have been created)
throw new ElasticsearchStatusException("data stream could not be created because backing index [{}] already exists",
RestStatus.BAD_REQUEST, e, firstBackingIndexName);
}
writeIndex = currentState.metadata().index(firstBackingIndexName);
}
IndexMetadata firstBackingIndex = currentState.metadata().index(firstBackingIndexName);
assert firstBackingIndex != null;
assert firstBackingIndex.mapping() != null : "no mapping found for backing index [" + firstBackingIndexName + "]";
assert writeIndex != null;
assert writeIndex.mapping() != null : "no mapping found for backing index [" + writeIndex.getIndex().getName() + "]";

String fieldName = template.getDataStreamTemplate().getTimestampField();
DataStream.TimestampField timestampField = new DataStream.TimestampField(fieldName);
List<Index> dsBackingIndices = backingIndices.stream().map(IndexMetadata::getIndex).collect(Collectors.toList());
dsBackingIndices.add(writeIndex.getIndex());
boolean hidden = template.getDataStreamTemplate().isHidden();
DataStream newDataStream =
new DataStream(request.name, timestampField,
Collections.singletonList(firstBackingIndex.getIndex()), 1L,
template.metadata() != null ? Collections.unmodifiableMap(new HashMap<>(template.metadata())) : null, hidden, false);
DataStream newDataStream = new DataStream(dataStreamName, timestampField, dsBackingIndices, 1L,
template.metadata() != null ? org.elasticsearch.common.collect.Map.copyOf(template.metadata()) : null, hidden, false);
Metadata.Builder builder = Metadata.builder(currentState.metadata()).put(newDataStream);
logger.info("adding data stream [{}]", request.name);
logger.info("adding data stream [{}] with write index [{}] and backing indices [{}]", dataStreamName,
writeIndex.getIndex().getName(),
Strings.arrayToCommaDelimitedString(backingIndices.stream().map(i -> i.getIndex().getName()).toArray()));
return ClusterState.builder(currentState).metadata(builder).build();
}

Expand Down
Loading

0 comments on commit 6830b7a

Please sign in to comment.