add Rest tests to index-lifecycle (#30159)
* add QA-style Rest tests to index-lifecycle This PR introduces a `qa` module within the index-lifecycle project. the idea is to have both complex policies tested, as well as policies with isolated/singular actions. So far, only tests with policies containing one action are implemented. Following Actions have implemented tests in this commit - AllocateAction - DeleteAction - ForceMergeAction - ReadOnlyAction - ReplicasAction tests to be added later - RolloverAction - ShrinkAction * respond to review and enable integTests * fix dependsOn fiasco * fix license * update to new proj structure * move to new integTest with x-pack-core as module * remove unused imports * update to use module instead of plugin
This commit is contained in:
parent
4e757fff21
commit
2814557679
|
@ -1,6 +1,7 @@
|
||||||
evaluationDependsOn(xpackModule('core'))
|
evaluationDependsOn(xpackModule('core'))
|
||||||
|
|
||||||
apply plugin: 'elasticsearch.esplugin'
|
apply plugin: 'elasticsearch.esplugin'
|
||||||
|
|
||||||
esplugin {
|
esplugin {
|
||||||
name 'x-pack-index-lifecycle'
|
name 'x-pack-index-lifecycle'
|
||||||
description 'Elasticsearch Expanded Pack Plugin - Index Lifecycle'
|
description 'Elasticsearch Expanded Pack Plugin - Index Lifecycle'
|
||||||
|
@ -11,16 +12,23 @@ esplugin {
|
||||||
}
|
}
|
||||||
archivesBaseName = 'x-pack-index-lifecycle'
|
archivesBaseName = 'x-pack-index-lifecycle'
|
||||||
|
|
||||||
// TODO: enable this once we have tests
|
|
||||||
licenseHeaders.enabled = false
|
|
||||||
|
|
||||||
integTest.enabled = false
|
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
compileOnly "org.elasticsearch.plugin:x-pack-core:${version}"
|
compileOnly "org.elasticsearch.plugin:x-pack-core:${version}"
|
||||||
testCompile project(path: xpackModule('core'), configuration: 'testArtifacts')
|
testCompile project(path: xpackModule('core'), configuration: 'testArtifacts')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
integTestCluster {
|
||||||
|
numNodes = 2
|
||||||
|
clusterName = 'index-lifecycle'
|
||||||
|
setting 'xpack.security.enabled', 'false'
|
||||||
|
setting 'xpack.watcher.enabled', 'false'
|
||||||
|
setting 'xpack.monitoring.enabled', 'false'
|
||||||
|
setting 'xpack.ml.enabled', 'false'
|
||||||
|
setting 'xpack.index_lifecycle.enabled', 'true'
|
||||||
|
setting 'indices.lifecycle.poll_interval', '500ms'
|
||||||
|
module project(xpackModule('core'))
|
||||||
|
}
|
||||||
|
|
||||||
run {
|
run {
|
||||||
plugin xpackModule('core')
|
plugin xpackModule('core')
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,164 @@
|
||||||
|
/*
|
||||||
|
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||||
|
* or more contributor license agreements. Licensed under the Elastic License;
|
||||||
|
* you may not use this file except in compliance with the Elastic License.
|
||||||
|
*/
|
||||||
|
package org.elasticsearch.xpack.indexlifecycle;
|
||||||
|
|
||||||
|
import org.apache.http.entity.ContentType;
|
||||||
|
import org.apache.http.entity.StringEntity;
|
||||||
|
import org.elasticsearch.cluster.metadata.IndexMetaData;
|
||||||
|
import org.elasticsearch.common.Strings;
|
||||||
|
import org.elasticsearch.common.settings.Settings;
|
||||||
|
import org.elasticsearch.common.unit.TimeValue;
|
||||||
|
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||||
|
import org.elasticsearch.test.rest.ESRestTestCase;
|
||||||
|
import org.elasticsearch.xpack.core.indexlifecycle.AllocateAction;
|
||||||
|
import org.elasticsearch.xpack.core.indexlifecycle.DeleteAction;
|
||||||
|
import org.elasticsearch.xpack.core.indexlifecycle.ForceMergeAction;
|
||||||
|
import org.elasticsearch.xpack.core.indexlifecycle.LifecycleAction;
|
||||||
|
import org.elasticsearch.xpack.core.indexlifecycle.LifecyclePolicy;
|
||||||
|
import org.elasticsearch.xpack.core.indexlifecycle.LifecycleSettings;
|
||||||
|
import org.elasticsearch.xpack.core.indexlifecycle.Phase;
|
||||||
|
import org.elasticsearch.xpack.core.indexlifecycle.ReadOnlyAction;
|
||||||
|
import org.elasticsearch.xpack.core.indexlifecycle.ReplicasAction;
|
||||||
|
import org.elasticsearch.xpack.core.indexlifecycle.Step.StepKey;
|
||||||
|
import org.elasticsearch.xpack.core.indexlifecycle.TerminalPolicyStep;
|
||||||
|
import org.elasticsearch.xpack.core.indexlifecycle.TimeseriesLifecycleType;
|
||||||
|
import org.junit.Before;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
import static java.util.Collections.singletonMap;
|
||||||
|
import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
|
||||||
|
import static org.hamcrest.Matchers.equalTo;
|
||||||
|
import static org.hamcrest.Matchers.greaterThan;
|
||||||
|
|
||||||
|
public class TimeSeriesLifecycleActionsIT extends ESRestTestCase {
|
||||||
|
private String index;
|
||||||
|
private String policy;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void refreshIndex() {
|
||||||
|
index = randomAlphaOfLength(10).toLowerCase(Locale.ROOT);
|
||||||
|
policy = randomAlphaOfLength(5);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testAllocate() throws Exception {
|
||||||
|
createIndexWithSettings(index, Settings.builder().put(IndexMetaData.SETTING_NUMBER_OF_SHARDS, 2)
|
||||||
|
.put(IndexMetaData.SETTING_NUMBER_OF_REPLICAS, 0));
|
||||||
|
String allocateNodeName = "node-" + randomFrom(0, 1);
|
||||||
|
AllocateAction allocateAction = new AllocateAction(null, null, singletonMap("_name", allocateNodeName));
|
||||||
|
createNewSingletonPolicy("warm", allocateAction);
|
||||||
|
updateIndexSettings(index, Settings.builder().put(LifecycleSettings.LIFECYCLE_NAME, policy));
|
||||||
|
assertBusy(() -> {
|
||||||
|
Map<String, Object> settings = getOnlyIndexSettings(index);
|
||||||
|
assertThat(getStepKey(settings), equalTo(TerminalPolicyStep.KEY));
|
||||||
|
});
|
||||||
|
ensureGreen(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testDelete() throws Exception {
|
||||||
|
createIndexWithSettings(index, Settings.builder().put(IndexMetaData.SETTING_NUMBER_OF_SHARDS, 1)
|
||||||
|
.put(IndexMetaData.SETTING_NUMBER_OF_REPLICAS, 0));
|
||||||
|
createNewSingletonPolicy("delete", new DeleteAction());
|
||||||
|
updateIndexSettings(index, Settings.builder().put(LifecycleSettings.LIFECYCLE_NAME, policy));
|
||||||
|
assertBusy(() -> assertFalse(indexExists(index)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testReadOnly() throws Exception {
|
||||||
|
createIndexWithSettings(index, Settings.builder().put(IndexMetaData.SETTING_NUMBER_OF_SHARDS, 1)
|
||||||
|
.put(IndexMetaData.SETTING_NUMBER_OF_REPLICAS, 0));
|
||||||
|
createNewSingletonPolicy("warm", new ReadOnlyAction());
|
||||||
|
updateIndexSettings(index, Settings.builder().put(LifecycleSettings.LIFECYCLE_NAME, policy));
|
||||||
|
assertBusy(() -> {
|
||||||
|
Map<String, Object> settings = getOnlyIndexSettings(index);
|
||||||
|
assertThat(getStepKey(settings), equalTo(TerminalPolicyStep.KEY));
|
||||||
|
assertThat(settings.get(IndexMetaData.INDEX_BLOCKS_WRITE_SETTING.getKey()), equalTo("true"));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public void testForceMergeAction() throws Exception {
|
||||||
|
createIndexWithSettings(index, Settings.builder().put(IndexMetaData.SETTING_NUMBER_OF_SHARDS, 1)
|
||||||
|
.put(IndexMetaData.SETTING_NUMBER_OF_REPLICAS, 0));
|
||||||
|
for (int i = 0; i < randomIntBetween(2, 10); i++) {
|
||||||
|
client().performRequest("PUT", index + "/_doc/" + i, singletonMap("refresh", "true"),
|
||||||
|
new StringEntity("{\"a\": \"test\"}", ContentType.APPLICATION_JSON));
|
||||||
|
}
|
||||||
|
|
||||||
|
Supplier<Integer> numSegments = () -> {
|
||||||
|
try {
|
||||||
|
Map<String, Object> segmentResponse = getAsMap(index + "/_segments");
|
||||||
|
segmentResponse = (Map<String, Object>) segmentResponse.get("indices");
|
||||||
|
segmentResponse = (Map<String, Object>) segmentResponse.get(index);
|
||||||
|
segmentResponse = (Map<String, Object>) segmentResponse.get("shards");
|
||||||
|
List<Map<String, Object>> shards = (List<Map<String, Object>>) segmentResponse.get("0");
|
||||||
|
return (Integer) shards.get(0).get("num_search_segments");
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
assertThat(numSegments.get(), greaterThan(1));
|
||||||
|
|
||||||
|
createNewSingletonPolicy("warm", new ForceMergeAction(1, false));
|
||||||
|
updateIndexSettings(index, Settings.builder().put(LifecycleSettings.LIFECYCLE_NAME, policy));
|
||||||
|
|
||||||
|
assertBusy(() -> {
|
||||||
|
assertThat(getStepKey(getOnlyIndexSettings(index)), equalTo(TerminalPolicyStep.KEY));
|
||||||
|
assertThat(numSegments.get(), equalTo(1));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testReplicasAction() throws Exception {
|
||||||
|
int numShards = randomFrom(1, 5);
|
||||||
|
int numReplicas = randomFrom(0, 1);
|
||||||
|
int finalNumReplicas = (numReplicas + 1) % 2;
|
||||||
|
createIndexWithSettings(index, Settings.builder().put(IndexMetaData.SETTING_NUMBER_OF_SHARDS, numShards)
|
||||||
|
.put(IndexMetaData.SETTING_NUMBER_OF_REPLICAS, numReplicas));
|
||||||
|
createNewSingletonPolicy("warm", new ReplicasAction(finalNumReplicas));
|
||||||
|
updateIndexSettings(index, Settings.builder().put(LifecycleSettings.LIFECYCLE_NAME, policy));
|
||||||
|
|
||||||
|
assertBusy(() -> {
|
||||||
|
Map<String, Object> settings = getOnlyIndexSettings(index);
|
||||||
|
assertThat(getStepKey(settings), equalTo(TerminalPolicyStep.KEY));
|
||||||
|
assertThat(settings.get(IndexMetaData.INDEX_NUMBER_OF_REPLICAS_SETTING.getKey()), equalTo(String.valueOf(finalNumReplicas)));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createNewSingletonPolicy(String phaseName, LifecycleAction action) throws IOException {
|
||||||
|
Phase phase = new Phase(phaseName, TimeValue.ZERO, singletonMap(action.getWriteableName(), action));
|
||||||
|
LifecyclePolicy lifecyclePolicy =
|
||||||
|
new LifecyclePolicy(TimeseriesLifecycleType.INSTANCE, policy, singletonMap(phase.getName(), phase));
|
||||||
|
XContentBuilder builder = jsonBuilder();
|
||||||
|
lifecyclePolicy.toXContent(builder, null);
|
||||||
|
final StringEntity entity = new StringEntity(
|
||||||
|
"{ \"policy\":" + Strings.toString(builder) + "}", ContentType.APPLICATION_JSON);
|
||||||
|
client().performRequest("PUT", "_xpack/index_lifecycle/" + policy, Collections.emptyMap(), entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createIndexWithSettings(String index, Settings.Builder settings) throws IOException {
|
||||||
|
// create the test-index index
|
||||||
|
createIndex(index, settings.build());
|
||||||
|
// wait for the shards to initialize
|
||||||
|
ensureGreen(index);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
private Map<String, Object> getOnlyIndexSettings(String index) throws IOException {
|
||||||
|
return (Map<String, Object>) ((Map<String, Object>) getIndexSettings(index).get(index)).get("settings");
|
||||||
|
}
|
||||||
|
|
||||||
|
private StepKey getStepKey(Map<String, Object> settings) {
|
||||||
|
String phase = (String) settings.get(LifecycleSettings.LIFECYCLE_PHASE);
|
||||||
|
String action = (String) settings.get(LifecycleSettings.LIFECYCLE_ACTION);
|
||||||
|
String step = (String) settings.get(LifecycleSettings.LIFECYCLE_STEP);
|
||||||
|
return new StepKey(phase, action, step);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue