Skip to content

Commit

Permalink
[7.x] Add usage to get ILM policy response (elastic#74518) (elastic#7…
Browse files Browse the repository at this point in the history
  • Loading branch information
dakrone authored Jun 23, 2021
1 parent a322fd3 commit 16c0082
Show file tree
Hide file tree
Showing 9 changed files with 422 additions and 11 deletions.
6 changes: 6 additions & 0 deletions docs/reference/ilm/apis/get-lifecycle.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,11 @@ If the request succeeds, the body of the response contains the policy definition
}
}
}
},
"in_use_by" : { <3>
"indices" : [],
"data_streams" : [],
"composable_templates" : []
}
}
}
Expand All @@ -115,3 +120,4 @@ If the request succeeds, the body of the response contains the policy definition

<1> The policy version is incremented whenever the policy is updated
<2> When this policy was last modified
<3> Which indices, data streams, or templates currently use this policy
122 changes: 122 additions & 0 deletions server/src/main/java/org/elasticsearch/cluster/metadata/ItemUsage.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/

package org.elasticsearch.cluster.metadata;

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.xcontent.ToXContentObject;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.core.Nullable;

import java.io.IOException;
import java.util.Collection;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;

/**
* A class encapsulating the usage of a particular "thing" by something else
*/
public class ItemUsage implements Writeable, ToXContentObject {

private final Set<String> indices;
private final Set<String> dataStreams;
private final Set<String> composableTemplates;

/**
* Create a new usage, a {@code null} value indicates that the item *cannot* be used by the
* thing, otherwise use an empty collection to indicate no usage.
*/
public ItemUsage(@Nullable Collection<String> indices,
@Nullable Collection<String> dataStreams,
@Nullable Collection<String> composableTemplates) {
this.indices = indices == null ? null : new HashSet<>(indices);
this.dataStreams = dataStreams == null ? null : new HashSet<>(dataStreams);
this.composableTemplates = composableTemplates == null ? null : new HashSet<>(composableTemplates);
}

public ItemUsage(StreamInput in) throws IOException {
if (in.readBoolean()) {
this.indices = in.readSet(StreamInput::readString);
} else {
this.indices = null;
}
if (in.readBoolean()) {
this.dataStreams = in.readSet(StreamInput::readString);
} else {
this.dataStreams = null;
}
if (in.readBoolean()) {
this.composableTemplates = in.readSet(StreamInput::readString);
} else {
this.composableTemplates = null;
}
}

public Set<String> getIndices() {
return indices;
}

public Set<String> getDataStreams() {
return dataStreams;
}

public Set<String> getComposableTemplates() {
return composableTemplates;
}

@Override
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
builder.startObject();
if (this.indices != null) {
builder.field("indices", this.indices);
}
if (this.dataStreams != null) {
builder.field("data_streams", this.dataStreams);
}
if (this.composableTemplates != null) {
builder.field("composable_templates", this.composableTemplates);
}
builder.endObject();
return builder;
}

@Override
public void writeTo(StreamOutput out) throws IOException {
out.writeOptionalStringCollection(this.indices);
out.writeOptionalStringCollection(this.dataStreams);
out.writeOptionalStringCollection(this.composableTemplates);
}

@Override
public int hashCode() {
return Objects.hash(this.indices, this.dataStreams, this.composableTemplates);
}

@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
ItemUsage other = (ItemUsage) obj;
return Objects.equals(indices, other.indices) &&
Objects.equals(dataStreams, other.dataStreams) &&
Objects.equals(composableTemplates, other.composableTemplates);
}

@Override
public String toString() {
return Strings.toString(this);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/

package org.elasticsearch.cluster.metadata;

import org.elasticsearch.Version;
import org.elasticsearch.core.Nullable;
import org.elasticsearch.test.AbstractWireTestCase;

import java.io.IOException;
import java.util.List;

public class ItemUsageTests extends AbstractWireTestCase<ItemUsage> {

public static ItemUsage randomUsage() {
return new ItemUsage(randomStringList(), randomStringList(), randomStringList());
}

@Nullable
private static List<String> randomStringList() {
if (randomBoolean()) {
return null;
} else {
return randomList(0, 1, () -> randomAlphaOfLengthBetween(2, 10));
}
}

@Override
protected ItemUsage createTestInstance() {
return randomUsage();
}

@Override
protected ItemUsage copyInstance(ItemUsage instance, Version version) throws IOException {
return new ItemUsage(instance.getIndices(), instance.getDataStreams(), instance.getComposableTemplates());
}

@Override
protected ItemUsage mutateInstance(ItemUsage instance) throws IOException {
return super.mutateInstance(instance);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,15 @@
package org.elasticsearch.xpack.core.ilm;

import org.elasticsearch.ElasticsearchParseException;
import org.elasticsearch.action.support.IndicesOptions;
import org.elasticsearch.cluster.ClusterState;
import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver;
import org.elasticsearch.cluster.metadata.ItemUsage;
import org.elasticsearch.cluster.metadata.MetadataIndexTemplateService;
import org.elasticsearch.common.bytes.BytesArray;
import org.elasticsearch.common.bytes.BytesReference;
import org.elasticsearch.common.compress.NotXContentException;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.LoggingDeprecationHandler;
import org.elasticsearch.common.xcontent.NamedXContentRegistry;
import org.elasticsearch.common.xcontent.XContentHelper;
Expand All @@ -21,9 +27,12 @@
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;

/**
* A utility class used for loading index lifecycle policies from the resource classpath
* A utility class used for index lifecycle policies
*/
public class LifecyclePolicyUtils {

Expand Down Expand Up @@ -76,4 +85,41 @@ private static void validate(BytesReference source) {
throw new ElasticsearchParseException("invalid policy", e);
}
}

/**
* Given a cluster state and ILM policy, calculate the {@link ItemUsage} of
* the policy (what indices, data streams, and templates use the policy)
*/
public static ItemUsage calculateUsage(final IndexNameExpressionResolver indexNameExpressionResolver,
final ClusterState state, final String policyName) {
final List<String> indices = StreamSupport.stream(state.metadata().indices().values().spliterator(), false)
.map(cursor -> cursor.value)
.filter(indexMetadata -> policyName.equals(LifecycleSettings.LIFECYCLE_NAME_SETTING.get(indexMetadata.getSettings())))
.map(indexMetadata -> indexMetadata.getIndex().getName())
.collect(Collectors.toList());

final List<String> allDataStreams = indexNameExpressionResolver.dataStreamNames(state,
IndicesOptions.LENIENT_EXPAND_OPEN_CLOSED_HIDDEN);

final List<String> dataStreams = allDataStreams.stream()
.filter(dsName -> {
String indexTemplate = MetadataIndexTemplateService.findV2Template(state.metadata(), dsName, false);
if (indexTemplate != null) {
Settings settings = MetadataIndexTemplateService.resolveSettings(state.metadata(), indexTemplate);
return policyName.equals(LifecycleSettings.LIFECYCLE_NAME_SETTING.get(settings));
} else {
return false;
}
})
.collect(Collectors.toList());

final List<String> composableTemplates = state.metadata().templatesV2().keySet().stream()
.filter(templateName -> {
Settings settings = MetadataIndexTemplateService.resolveSettings(state.metadata(), templateName);
return policyName.equals(LifecycleSettings.LIFECYCLE_NAME_SETTING.get(settings));
})
.collect(Collectors.toList());

return new ItemUsage(indices, dataStreams, composableTemplates);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,12 @@

package org.elasticsearch.xpack.core.ilm.action;

import org.elasticsearch.Version;
import org.elasticsearch.action.ActionRequestValidationException;
import org.elasticsearch.action.ActionResponse;
import org.elasticsearch.action.ActionType;
import org.elasticsearch.action.support.master.AcknowledgedRequest;
import org.elasticsearch.cluster.metadata.ItemUsage;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
Expand All @@ -21,6 +23,7 @@

import java.io.IOException;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Objects;

Expand Down Expand Up @@ -57,6 +60,7 @@ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws
builder.field("version", item.getVersion());
builder.field("modified_date", item.getModifiedDate());
builder.field("policy", item.getLifecyclePolicy());
builder.field("in_use_by", item.getUsage());
builder.endObject();
}
builder.endObject();
Expand Down Expand Up @@ -149,24 +153,34 @@ public static class LifecyclePolicyResponseItem implements Writeable {
private final LifecyclePolicy lifecyclePolicy;
private final long version;
private final String modifiedDate;
private final ItemUsage usage;

public LifecyclePolicyResponseItem(LifecyclePolicy lifecyclePolicy, long version, String modifiedDate) {
public LifecyclePolicyResponseItem(LifecyclePolicy lifecyclePolicy, long version, String modifiedDate, ItemUsage usage) {
this.lifecyclePolicy = lifecyclePolicy;
this.version = version;
this.modifiedDate = modifiedDate;
this.usage = usage;
}

LifecyclePolicyResponseItem(StreamInput in) throws IOException {
this.lifecyclePolicy = new LifecyclePolicy(in);
this.version = in.readVLong();
this.modifiedDate = in.readString();
if (in.getVersion().onOrAfter(Version.V_7_14_0)) {
this.usage = new ItemUsage(in);
} else {
this.usage = new ItemUsage(Collections.emptyList(), Collections.emptyList(), Collections.emptyList());
}
}

@Override
public void writeTo(StreamOutput out) throws IOException {
lifecyclePolicy.writeTo(out);
out.writeVLong(version);
out.writeString(modifiedDate);
if (out.getVersion().onOrAfter(Version.V_7_14_0)) {
this.usage.writeTo(out);
}
}

public LifecyclePolicy getLifecyclePolicy() {
Expand All @@ -181,9 +195,13 @@ public String getModifiedDate() {
return modifiedDate;
}

public ItemUsage getUsage() {
return usage;
}

@Override
public int hashCode() {
return Objects.hash(lifecyclePolicy, version, modifiedDate);
return Objects.hash(lifecyclePolicy, version, modifiedDate, usage);
}

@Override
Expand All @@ -197,9 +215,9 @@ public boolean equals(Object obj) {
LifecyclePolicyResponseItem other = (LifecyclePolicyResponseItem) obj;
return Objects.equals(lifecyclePolicy, other.lifecyclePolicy) &&
Objects.equals(version, other.version) &&
Objects.equals(modifiedDate, other.modifiedDate);
Objects.equals(modifiedDate, other.modifiedDate) &&
Objects.equals(usage, other.usage);
}

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,10 @@ protected LifecyclePolicyMetadata doParseInstance(XContentParser parser) throws

@Override
protected LifecyclePolicyMetadata createTestInstance() {
return createRandomPolicyMetadata(lifecycleName);
}

public static LifecyclePolicyMetadata createRandomPolicyMetadata(String lifecycleName) {
Map<String, String> headers = new HashMap<>();
int numberHeaders = between(0, 10);
for (int i = 0; i < numberHeaders; i++) {
Expand Down
Loading

0 comments on commit 16c0082

Please sign in to comment.