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:
Colin Goodheart-Smithe 2018-10-24 18:28:46 +01:00 committed by GitHub
parent c7fe87e43f
commit e7fddb5c93
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 715 additions and 2 deletions

View File

@ -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);
}
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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()));
}
}
}

View File

@ -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();
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}