Skip to content

Commit fc699c6

Browse files
committed
Clean Up Snapshot Create Rest API (#31779)
Make SnapshotInfo and CreateSnapshotResponse parsers lenient for backwards compatibility. Remove extraneous fields from CreateSnapshotRequest toXContent.
1 parent 6e1b187 commit fc699c6

File tree

11 files changed

+56
-93
lines changed

11 files changed

+56
-93
lines changed

client/rest-high-level/src/main/java/org/elasticsearch/client/SnapshotClient.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@ public void verifyRepositoryAsync(VerifyRepositoryRequest verifyRepositoryReques
174174
* See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/modules-snapshots.html"> Snapshot and Restore
175175
* API on elastic.co</a>
176176
*/
177-
public CreateSnapshotResponse createSnapshot(CreateSnapshotRequest createSnapshotRequest, RequestOptions options)
177+
public CreateSnapshotResponse create(CreateSnapshotRequest createSnapshotRequest, RequestOptions options)
178178
throws IOException {
179179
return restHighLevelClient.performRequestAndParseEntity(createSnapshotRequest, RequestConverters::createSnapshot, options,
180180
CreateSnapshotResponse::fromXContent, emptySet());
@@ -186,7 +186,7 @@ public CreateSnapshotResponse createSnapshot(CreateSnapshotRequest createSnapsho
186186
* See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/modules-snapshots.html"> Snapshot and Restore
187187
* API on elastic.co</a>
188188
*/
189-
public void createSnapshotAsync(CreateSnapshotRequest createSnapshotRequest, RequestOptions options,
189+
public void createAsync(CreateSnapshotRequest createSnapshotRequest, RequestOptions options,
190190
ActionListener<CreateSnapshotResponse> listener) {
191191
restHighLevelClient.performRequestAsyncAndParseEntity(createSnapshotRequest, RequestConverters::createSnapshot, options,
192192
CreateSnapshotResponse::fromXContent, listener, emptySet());

client/rest-high-level/src/test/java/org/elasticsearch/client/SnapshotIT.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,8 @@ private PutRepositoryResponse createTestRepository(String repository, String typ
5757
private CreateSnapshotResponse createTestSnapshot(CreateSnapshotRequest createSnapshotRequest) throws IOException {
5858
// assumes the repository already exists
5959

60-
return execute(createSnapshotRequest, highLevelClient().snapshot()::createSnapshot,
61-
highLevelClient().snapshot()::createSnapshotAsync);
60+
return execute(createSnapshotRequest, highLevelClient().snapshot()::create,
61+
highLevelClient().snapshot()::createAsync);
6262
}
6363

6464
public void testCreateRepository() throws IOException {

client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/SnapshotClientDocumentationIT.java

+8-2
Original file line numberDiff line numberDiff line change
@@ -420,14 +420,20 @@ public void testSnapshotCreate() throws IOException {
420420
// end::create-snapshot-request-waitForCompletion
421421

422422
// tag::create-snapshot-execute
423-
CreateSnapshotResponse response = client.snapshot().createSnapshot(request, RequestOptions.DEFAULT);
423+
CreateSnapshotResponse response = client.snapshot().create(request, RequestOptions.DEFAULT);
424424
// end::create-snapshot-execute
425425

426426
// tag::create-snapshot-response
427427
RestStatus status = response.status(); // <1>
428428
// end::create-snapshot-response
429429

430430
assertEquals(RestStatus.OK, status);
431+
432+
// tag::create-snapshot-response-snapshot-info
433+
SnapshotInfo snapshotInfo = response.getSnapshotInfo(); // <1>
434+
// end::create-snapshot-response-snapshot-info
435+
436+
assertNotNull(snapshotInfo);
431437
}
432438

433439
public void testSnapshotCreateAsync() throws InterruptedException {
@@ -455,7 +461,7 @@ public void onFailure(Exception exception) {
455461
listener = new LatchedActionListener<>(listener, latch);
456462

457463
// tag::create-snapshot-execute-async
458-
client.snapshot().createSnapshotAsync(request, RequestOptions.DEFAULT, listener); // <1>
464+
client.snapshot().createAsync(request, RequestOptions.DEFAULT, listener); // <1>
459465
// end::create-snapshot-execute-async
460466

461467
assertTrue(latch.await(30L, TimeUnit.SECONDS));

docs/java-rest/high-level/snapshot/create_snapshot.asciidoc

+11
Original file line numberDiff line numberDiff line change
@@ -73,11 +73,22 @@ include-tagged::{doc-tests}/SnapshotClientDocumentationIT.java[create-snapshot-r
7373
[[java-rest-high-snapshot-create-snapshot-sync]]
7474
==== Synchronous Execution
7575

76+
Execute a `CreateSnapshotRequest` synchronously to receive a `CreateSnapshotResponse`.
77+
7678
["source","java",subs="attributes,callouts,macros"]
7779
--------------------------------------------------
7880
include-tagged::{doc-tests}/SnapshotClientDocumentationIT.java[create-snapshot-execute]
7981
--------------------------------------------------
8082

83+
Retrieve the `SnapshotInfo` from a `CreateSnapshotResponse` when the snapshot is fully created.
84+
(The `waitForCompletion` parameter is `true`).
85+
86+
["source","java",subs="attributes,callouts,macros"]
87+
--------------------------------------------------
88+
include-tagged::{doc-tests}/SnapshotClientDocumentationIT.java[create-snapshot-response-snapshot-info]
89+
--------------------------------------------------
90+
<1> The `SnapshotInfo` object.
91+
8192
[[java-rest-high-snapshot-create-snapshot-async]]
8293
==== Asynchronous Execution
8394

server/src/main/java/org/elasticsearch/action/admin/cluster/snapshots/create/CreateSnapshotRequest.java

+1-3
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,9 @@
4242

4343
import static org.elasticsearch.action.ValidateActions.addValidationError;
4444
import static org.elasticsearch.common.Strings.EMPTY_ARRAY;
45+
import static org.elasticsearch.common.settings.Settings.Builder.EMPTY_SETTINGS;
4546
import static org.elasticsearch.common.settings.Settings.readSettingsFromStream;
4647
import static org.elasticsearch.common.settings.Settings.writeSettingsToStream;
47-
import static org.elasticsearch.common.settings.Settings.Builder.EMPTY_SETTINGS;
4848
import static org.elasticsearch.common.xcontent.support.XContentMapValues.nodeBooleanValue;
4949

5050
/**
@@ -408,8 +408,6 @@ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws
408408
if (indicesOptions != null) {
409409
indicesOptions.toXContent(builder, params);
410410
}
411-
builder.field("wait_for_completion", waitForCompletion);
412-
builder.field("master_node_timeout", masterNodeTimeout.toString());
413411
builder.endObject();
414412
return builder;
415413
}

server/src/main/java/org/elasticsearch/action/admin/cluster/snapshots/create/CreateSnapshotResponse.java

+15-35
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,16 @@
2121

2222
import org.elasticsearch.action.ActionResponse;
2323
import org.elasticsearch.common.Nullable;
24+
import org.elasticsearch.common.ParseField;
2425
import org.elasticsearch.common.io.stream.StreamInput;
2526
import org.elasticsearch.common.io.stream.StreamOutput;
27+
import org.elasticsearch.common.xcontent.ObjectParser;
2628
import org.elasticsearch.common.xcontent.ToXContentObject;
2729
import org.elasticsearch.common.xcontent.XContentBuilder;
2830
import org.elasticsearch.common.xcontent.XContentParser;
29-
import org.elasticsearch.common.xcontent.XContentParser.Token;
3031
import org.elasticsearch.rest.RestStatus;
3132
import org.elasticsearch.snapshots.SnapshotInfo;
33+
import org.elasticsearch.snapshots.SnapshotInfo.SnapshotInfoBuilder;
3234

3335
import java.io.IOException;
3436
import java.util.Objects;
@@ -38,6 +40,14 @@
3840
*/
3941
public class CreateSnapshotResponse extends ActionResponse implements ToXContentObject {
4042

43+
private static final ObjectParser<CreateSnapshotResponse, Void> PARSER =
44+
new ObjectParser<>(CreateSnapshotResponse.class.getName(), true, CreateSnapshotResponse::new);
45+
46+
static {
47+
PARSER.declareObject(CreateSnapshotResponse::setSnapshotInfoFromBuilder,
48+
SnapshotInfo.SNAPSHOT_INFO_PARSER, new ParseField("snapshot"));
49+
}
50+
4151
@Nullable
4252
private SnapshotInfo snapshotInfo;
4353

@@ -48,8 +58,8 @@ public class CreateSnapshotResponse extends ActionResponse implements ToXContent
4858
CreateSnapshotResponse() {
4959
}
5060

51-
void setSnapshotInfo(SnapshotInfo snapshotInfo) {
52-
this.snapshotInfo = snapshotInfo;
61+
private void setSnapshotInfoFromBuilder(SnapshotInfoBuilder snapshotInfoBuilder) {
62+
this.snapshotInfo = snapshotInfoBuilder.build();
5363
}
5464

5565
/**
@@ -101,38 +111,8 @@ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws
101111
return builder;
102112
}
103113

104-
public static CreateSnapshotResponse fromXContent(XContentParser parser) throws IOException {
105-
CreateSnapshotResponse createSnapshotResponse = new CreateSnapshotResponse();
106-
107-
parser.nextToken(); // move to '{'
108-
109-
if (parser.currentToken() != Token.START_OBJECT) {
110-
throw new IllegalArgumentException("unexpected token [" + parser.currentToken() + "], expected ['{']");
111-
}
112-
113-
parser.nextToken(); // move to 'snapshot' || 'accepted'
114-
115-
if ("snapshot".equals(parser.currentName())) {
116-
createSnapshotResponse.snapshotInfo = SnapshotInfo.fromXContent(parser);
117-
} else if ("accepted".equals(parser.currentName())) {
118-
parser.nextToken(); // move to 'accepted' field value
119-
120-
if (parser.booleanValue()) {
121-
// ensure accepted is a boolean value
122-
}
123-
124-
parser.nextToken(); // move past 'true'/'false'
125-
} else {
126-
throw new IllegalArgumentException("unexpected token [" + parser.currentToken() + "] expected ['snapshot', 'accepted']");
127-
}
128-
129-
if (parser.currentToken() != Token.END_OBJECT) {
130-
throw new IllegalArgumentException("unexpected token [" + parser.currentToken() + "], expected ['}']");
131-
}
132-
133-
parser.nextToken(); // move past '}'
134-
135-
return createSnapshotResponse;
114+
public static CreateSnapshotResponse fromXContent(XContentParser parser) {
115+
return PARSER.apply(parser, null);
136116
}
137117

138118
@Override

server/src/main/java/org/elasticsearch/action/support/IndicesOptions.java

+13-15
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import org.elasticsearch.Version;
2323
import org.elasticsearch.common.io.stream.StreamInput;
2424
import org.elasticsearch.common.io.stream.StreamOutput;
25+
import org.elasticsearch.common.xcontent.ToXContent;
2526
import org.elasticsearch.common.xcontent.ToXContentFragment;
2627
import org.elasticsearch.common.xcontent.XContentBuilder;
2728
import org.elasticsearch.rest.RestRequest;
@@ -322,21 +323,6 @@ public static IndicesOptions fromMap(Map<String, Object> map, IndicesOptions def
322323
defaultSettings);
323324
}
324325

325-
@Override
326-
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
327-
builder.startArray("expand_wildcards");
328-
for (WildcardStates expandWildcard : expandWildcards) {
329-
builder.value(expandWildcard.toString().toLowerCase(Locale.ROOT));
330-
}
331-
builder.endArray();
332-
builder.field("ignore_unavailable", ignoreUnavailable());
333-
builder.field("allow_no_indices", allowNoIndices());
334-
builder.field("forbid_aliases_to_multiple_indices", allowAliasesToMultipleIndices() == false);
335-
builder.field("forbid_closed_indices", forbidClosedIndices());
336-
builder.field("ignore_aliases", ignoreAliases());
337-
return builder;
338-
}
339-
340326
/**
341327
* Returns true if the name represents a valid name for one of the indices option
342328
* false otherwise
@@ -366,6 +352,18 @@ public static IndicesOptions fromParameters(Object wildcardsString, Object ignor
366352
);
367353
}
368354

355+
@Override
356+
public XContentBuilder toXContent(XContentBuilder builder, ToXContent.Params params) throws IOException {
357+
builder.startArray("expand_wildcards");
358+
for (WildcardStates expandWildcard : expandWildcards) {
359+
builder.value(expandWildcard.toString().toLowerCase(Locale.ROOT));
360+
}
361+
builder.endArray();
362+
builder.field("ignore_unavailable", ignoreUnavailable());
363+
builder.field("allow_no_indices", allowNoIndices());
364+
return builder;
365+
}
366+
369367
/**
370368
* @return indices options that requires every specified index to exist, expands wildcards only to open indices and
371369
* allows that no indices are resolved from wildcard expressions (not returning an error).

server/src/main/java/org/elasticsearch/snapshots/SnapshotInfo.java

-25
Original file line numberDiff line numberDiff line change
@@ -138,22 +138,6 @@ private void setShardFailures(List<SnapshotShardFailure> shardFailures) {
138138
this.shardFailures = shardFailures;
139139
}
140140

141-
private void ignoreVersion(String version) {
142-
// ignore extra field
143-
}
144-
145-
private void ignoreStartTime(String startTime) {
146-
// ignore extra field
147-
}
148-
149-
private void ignoreEndTime(String endTime) {
150-
// ignore extra field
151-
}
152-
153-
private void ignoreDurationInMillis(long durationInMillis) {
154-
// ignore extra field
155-
}
156-
157141
public SnapshotInfo build() {
158142
SnapshotId snapshotId = new SnapshotId(snapshotName, snapshotUUID);
159143

@@ -195,10 +179,6 @@ private void setSuccessfulShards(int successfulShards) {
195179
int getSuccessfulShards() {
196180
return successfulShards;
197181
}
198-
199-
private void ignoreFailedShards(int failedShards) {
200-
// ignore extra field
201-
}
202182
}
203183

204184
public static final ObjectParser<SnapshotInfoBuilder, Void> SNAPSHOT_INFO_PARSER =
@@ -220,14 +200,9 @@ private void ignoreFailedShards(int failedShards) {
220200
SNAPSHOT_INFO_PARSER.declareInt(SnapshotInfoBuilder::setVersion, new ParseField(VERSION_ID));
221201
SNAPSHOT_INFO_PARSER.declareObjectArray(SnapshotInfoBuilder::setShardFailures, SnapshotShardFailure.SNAPSHOT_SHARD_FAILURE_PARSER,
222202
new ParseField(FAILURES));
223-
SNAPSHOT_INFO_PARSER.declareString(SnapshotInfoBuilder::ignoreVersion, new ParseField(VERSION));
224-
SNAPSHOT_INFO_PARSER.declareString(SnapshotInfoBuilder::ignoreStartTime, new ParseField(START_TIME));
225-
SNAPSHOT_INFO_PARSER.declareString(SnapshotInfoBuilder::ignoreEndTime, new ParseField(END_TIME));
226-
SNAPSHOT_INFO_PARSER.declareLong(SnapshotInfoBuilder::ignoreDurationInMillis, new ParseField(DURATION_IN_MILLIS));
227203

228204
SHARD_STATS_PARSER.declareInt(ShardStatsBuilder::setTotalShards, new ParseField(TOTAL));
229205
SHARD_STATS_PARSER.declareInt(ShardStatsBuilder::setSuccessfulShards, new ParseField(SUCCESSFUL));
230-
SHARD_STATS_PARSER.declareInt(ShardStatsBuilder::ignoreFailedShards, new ParseField(FAILED));
231206
}
232207

233208
private final SnapshotId snapshotId;

server/src/test/java/org/elasticsearch/action/admin/cluster/snapshots/create/CreateSnapshotRequestTests.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -102,8 +102,8 @@ public void testToXContent() throws IOException {
102102
NamedXContentRegistry.EMPTY, null, BytesReference.bytes(builder).streamInput());
103103
Map<String, Object> map = parser.mapOrdered();
104104
CreateSnapshotRequest processed = new CreateSnapshotRequest((String)map.get("repository"), (String)map.get("snapshot"));
105-
processed.waitForCompletion((boolean)map.getOrDefault("wait_for_completion", false));
106-
processed.masterNodeTimeout((String)map.getOrDefault("master_node_timeout", "30s"));
105+
processed.waitForCompletion(original.waitForCompletion());
106+
processed.masterNodeTimeout(original.masterNodeTimeout());
107107
processed.source(map);
108108

109109
assertEquals(original, processed);

server/src/test/java/org/elasticsearch/action/admin/cluster/snapshots/create/CreateSnapshotResponseTests.java

+2-4
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ protected CreateSnapshotResponse doParseInstance(XContentParser parser) throws I
4040

4141
@Override
4242
protected boolean supportsUnknownFields() {
43-
return false;
43+
return true;
4444
}
4545

4646
@Override
@@ -63,9 +63,7 @@ protected CreateSnapshotResponse createTestInstance() {
6363

6464
boolean globalState = randomBoolean();
6565

66-
CreateSnapshotResponse response = new CreateSnapshotResponse();
67-
response.setSnapshotInfo(
66+
return new CreateSnapshotResponse(
6867
new SnapshotInfo(snapshotId, indices, startTime, reason, endTime, totalShards, shardFailures, globalState));
69-
return response;
7068
}
7169
}

server/src/test/java/org/elasticsearch/action/support/IndicesOptionsTests.java

-3
Original file line numberDiff line numberDiff line change
@@ -324,8 +324,5 @@ public void testToXContent() throws IOException {
324324
}
325325
assertEquals(map.get("ignore_unavailable"), options.contains(Option.IGNORE_UNAVAILABLE));
326326
assertEquals(map.get("allow_no_indices"), options.contains(Option.ALLOW_NO_INDICES));
327-
assertEquals(map.get("forbid_aliases_to_multiple_indices"), options.contains(Option.FORBID_ALIASES_TO_MULTIPLE_INDICES));
328-
assertEquals(map.get("forbid_closed_indices"), options.contains(Option.FORBID_CLOSED_INDICES));
329-
assertEquals(map.get("ignore_aliases"), options.contains(Option.IGNORE_ALIASES));
330327
}
331328
}

0 commit comments

Comments
 (0)