Adds usage data for ILM (#33377)
* Adds usage data for ILM * Adds tests for IndexLifecycleFeatureSetUsage and friends * Adds tests for IndexLifecycleFeatureSet * Fixes merge errors * Add number of indices managed to usage stats Also adds more tests * Addresses Review comments
This commit is contained in:
parent
c7fe87e43f
commit
e7fddb5c93
|
@ -5,19 +5,201 @@
|
|||
*/
|
||||
package org.elasticsearch.xpack.core.indexlifecycle;
|
||||
|
||||
import org.elasticsearch.common.ParseField;
|
||||
import org.elasticsearch.common.Strings;
|
||||
import org.elasticsearch.common.io.stream.StreamInput;
|
||||
import org.elasticsearch.common.io.stream.StreamOutput;
|
||||
import org.elasticsearch.common.io.stream.Writeable;
|
||||
import org.elasticsearch.common.unit.TimeValue;
|
||||
import org.elasticsearch.common.xcontent.ToXContentObject;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.xpack.core.XPackFeatureSet;
|
||||
import org.elasticsearch.xpack.core.XPackField;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
public class IndexLifecycleFeatureSetUsage extends XPackFeatureSet.Usage {
|
||||
|
||||
private List<PolicyStats> policyStats;
|
||||
|
||||
public IndexLifecycleFeatureSetUsage(StreamInput input) throws IOException {
|
||||
super(input);
|
||||
if (input.readBoolean()) {
|
||||
policyStats = input.readList(PolicyStats::new);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeTo(StreamOutput out) throws IOException {
|
||||
super.writeTo(out);
|
||||
boolean hasPolicyStats = policyStats != null;
|
||||
out.writeBoolean(hasPolicyStats);
|
||||
if (hasPolicyStats) {
|
||||
out.writeList(policyStats);
|
||||
}
|
||||
}
|
||||
|
||||
public IndexLifecycleFeatureSetUsage(boolean available, boolean enabled) {
|
||||
this(available, enabled, null);
|
||||
}
|
||||
|
||||
public IndexLifecycleFeatureSetUsage(boolean available, boolean enabled, List<PolicyStats> policyStats) {
|
||||
super(XPackField.INDEX_LIFECYCLE, available, enabled);
|
||||
this.policyStats = policyStats;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void innerXContent(XContentBuilder builder, Params params) throws IOException {
|
||||
if (policyStats != null) {
|
||||
builder.field("policy_count", policyStats.size());
|
||||
builder.field("policy_stats", policyStats);
|
||||
}
|
||||
}
|
||||
|
||||
public List<PolicyStats> getPolicyStats() {
|
||||
return policyStats;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(available, enabled, policyStats);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}
|
||||
IndexLifecycleFeatureSetUsage other = (IndexLifecycleFeatureSetUsage) obj;
|
||||
return Objects.equals(available, other.available) &&
|
||||
Objects.equals(enabled, other.enabled) &&
|
||||
Objects.equals(policyStats, other.policyStats);
|
||||
}
|
||||
|
||||
public static final class PolicyStats implements ToXContentObject, Writeable {
|
||||
|
||||
public static final ParseField INDICES_MANAGED_FIELD = new ParseField("indices_managed");
|
||||
|
||||
private final Map<String, PhaseStats> phaseStats;
|
||||
private final int indicesManaged;
|
||||
|
||||
public PolicyStats(Map<String, PhaseStats> phaseStats, int numberIndicesManaged) {
|
||||
this.phaseStats = phaseStats;
|
||||
this.indicesManaged = numberIndicesManaged;
|
||||
}
|
||||
|
||||
public PolicyStats(StreamInput in) throws IOException {
|
||||
this.phaseStats = in.readMap(StreamInput::readString, PhaseStats::new);
|
||||
this.indicesManaged = in.readVInt();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeTo(StreamOutput out) throws IOException {
|
||||
out.writeMap(phaseStats, StreamOutput::writeString, (o, p) -> p.writeTo(o));
|
||||
out.writeVInt(indicesManaged);
|
||||
}
|
||||
|
||||
@Override
|
||||
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
|
||||
builder.startObject();
|
||||
builder.field(LifecyclePolicy.PHASES_FIELD.getPreferredName(), phaseStats);
|
||||
builder.field(INDICES_MANAGED_FIELD.getPreferredName(), indicesManaged);
|
||||
builder.endObject();
|
||||
return builder;
|
||||
}
|
||||
|
||||
public Map<String, PhaseStats> getPhaseStats() {
|
||||
return phaseStats;
|
||||
}
|
||||
|
||||
public int getIndicesManaged() {
|
||||
return indicesManaged;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(phaseStats, indicesManaged);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}
|
||||
PolicyStats other = (PolicyStats) obj;
|
||||
return Objects.equals(phaseStats, other.phaseStats) &&
|
||||
Objects.equals(indicesManaged, other.indicesManaged);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return Strings.toString(this);
|
||||
}
|
||||
}
|
||||
|
||||
public static final class PhaseStats implements ToXContentObject, Writeable {
|
||||
private final String[] actionNames;
|
||||
private final TimeValue minimumAge;
|
||||
|
||||
public PhaseStats(TimeValue after, String[] actionNames) {
|
||||
this.actionNames = actionNames;
|
||||
this.minimumAge = after;
|
||||
}
|
||||
|
||||
public PhaseStats(StreamInput in) throws IOException {
|
||||
actionNames = in.readStringArray();
|
||||
minimumAge = in.readTimeValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeTo(StreamOutput out) throws IOException {
|
||||
out.writeStringArray(actionNames);
|
||||
out.writeTimeValue(minimumAge);
|
||||
}
|
||||
|
||||
@Override
|
||||
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
|
||||
builder.startObject();
|
||||
builder.field(Phase.MINIMUM_AGE.getPreferredName(), minimumAge.getMillis());
|
||||
builder.field(Phase.ACTIONS_FIELD.getPreferredName(), actionNames);
|
||||
builder.endObject();
|
||||
return builder;
|
||||
}
|
||||
|
||||
public String[] getActionNames() {
|
||||
return actionNames;
|
||||
}
|
||||
|
||||
public TimeValue getAfter() {
|
||||
return minimumAge;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(Arrays.hashCode(actionNames), minimumAge);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}
|
||||
PhaseStats other = (PhaseStats) obj;
|
||||
return Objects.equals(minimumAge, other.minimumAge) &&
|
||||
Objects.deepEquals(actionNames, other.actionNames);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* 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.core.indexlifecycle;
|
||||
|
||||
import org.elasticsearch.common.io.stream.Writeable.Reader;
|
||||
import org.elasticsearch.test.AbstractWireSerializingTestCase;
|
||||
import org.elasticsearch.xpack.core.indexlifecycle.IndexLifecycleFeatureSetUsage.PolicyStats;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class IndexLifecycleFeatureSetUsageTests extends AbstractWireSerializingTestCase<IndexLifecycleFeatureSetUsage> {
|
||||
|
||||
@Override
|
||||
protected IndexLifecycleFeatureSetUsage createTestInstance() {
|
||||
boolean enabled = randomBoolean();
|
||||
boolean available = randomBoolean();
|
||||
List<PolicyStats> policyStats = null;
|
||||
if (enabled) {
|
||||
int size = randomIntBetween(0, 10);
|
||||
policyStats = new ArrayList<>(size);
|
||||
for (int i = 0; i < size; i++) {
|
||||
policyStats.add(PolicyStatsTests.createRandomInstance());
|
||||
}
|
||||
}
|
||||
return new IndexLifecycleFeatureSetUsage(available, enabled, policyStats);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IndexLifecycleFeatureSetUsage mutateInstance(IndexLifecycleFeatureSetUsage instance) throws IOException {
|
||||
boolean available = instance.available();
|
||||
boolean enabled = instance.enabled();
|
||||
List<PolicyStats> policyStats = instance.getPolicyStats();
|
||||
switch (between(0, 2)) {
|
||||
case 0:
|
||||
available = available == false;
|
||||
break;
|
||||
case 1:
|
||||
enabled = enabled == false;
|
||||
break;
|
||||
case 2:
|
||||
if (policyStats == null) {
|
||||
policyStats = new ArrayList<>();
|
||||
policyStats.add(PolicyStatsTests.createRandomInstance());
|
||||
} else if (randomBoolean()) {
|
||||
policyStats = null;
|
||||
} else {
|
||||
policyStats = new ArrayList<>(policyStats);
|
||||
policyStats.add(PolicyStatsTests.createRandomInstance());
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new AssertionError("Illegal randomisation branch");
|
||||
}
|
||||
return new IndexLifecycleFeatureSetUsage(available, enabled, policyStats);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Reader<IndexLifecycleFeatureSetUsage> instanceReader() {
|
||||
return IndexLifecycleFeatureSetUsage::new;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* 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.core.indexlifecycle;
|
||||
|
||||
import org.elasticsearch.common.io.stream.Writeable.Reader;
|
||||
import org.elasticsearch.common.unit.TimeValue;
|
||||
import org.elasticsearch.test.AbstractWireSerializingTestCase;
|
||||
import org.elasticsearch.xpack.core.indexlifecycle.IndexLifecycleFeatureSetUsage.PhaseStats;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
|
||||
public class PhaseStatsTests extends AbstractWireSerializingTestCase<PhaseStats> {
|
||||
|
||||
@Override
|
||||
protected PhaseStats createTestInstance() {
|
||||
return createRandomInstance();
|
||||
}
|
||||
|
||||
public static PhaseStats createRandomInstance() {
|
||||
TimeValue after = TimeValue.parseTimeValue(randomTimeValue(), "phase_stats_tests");
|
||||
String[] actionNames = randomArray(0, 20, size -> new String[size], () -> randomAlphaOfLengthBetween(1, 20));
|
||||
return new PhaseStats(after, actionNames);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PhaseStats mutateInstance(PhaseStats instance) throws IOException {
|
||||
TimeValue after = instance.getAfter();
|
||||
String[] actionNames = instance.getActionNames();
|
||||
switch (between(0, 1)) {
|
||||
case 0:
|
||||
after = randomValueOtherThan(after, () -> TimeValue.parseTimeValue(randomPositiveTimeValue(), "rollover_action_test"));
|
||||
break;
|
||||
case 1:
|
||||
actionNames = randomValueOtherThanMany(a -> Arrays.equals(a, instance.getActionNames()),
|
||||
() -> randomArray(0, 20, size -> new String[size], () -> randomAlphaOfLengthBetween(1, 20)));
|
||||
break;
|
||||
default:
|
||||
throw new AssertionError("Illegal randomisation branch");
|
||||
}
|
||||
return new PhaseStats(after, actionNames);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Reader<PhaseStats> instanceReader() {
|
||||
return PhaseStats::new;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
* 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.core.indexlifecycle;
|
||||
|
||||
import org.elasticsearch.common.io.stream.Writeable.Reader;
|
||||
import org.elasticsearch.test.AbstractWireSerializingTestCase;
|
||||
import org.elasticsearch.xpack.core.indexlifecycle.IndexLifecycleFeatureSetUsage.PhaseStats;
|
||||
import org.elasticsearch.xpack.core.indexlifecycle.IndexLifecycleFeatureSetUsage.PolicyStats;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class PolicyStatsTests extends AbstractWireSerializingTestCase<PolicyStats> {
|
||||
|
||||
@Override
|
||||
protected PolicyStats createTestInstance() {
|
||||
return createRandomInstance();
|
||||
}
|
||||
|
||||
public static PolicyStats createRandomInstance() {
|
||||
int size = randomIntBetween(0, 10);
|
||||
Map<String, PhaseStats> phaseStats = new HashMap<>(size);
|
||||
for (int i = 0; i < size; i++) {
|
||||
phaseStats.put(randomAlphaOfLengthBetween(1, 20), PhaseStatsTests.createRandomInstance());
|
||||
}
|
||||
return new PolicyStats(phaseStats, randomIntBetween(0, 100));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PolicyStats mutateInstance(PolicyStats instance) throws IOException {
|
||||
Map<String, PhaseStats> phaseStats = instance.getPhaseStats();
|
||||
int indicesManaged = instance.getIndicesManaged();
|
||||
switch (between(0, 1)) {
|
||||
case 0:
|
||||
phaseStats = new HashMap<>(instance.getPhaseStats());
|
||||
phaseStats.put(randomAlphaOfLengthBetween(1, 20), PhaseStatsTests.createRandomInstance());
|
||||
break;
|
||||
case 1:
|
||||
indicesManaged = randomIntBetween(1, 50);
|
||||
break;
|
||||
default:
|
||||
throw new AssertionError("Illegal randomisation branch");
|
||||
}
|
||||
return new PolicyStats(phaseStats, indicesManaged);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Reader<PolicyStats> instanceReader() {
|
||||
return PolicyStats::new;
|
||||
}
|
||||
|
||||
}
|
|
@ -6,7 +6,10 @@
|
|||
package org.elasticsearch.xpack.indexlifecycle;
|
||||
|
||||
import org.elasticsearch.action.ActionListener;
|
||||
import org.elasticsearch.cluster.metadata.MetaData;
|
||||
import org.elasticsearch.cluster.service.ClusterService;
|
||||
import org.elasticsearch.common.Nullable;
|
||||
import org.elasticsearch.common.collect.Tuple;
|
||||
import org.elasticsearch.common.inject.Inject;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.license.XPackLicenseState;
|
||||
|
@ -14,16 +17,25 @@ import org.elasticsearch.xpack.core.XPackFeatureSet;
|
|||
import org.elasticsearch.xpack.core.XPackField;
|
||||
import org.elasticsearch.xpack.core.XPackSettings;
|
||||
import org.elasticsearch.xpack.core.indexlifecycle.IndexLifecycleFeatureSetUsage;
|
||||
import org.elasticsearch.xpack.core.indexlifecycle.IndexLifecycleFeatureSetUsage.PhaseStats;
|
||||
import org.elasticsearch.xpack.core.indexlifecycle.IndexLifecycleFeatureSetUsage.PolicyStats;
|
||||
import org.elasticsearch.xpack.core.indexlifecycle.IndexLifecycleMetadata;
|
||||
import org.elasticsearch.xpack.core.indexlifecycle.LifecycleSettings;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class IndexLifecycleFeatureSet implements XPackFeatureSet {
|
||||
|
||||
private final boolean enabled;
|
||||
private final XPackLicenseState licenseState;
|
||||
private ClusterService clusterService;
|
||||
|
||||
@Inject
|
||||
public IndexLifecycleFeatureSet(Settings settings, @Nullable XPackLicenseState licenseState) {
|
||||
public IndexLifecycleFeatureSet(Settings settings, @Nullable XPackLicenseState licenseState, ClusterService clusterService) {
|
||||
this.clusterService = clusterService;
|
||||
this.enabled = XPackSettings.INDEX_LIFECYCLE_ENABLED.get(settings);
|
||||
this.licenseState = licenseState;
|
||||
}
|
||||
|
@ -55,7 +67,31 @@ public class IndexLifecycleFeatureSet implements XPackFeatureSet {
|
|||
|
||||
@Override
|
||||
public void usage(ActionListener<XPackFeatureSet.Usage> listener) {
|
||||
listener.onResponse(new IndexLifecycleFeatureSetUsage(available(), enabled()));
|
||||
MetaData metaData = clusterService.state().metaData();
|
||||
IndexLifecycleMetadata lifecycleMetadata = metaData.custom(IndexLifecycleMetadata.TYPE);
|
||||
if (enabled() && lifecycleMetadata != null) {
|
||||
Map<String, Integer> policyUsage = new HashMap<>();
|
||||
metaData.indices().forEach(entry -> {
|
||||
String policyName = LifecycleSettings.LIFECYCLE_NAME_SETTING.get(entry.value.getSettings());
|
||||
Integer indicesManaged = policyUsage.get(policyName);
|
||||
if (indicesManaged == null) {
|
||||
indicesManaged = 1;
|
||||
} else {
|
||||
indicesManaged = indicesManaged + 1;
|
||||
}
|
||||
policyUsage.put(policyName, indicesManaged);
|
||||
});
|
||||
List<PolicyStats> policyStats = lifecycleMetadata.getPolicies().values().stream().map(policy -> {
|
||||
Map<String, PhaseStats> phaseStats = policy.getPhases().values().stream().map(phase -> {
|
||||
String[] actionNames = phase.getActions().keySet().toArray(new String[phase.getActions().size()]);
|
||||
return new Tuple<String, PhaseStats>(phase.getName(), new PhaseStats(phase.getMinimumAge(), actionNames));
|
||||
}).collect(Collectors.toMap(Tuple::v1, Tuple::v2));
|
||||
return new PolicyStats(phaseStats, policyUsage.getOrDefault(policy.getName(), 0));
|
||||
}).collect(Collectors.toList());
|
||||
listener.onResponse(new IndexLifecycleFeatureSetUsage(available(), enabled(), policyStats));
|
||||
} else {
|
||||
listener.onResponse(new IndexLifecycleFeatureSetUsage(available(), enabled()));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,146 @@
|
|||
/*
|
||||
* 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.elasticsearch.Version;
|
||||
import org.elasticsearch.action.support.PlainActionFuture;
|
||||
import org.elasticsearch.cluster.ClusterName;
|
||||
import org.elasticsearch.cluster.ClusterState;
|
||||
import org.elasticsearch.cluster.metadata.IndexMetaData;
|
||||
import org.elasticsearch.cluster.metadata.MetaData;
|
||||
import org.elasticsearch.cluster.service.ClusterService;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.license.XPackLicenseState;
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
import org.elasticsearch.xpack.core.indexlifecycle.IndexLifecycleFeatureSetUsage;
|
||||
import org.elasticsearch.xpack.core.indexlifecycle.IndexLifecycleFeatureSetUsage.PolicyStats;
|
||||
import org.elasticsearch.xpack.core.indexlifecycle.IndexLifecycleMetadata;
|
||||
import org.elasticsearch.xpack.core.indexlifecycle.LifecyclePolicy;
|
||||
import org.elasticsearch.xpack.core.indexlifecycle.LifecyclePolicyMetadata;
|
||||
import org.elasticsearch.xpack.core.indexlifecycle.LifecycleSettings;
|
||||
import org.elasticsearch.xpack.core.indexlifecycle.OperationMode;
|
||||
import org.elasticsearch.xpack.core.indexlifecycle.Phase;
|
||||
import org.junit.Before;
|
||||
import org.mockito.Mockito;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
public class IndexLifecycleFeatureSetTests extends ESTestCase {
|
||||
|
||||
private XPackLicenseState licenseState;
|
||||
private ClusterService clusterService;
|
||||
|
||||
@Before
|
||||
public void init() throws Exception {
|
||||
licenseState = mock(XPackLicenseState.class);
|
||||
clusterService = mock(ClusterService.class);
|
||||
}
|
||||
|
||||
public void testAvailable() {
|
||||
IndexLifecycleFeatureSet featureSet = new IndexLifecycleFeatureSet(Settings.EMPTY, licenseState, clusterService);
|
||||
|
||||
when(licenseState.isIndexLifecycleAllowed()).thenReturn(false);
|
||||
assertThat(featureSet.available(), equalTo(false));
|
||||
|
||||
when(licenseState.isIndexLifecycleAllowed()).thenReturn(true);
|
||||
assertThat(featureSet.available(), equalTo(true));
|
||||
|
||||
featureSet = new IndexLifecycleFeatureSet(Settings.EMPTY, null, clusterService);
|
||||
assertThat(featureSet.available(), equalTo(false));
|
||||
}
|
||||
|
||||
public void testEnabled() {
|
||||
Settings.Builder settings = Settings.builder().put("xpack.ilm.enabled", false);
|
||||
IndexLifecycleFeatureSet featureSet = new IndexLifecycleFeatureSet(settings.build(), licenseState, clusterService);
|
||||
assertThat(featureSet.enabled(), equalTo(false));
|
||||
|
||||
settings = Settings.builder().put("xpack.ilm.enabled", true);
|
||||
featureSet = new IndexLifecycleFeatureSet(settings.build(), licenseState, clusterService);
|
||||
assertThat(featureSet.enabled(), equalTo(true));
|
||||
}
|
||||
|
||||
public void testName() {
|
||||
IndexLifecycleFeatureSet featureSet = new IndexLifecycleFeatureSet(Settings.EMPTY, licenseState, clusterService);
|
||||
assertThat(featureSet.name(), equalTo("ilm"));
|
||||
}
|
||||
|
||||
public void testNativeCodeInfo() {
|
||||
IndexLifecycleFeatureSet featureSet = new IndexLifecycleFeatureSet(Settings.EMPTY, licenseState, clusterService);
|
||||
assertNull(featureSet.nativeCodeInfo());
|
||||
}
|
||||
|
||||
public void testUsageStats() throws Exception {
|
||||
Map<String, String> indexPolicies = new HashMap<>();
|
||||
List<LifecyclePolicy> policies = new ArrayList<>();
|
||||
String policy1Name = randomAlphaOfLength(10);
|
||||
String policy2Name = randomAlphaOfLength(10);
|
||||
String policy3Name = randomAlphaOfLength(10);
|
||||
indexPolicies.put("index_1", policy1Name);
|
||||
indexPolicies.put("index_2", policy1Name);
|
||||
indexPolicies.put("index_3", policy1Name);
|
||||
indexPolicies.put("index_4", policy1Name);
|
||||
indexPolicies.put("index_5", policy3Name);
|
||||
LifecyclePolicy policy1 = new LifecyclePolicy(policy1Name, Collections.emptyMap());
|
||||
policies.add(policy1);
|
||||
PolicyStats policy1Stats = new PolicyStats(Collections.emptyMap(), 4);
|
||||
|
||||
Map<String, Phase> phases1 = new HashMap<>();
|
||||
LifecyclePolicy policy2 = new LifecyclePolicy(policy2Name, phases1);
|
||||
policies.add(policy2);
|
||||
PolicyStats policy2Stats = new PolicyStats(Collections.emptyMap(), 0);
|
||||
|
||||
LifecyclePolicy policy3 = new LifecyclePolicy(policy3Name, Collections.emptyMap());
|
||||
policies.add(policy3);
|
||||
PolicyStats policy3Stats = new PolicyStats(Collections.emptyMap(), 1);
|
||||
|
||||
ClusterState clusterState = buildClusterState(policies, indexPolicies);
|
||||
Mockito.when(clusterService.state()).thenReturn(clusterState);
|
||||
|
||||
PlainActionFuture<IndexLifecycleFeatureSet.Usage> future = new PlainActionFuture<>();
|
||||
IndexLifecycleFeatureSet ilmFeatureSet = new IndexLifecycleFeatureSet(Settings.EMPTY, licenseState, clusterService);
|
||||
ilmFeatureSet.usage(future);
|
||||
IndexLifecycleFeatureSetUsage ilmUsage = (IndexLifecycleFeatureSetUsage) future.get();
|
||||
assertThat(ilmUsage.enabled(), equalTo(ilmFeatureSet.enabled()));
|
||||
assertThat(ilmUsage.available(), equalTo(ilmFeatureSet.available()));
|
||||
|
||||
List<PolicyStats> policyStatsList = ilmUsage.getPolicyStats();
|
||||
assertThat(policyStatsList.size(), equalTo(policies.size()));
|
||||
assertTrue(policyStatsList.contains(policy1Stats));
|
||||
assertTrue(policyStatsList.contains(policy2Stats));
|
||||
assertTrue(policyStatsList.contains(policy3Stats));
|
||||
|
||||
}
|
||||
|
||||
private ClusterState buildClusterState(List<LifecyclePolicy> lifecyclePolicies, Map<String, String> indexPolicies) {
|
||||
Map<String, LifecyclePolicyMetadata> lifecyclePolicyMetadatasMap = lifecyclePolicies.stream()
|
||||
.map(p -> new LifecyclePolicyMetadata(p, Collections.emptyMap(), 1, 0L))
|
||||
.collect(Collectors.toMap(LifecyclePolicyMetadata::getName, Function.identity()));
|
||||
IndexLifecycleMetadata indexLifecycleMetadata = new IndexLifecycleMetadata(lifecyclePolicyMetadatasMap, OperationMode.RUNNING);
|
||||
|
||||
MetaData.Builder metadata = MetaData.builder().putCustom(IndexLifecycleMetadata.TYPE, indexLifecycleMetadata);
|
||||
indexPolicies.forEach((indexName, policyName) -> {
|
||||
Settings indexSettings = Settings.builder().put(LifecycleSettings.LIFECYCLE_NAME, policyName)
|
||||
.put(IndexMetaData.SETTING_NUMBER_OF_SHARDS, 1)
|
||||
.put(IndexMetaData.SETTING_NUMBER_OF_REPLICAS, 0)
|
||||
.put(IndexMetaData.SETTING_VERSION_CREATED, Version.CURRENT).build();
|
||||
IndexMetaData.Builder indexMetadata = IndexMetaData.builder(indexName).settings(indexSettings);
|
||||
metadata.put(indexMetadata);
|
||||
});
|
||||
|
||||
return ClusterState.builder(new ClusterName("my_cluster")).metaData(metadata).build();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* 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.elasticsearch.common.io.stream.Writeable.Reader;
|
||||
import org.elasticsearch.test.AbstractWireSerializingTestCase;
|
||||
import org.elasticsearch.xpack.core.indexlifecycle.IndexLifecycleFeatureSetUsage;
|
||||
import org.elasticsearch.xpack.core.indexlifecycle.IndexLifecycleFeatureSetUsage.PolicyStats;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class IndexLifecycleFeatureSetUsageTests extends AbstractWireSerializingTestCase<IndexLifecycleFeatureSetUsage> {
|
||||
|
||||
@Override
|
||||
protected IndexLifecycleFeatureSetUsage createTestInstance() {
|
||||
boolean available = randomBoolean();
|
||||
boolean enabled = randomBoolean();
|
||||
List<PolicyStats> policyStats = new ArrayList<>();
|
||||
int size = randomIntBetween(0, 10);
|
||||
for (int i = 0; i < size; i++) {
|
||||
policyStats.add(PolicyStatsTests.randomPolicyStats());
|
||||
}
|
||||
return new IndexLifecycleFeatureSetUsage(available, enabled, policyStats);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IndexLifecycleFeatureSetUsage mutateInstance(IndexLifecycleFeatureSetUsage instance) throws IOException {
|
||||
boolean available = instance.available();
|
||||
boolean enabled = instance.enabled();
|
||||
List<PolicyStats> policyStats = instance.getPolicyStats();
|
||||
switch (between(0, 2)) {
|
||||
case 0:
|
||||
available = available == false;
|
||||
break;
|
||||
case 1:
|
||||
enabled = enabled == false;
|
||||
break;
|
||||
case 2:
|
||||
policyStats = new ArrayList<>(policyStats);
|
||||
policyStats.add(PolicyStatsTests.randomPolicyStats());
|
||||
break;
|
||||
default:
|
||||
throw new AssertionError("Illegal randomisation branch");
|
||||
}
|
||||
return new IndexLifecycleFeatureSetUsage(available, enabled, policyStats);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Reader<IndexLifecycleFeatureSetUsage> instanceReader() {
|
||||
return IndexLifecycleFeatureSetUsage::new;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* 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.elasticsearch.common.io.stream.Writeable.Reader;
|
||||
import org.elasticsearch.common.unit.TimeValue;
|
||||
import org.elasticsearch.test.AbstractWireSerializingTestCase;
|
||||
import org.elasticsearch.xpack.core.indexlifecycle.IndexLifecycleFeatureSetUsage.PhaseStats;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
|
||||
public class PhaseStatsTests extends AbstractWireSerializingTestCase<PhaseStats> {
|
||||
|
||||
@Override
|
||||
protected PhaseStats createTestInstance() {
|
||||
return randomPhaseStats();
|
||||
}
|
||||
|
||||
static PhaseStats randomPhaseStats() {
|
||||
TimeValue minimumAge = TimeValue.parseTimeValue(randomTimeValue(0, 1000000000, "s", "m", "h", "d"), "test_after");
|
||||
String[] actionNames = generateRandomStringArray(10, 20, false);
|
||||
return new PhaseStats(minimumAge, actionNames);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PhaseStats mutateInstance(PhaseStats instance) throws IOException {
|
||||
TimeValue minimumAge = instance.getAfter();
|
||||
String[] actionNames = instance.getActionNames();
|
||||
switch (between(0, 1)) {
|
||||
case 0:
|
||||
minimumAge = randomValueOtherThan(minimumAge,
|
||||
() -> TimeValue.parseTimeValue(randomTimeValue(0, 1000000000, "s", "m", "h", "d"), "test_after"));
|
||||
break;
|
||||
case 1:
|
||||
actionNames = Arrays.copyOf(actionNames, actionNames.length + 1);
|
||||
actionNames[actionNames.length - 1] = randomAlphaOfLengthBetween(10, 20);
|
||||
break;
|
||||
default:
|
||||
throw new AssertionError("Illegal randomisation branch");
|
||||
}
|
||||
return new PhaseStats(minimumAge, actionNames);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Reader<PhaseStats> instanceReader() {
|
||||
return PhaseStats::new;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* 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.elasticsearch.common.io.stream.Writeable.Reader;
|
||||
import org.elasticsearch.test.AbstractWireSerializingTestCase;
|
||||
import org.elasticsearch.xpack.core.indexlifecycle.IndexLifecycleFeatureSetUsage.PhaseStats;
|
||||
import org.elasticsearch.xpack.core.indexlifecycle.IndexLifecycleFeatureSetUsage.PolicyStats;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class PolicyStatsTests extends AbstractWireSerializingTestCase<PolicyStats> {
|
||||
|
||||
@Override
|
||||
protected PolicyStats createTestInstance() {
|
||||
return randomPolicyStats();
|
||||
}
|
||||
|
||||
static PolicyStats randomPolicyStats() {
|
||||
Map<String, PhaseStats> phaseStats = new HashMap<>();
|
||||
int size = randomIntBetween(0, 10);
|
||||
for (int i = 0; i < size; i++) {
|
||||
phaseStats.put(randomAlphaOfLength(10), PhaseStatsTests.randomPhaseStats());
|
||||
}
|
||||
int numberIndicesManaged = randomIntBetween(0, 1000);
|
||||
return new PolicyStats(phaseStats, numberIndicesManaged);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PolicyStats mutateInstance(PolicyStats instance) throws IOException {
|
||||
Map<String, PhaseStats> phaseStats = instance.getPhaseStats();
|
||||
int numberIndicesManaged = instance.getIndicesManaged();
|
||||
switch (between(0, 1)) {
|
||||
case 0:
|
||||
phaseStats = new HashMap<>(phaseStats);
|
||||
phaseStats.put(randomAlphaOfLength(10), PhaseStatsTests.randomPhaseStats());
|
||||
break;
|
||||
case 1:
|
||||
numberIndicesManaged += randomIntBetween(1, 10);
|
||||
break;
|
||||
default:
|
||||
throw new AssertionError("Illegal randomisation branch");
|
||||
}
|
||||
return new PolicyStats(phaseStats, numberIndicesManaged);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Reader<PolicyStats> instanceReader() {
|
||||
return PolicyStats::new;
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue