|
@@ -15,6 +15,7 @@ import org.elasticsearch.action.ActionListener;
|
|
|
import org.elasticsearch.action.admin.cluster.health.ClusterHealthRequest;
|
|
|
import org.elasticsearch.action.admin.cluster.health.ClusterHealthResponse;
|
|
|
import org.elasticsearch.action.admin.indices.alias.IndicesAliasesRequest;
|
|
|
+import org.elasticsearch.action.admin.indices.alias.IndicesAliasesRequestBuilder;
|
|
|
import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
|
|
|
import org.elasticsearch.action.admin.indices.create.CreateIndexResponse;
|
|
|
import org.elasticsearch.action.support.master.AcknowledgedResponse;
|
|
@@ -30,6 +31,7 @@ import org.elasticsearch.xpack.core.ml.job.persistence.ElasticsearchMappings;
|
|
|
import org.elasticsearch.xpack.core.ml.utils.ExceptionsHelper;
|
|
|
import org.elasticsearch.xpack.core.template.TemplateUtils;
|
|
|
|
|
|
+import java.util.List;
|
|
|
import java.util.SortedMap;
|
|
|
|
|
|
import static org.elasticsearch.xpack.core.ClientHelper.ML_ORIGIN;
|
|
@@ -41,8 +43,15 @@ public class AnnotationIndex {
|
|
|
|
|
|
public static final String READ_ALIAS_NAME = ".ml-annotations-read";
|
|
|
public static final String WRITE_ALIAS_NAME = ".ml-annotations-write";
|
|
|
- // Exposed for testing, but always use the aliases in non-test code
|
|
|
- public static final String INDEX_NAME = ".ml-annotations-6";
|
|
|
+
|
|
|
+ // Exposed for testing, but always use the aliases in non-test code.
|
|
|
+ public static final String LATEST_INDEX_NAME = ".ml-annotations-000001";
|
|
|
+ // Due to historical bugs this index may not have the correct mappings
|
|
|
+ // in some production clusters. Therefore new annotations should be
|
|
|
+ // written to the latest index. If we ever switch to another new annotations
|
|
|
+ // index then this list should be adjusted to include the previous latest
|
|
|
+ // index.
|
|
|
+ public static final List<String> OLD_INDEX_NAMES = List.of(".ml-annotations-6");
|
|
|
|
|
|
private static final String MAPPINGS_VERSION_VARIABLE = "xpack.ml.version";
|
|
|
|
|
@@ -85,12 +94,18 @@ public class AnnotationIndex {
|
|
|
finalListener::onFailure);
|
|
|
|
|
|
final ActionListener<Boolean> createAliasListener = ActionListener.wrap(success -> {
|
|
|
- final IndicesAliasesRequest request =
|
|
|
+ final IndicesAliasesRequestBuilder requestBuilder =
|
|
|
client.admin().indices().prepareAliases()
|
|
|
- .addAliasAction(IndicesAliasesRequest.AliasActions.add().index(INDEX_NAME).alias(READ_ALIAS_NAME).isHidden(true))
|
|
|
- .addAliasAction(IndicesAliasesRequest.AliasActions.add().index(INDEX_NAME).alias(WRITE_ALIAS_NAME).isHidden(true))
|
|
|
- .request();
|
|
|
- executeAsyncWithOrigin(client.threadPool().getThreadContext(), ML_ORIGIN, request,
|
|
|
+ .addAliasAction(IndicesAliasesRequest.AliasActions.add()
|
|
|
+ .index(LATEST_INDEX_NAME).alias(READ_ALIAS_NAME).isHidden(true))
|
|
|
+ .addAliasAction(IndicesAliasesRequest.AliasActions.add()
|
|
|
+ .index(LATEST_INDEX_NAME).alias(WRITE_ALIAS_NAME).isHidden(true));
|
|
|
+ for (String oldIndexName : OLD_INDEX_NAMES) {
|
|
|
+ if (state.getMetadata().getIndicesLookup().containsKey(oldIndexName)) {
|
|
|
+ requestBuilder.removeAlias(oldIndexName, WRITE_ALIAS_NAME);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ executeAsyncWithOrigin(client.threadPool().getThreadContext(), ML_ORIGIN, requestBuilder.request(),
|
|
|
ActionListener.<AcknowledgedResponse>wrap(
|
|
|
r -> checkMappingsListener.onResponse(r.isAcknowledged()), finalListener::onFailure),
|
|
|
client.admin().indices()::aliases);
|
|
@@ -104,18 +119,18 @@ public class AnnotationIndex {
|
|
|
mlLookup.isEmpty() == false && mlLookup.firstKey().startsWith(".ml")) {
|
|
|
|
|
|
// Create the annotations index if it doesn't exist already.
|
|
|
- if (mlLookup.containsKey(INDEX_NAME) == false) {
|
|
|
+ if (mlLookup.containsKey(LATEST_INDEX_NAME) == false) {
|
|
|
logger.debug(
|
|
|
() -> new ParameterizedMessage(
|
|
|
"Creating [{}] because [{}] exists; trace {}",
|
|
|
- INDEX_NAME,
|
|
|
+ LATEST_INDEX_NAME,
|
|
|
mlLookup.firstKey(),
|
|
|
org.elasticsearch.ExceptionsHelper.formatStackTrace(Thread.currentThread().getStackTrace())
|
|
|
)
|
|
|
);
|
|
|
|
|
|
CreateIndexRequest createIndexRequest =
|
|
|
- new CreateIndexRequest(INDEX_NAME)
|
|
|
+ new CreateIndexRequest(LATEST_INDEX_NAME)
|
|
|
.mapping(annotationsMapping())
|
|
|
.settings(Settings.builder()
|
|
|
.put(IndexMetadata.SETTING_AUTO_EXPAND_REPLICAS, "0-1")
|
|
@@ -140,7 +155,14 @@ public class AnnotationIndex {
|
|
|
}
|
|
|
|
|
|
// Recreate the aliases if they've gone even though the index still exists.
|
|
|
- if (mlLookup.containsKey(READ_ALIAS_NAME) == false || mlLookup.containsKey(WRITE_ALIAS_NAME) == false) {
|
|
|
+ IndexAbstraction writeAliasDefinition = mlLookup.get(WRITE_ALIAS_NAME);
|
|
|
+ if (mlLookup.containsKey(READ_ALIAS_NAME) == false || writeAliasDefinition == null) {
|
|
|
+ createAliasListener.onResponse(true);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ List<IndexMetadata> writeAliasMetadata = writeAliasDefinition.getIndices();
|
|
|
+ if (writeAliasMetadata.size() != 1 || LATEST_INDEX_NAME.equals(writeAliasMetadata.get(0).getIndex().getName()) == false) {
|
|
|
createAliasListener.onResponse(true);
|
|
|
return;
|
|
|
}
|
|
@@ -154,7 +176,7 @@ public class AnnotationIndex {
|
|
|
finalListener.onResponse(false);
|
|
|
}
|
|
|
|
|
|
- private static String annotationsMapping() {
|
|
|
+ public static String annotationsMapping() {
|
|
|
return TemplateUtils.loadTemplate(
|
|
|
"/org/elasticsearch/xpack/core/ml/annotations_index_mappings.json", Version.CURRENT.toString(), MAPPINGS_VERSION_VARIABLE);
|
|
|
}
|