Skip to content

Commit 20e57fe

Browse files
committed
Add RemoveBlock core service implementation
- Add RemoveIndexBlockRequest/Response/ClusterStateUpdateRequest classes - Add removeIndexBlock method to MetadataIndexStateService Provides core service infrastructure for removing index blocks.
1 parent 8d0c9ce commit 20e57fe

File tree

5 files changed

+515
-1
lines changed

5 files changed

+515
-1
lines changed
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the "Elastic License
4+
* 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
5+
* Public License v 1"; you may not use this file except in compliance with, at
6+
* your election, the "Elastic License 2.0", the "GNU Affero General Public
7+
* License v3.0 only", or the "Server Side Public License, v 1".
8+
*/
9+
package org.elasticsearch.action.admin.indices.readonly;
10+
11+
import org.elasticsearch.cluster.metadata.IndexMetadata.APIBlock;
12+
import org.elasticsearch.cluster.metadata.ProjectId;
13+
import org.elasticsearch.core.TimeValue;
14+
import org.elasticsearch.index.Index;
15+
16+
import java.util.Objects;
17+
18+
/**
19+
* Cluster state update request that allows to remove a block from one or more indices
20+
*/
21+
public record RemoveIndexBlockClusterStateUpdateRequest(
22+
TimeValue masterNodeTimeout,
23+
TimeValue ackTimeout,
24+
ProjectId projectId,
25+
APIBlock block,
26+
long taskId,
27+
Index[] indices
28+
) {
29+
public RemoveIndexBlockClusterStateUpdateRequest {
30+
Objects.requireNonNull(masterNodeTimeout);
31+
Objects.requireNonNull(ackTimeout);
32+
Objects.requireNonNull(projectId);
33+
Objects.requireNonNull(block);
34+
Objects.requireNonNull(indices);
35+
}
36+
}
Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the "Elastic License
4+
* 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
5+
* Public License v 1"; you may not use this file except in compliance with, at
6+
* your election, the "Elastic License 2.0", the "GNU Affero General Public
7+
* License v3.0 only", or the "Server Side Public License, v 1".
8+
*/
9+
10+
package org.elasticsearch.action.admin.indices.readonly;
11+
12+
import org.elasticsearch.action.ActionRequestValidationException;
13+
import org.elasticsearch.action.IndicesRequest;
14+
import org.elasticsearch.action.support.IndicesOptions;
15+
import org.elasticsearch.action.support.master.AcknowledgedRequest;
16+
import org.elasticsearch.cluster.metadata.IndexMetadata.APIBlock;
17+
import org.elasticsearch.common.io.stream.StreamInput;
18+
import org.elasticsearch.common.io.stream.StreamOutput;
19+
import org.elasticsearch.common.util.CollectionUtils;
20+
21+
import java.io.IOException;
22+
import java.util.Arrays;
23+
import java.util.Objects;
24+
25+
import static org.elasticsearch.action.ValidateActions.addValidationError;
26+
27+
/**
28+
* A request to remove a block from an index.
29+
*/
30+
public class RemoveIndexBlockRequest extends AcknowledgedRequest<RemoveIndexBlockRequest> implements IndicesRequest.Replaceable {
31+
32+
private final APIBlock block;
33+
private String[] indices;
34+
private IndicesOptions indicesOptions = IndicesOptions.strictExpandOpen();
35+
36+
public RemoveIndexBlockRequest(StreamInput in) throws IOException {
37+
super(in);
38+
indices = in.readStringArray();
39+
indicesOptions = IndicesOptions.readIndicesOptions(in);
40+
block = APIBlock.readFrom(in);
41+
}
42+
43+
/**
44+
* Constructs a new request for the specified block and indices
45+
*/
46+
public RemoveIndexBlockRequest(APIBlock block, String... indices) {
47+
super(TRAPPY_IMPLICIT_DEFAULT_MASTER_NODE_TIMEOUT, DEFAULT_ACK_TIMEOUT);
48+
this.block = Objects.requireNonNull(block);
49+
this.indices = Objects.requireNonNull(indices);
50+
}
51+
52+
@Override
53+
public ActionRequestValidationException validate() {
54+
ActionRequestValidationException validationException = null;
55+
if (CollectionUtils.isEmpty(indices)) {
56+
validationException = addValidationError("index is missing", validationException);
57+
}
58+
if (block == APIBlock.READ_ONLY_ALLOW_DELETE) {
59+
validationException = addValidationError("read_only_allow_delete block is for internal use only", validationException);
60+
}
61+
return validationException;
62+
}
63+
64+
/**
65+
* Returns the indices to have blocks removed
66+
*/
67+
@Override
68+
public String[] indices() {
69+
return indices;
70+
}
71+
72+
/**
73+
* Sets the indices to have blocks removed
74+
* @param indices the indices to have blocks removed
75+
* @return the request itself
76+
*/
77+
@Override
78+
public RemoveIndexBlockRequest indices(String... indices) {
79+
this.indices = Objects.requireNonNull(indices);
80+
return this;
81+
}
82+
83+
/**
84+
* Specifies what type of requested indices to ignore and how to deal with wildcard expressions.
85+
* For example indices that don't exist.
86+
*
87+
* @return the desired behaviour regarding indices to ignore and wildcard indices expressions
88+
*/
89+
@Override
90+
public IndicesOptions indicesOptions() {
91+
return indicesOptions;
92+
}
93+
94+
/**
95+
* Specifies what type of requested indices to ignore and how to deal wild wildcard expressions.
96+
* For example indices that don't exist.
97+
*
98+
* @param indicesOptions the desired behaviour regarding indices to ignore and wildcard indices expressions
99+
* @return the request itself
100+
*/
101+
public RemoveIndexBlockRequest indicesOptions(IndicesOptions indicesOptions) {
102+
this.indicesOptions = indicesOptions;
103+
return this;
104+
}
105+
106+
/**
107+
* Returns the block to be removed
108+
*/
109+
public APIBlock getBlock() {
110+
return block;
111+
}
112+
113+
@Override
114+
public void writeTo(StreamOutput out) throws IOException {
115+
super.writeTo(out);
116+
out.writeStringArray(indices);
117+
indicesOptions.writeIndicesOptions(out);
118+
block.writeTo(out);
119+
}
120+
121+
@Override
122+
public boolean equals(Object o) {
123+
if (this == o) {
124+
return true;
125+
}
126+
if (o == null || getClass() != o.getClass()) {
127+
return false;
128+
}
129+
RemoveIndexBlockRequest that = (RemoveIndexBlockRequest) o;
130+
return block == that.block && Arrays.equals(indices, that.indices) && Objects.equals(indicesOptions, that.indicesOptions);
131+
}
132+
133+
@Override
134+
public int hashCode() {
135+
int result = Objects.hash(block, indicesOptions);
136+
result = 31 * result + Arrays.hashCode(indices);
137+
return result;
138+
}
139+
140+
}
Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the "Elastic License
4+
* 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
5+
* Public License v 1"; you may not use this file except in compliance with, at
6+
* your election, the "Elastic License 2.0", the "GNU Affero General Public
7+
* License v3.0 only", or the "Server Side Public License, v 1".
8+
*/
9+
package org.elasticsearch.action.admin.indices.readonly;
10+
11+
import org.elasticsearch.ElasticsearchException;
12+
import org.elasticsearch.action.support.master.AcknowledgedResponse;
13+
import org.elasticsearch.common.Strings;
14+
import org.elasticsearch.common.io.stream.StreamInput;
15+
import org.elasticsearch.common.io.stream.StreamOutput;
16+
import org.elasticsearch.common.io.stream.Writeable;
17+
import org.elasticsearch.core.Nullable;
18+
import org.elasticsearch.index.Index;
19+
import org.elasticsearch.xcontent.ToXContentObject;
20+
import org.elasticsearch.xcontent.XContentBuilder;
21+
22+
import java.io.IOException;
23+
import java.util.List;
24+
import java.util.Objects;
25+
26+
/**
27+
* A response for a remove index block action.
28+
*/
29+
public class RemoveIndexBlockResponse extends AcknowledgedResponse {
30+
31+
public static final RemoveIndexBlockResponse EMPTY = new RemoveIndexBlockResponse(true, List.of());
32+
33+
private final List<RemoveBlockResult> indices;
34+
35+
public RemoveIndexBlockResponse(StreamInput in) throws IOException {
36+
super(in);
37+
indices = in.readCollectionAsList(RemoveBlockResult::new);
38+
}
39+
40+
public RemoveIndexBlockResponse(boolean acknowledged, List<RemoveBlockResult> indices) {
41+
super(acknowledged);
42+
this.indices = List.copyOf(Objects.requireNonNull(indices, "indices must not be null"));
43+
}
44+
45+
/**
46+
* Returns the list of {@link RemoveBlockResult}.
47+
*/
48+
public List<RemoveBlockResult> getIndices() {
49+
return indices;
50+
}
51+
52+
@Override
53+
public void writeTo(StreamOutput out) throws IOException {
54+
super.writeTo(out);
55+
out.writeCollection(indices);
56+
}
57+
58+
@Override
59+
protected void addCustomFields(XContentBuilder builder, Params params) throws IOException {
60+
builder.startArray("indices");
61+
for (RemoveBlockResult index : indices) {
62+
index.toXContent(builder, params);
63+
}
64+
builder.endArray();
65+
}
66+
67+
@Override
68+
public boolean equals(Object o) {
69+
if (super.equals(o)) {
70+
RemoveIndexBlockResponse that = (RemoveIndexBlockResponse) o;
71+
return Objects.equals(indices, that.indices);
72+
}
73+
return false;
74+
}
75+
76+
@Override
77+
public int hashCode() {
78+
return Objects.hash(super.hashCode(), indices);
79+
}
80+
81+
@Override
82+
public String toString() {
83+
return "RemoveIndexBlockResponse{" + "acknowledged=" + isAcknowledged() + ", indices=" + indices + '}';
84+
}
85+
86+
public static class RemoveBlockResult implements Writeable, ToXContentObject {
87+
88+
private final Index index;
89+
private final @Nullable Exception exception;
90+
91+
public RemoveBlockResult(final Index index) {
92+
this.index = Objects.requireNonNull(index);
93+
this.exception = null;
94+
}
95+
96+
public RemoveBlockResult(final Index index, final Exception failure) {
97+
this.index = Objects.requireNonNull(index);
98+
this.exception = Objects.requireNonNull(failure);
99+
}
100+
101+
RemoveBlockResult(final StreamInput in) throws IOException {
102+
this.index = new Index(in);
103+
this.exception = in.readException();
104+
}
105+
106+
@Override
107+
public void writeTo(final StreamOutput out) throws IOException {
108+
index.writeTo(out);
109+
out.writeException(exception);
110+
}
111+
112+
public Index getIndex() {
113+
return index;
114+
}
115+
116+
public Exception getException() {
117+
return exception;
118+
}
119+
120+
public boolean hasFailures() {
121+
return exception != null;
122+
}
123+
124+
@Override
125+
public XContentBuilder toXContent(final XContentBuilder builder, final Params params) throws IOException {
126+
builder.startObject();
127+
{
128+
builder.field("name", index.getName());
129+
if (hasFailures()) {
130+
builder.startObject("exception");
131+
ElasticsearchException.generateFailureXContent(builder, params, exception, true);
132+
builder.endObject();
133+
} else {
134+
builder.field("unblocked", true);
135+
}
136+
}
137+
return builder.endObject();
138+
}
139+
140+
@Override
141+
public String toString() {
142+
return Strings.toString(this);
143+
}
144+
}
145+
146+
}

0 commit comments

Comments
 (0)