Skip to content

Commit 3b9c820

Browse files
authored
Add GET Repository High Level REST API (#30362)
This commit adds the Snapshot Client with a first API call within it, the get repositories call in snapshot/restore module. This also creates a snapshot namespace for the docs, as well as get repositories docs. Relates #27205
1 parent ad56424 commit 3b9c820

File tree

9 files changed

+435
-0
lines changed

9 files changed

+435
-0
lines changed

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

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import org.apache.http.entity.ContentType;
3030
import org.apache.lucene.util.BytesRef;
3131
import org.elasticsearch.action.DocWriteRequest;
32+
import org.elasticsearch.action.admin.cluster.repositories.get.GetRepositoriesRequest;
3233
import org.elasticsearch.action.admin.cluster.settings.ClusterUpdateSettingsRequest;
3334
import org.elasticsearch.action.admin.indices.alias.IndicesAliasesRequest;
3435
import org.elasticsearch.action.admin.indices.alias.get.GetAliasesRequest;
@@ -644,6 +645,17 @@ static Request indexPutSettings(UpdateSettingsRequest updateSettingsRequest) thr
644645
return request;
645646
}
646647

648+
static Request getRepositories(GetRepositoriesRequest getRepositoriesRequest) {
649+
String[] repositories = getRepositoriesRequest.repositories() == null ? Strings.EMPTY_ARRAY : getRepositoriesRequest.repositories();
650+
String endpoint = new EndpointBuilder().addPathPartAsIs("_snapshot").addCommaSeparatedPathParts(repositories).build();
651+
Request request = new Request(HttpGet.METHOD_NAME, endpoint);
652+
653+
Params parameters = new Params(request);
654+
parameters.withMasterTimeout(getRepositoriesRequest.masterNodeTimeout());
655+
parameters.withLocal(getRepositoriesRequest.local());
656+
return request;
657+
}
658+
647659
static Request putTemplate(PutIndexTemplateRequest putIndexTemplateRequest) throws IOException {
648660
String endpoint = new EndpointBuilder().addPathPartAsIs("_template").addPathPart(putIndexTemplateRequest.name()).build();
649661
Request request = new Request(HttpPut.METHOD_NAME, endpoint);

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

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@
2626
import org.elasticsearch.action.ActionListener;
2727
import org.elasticsearch.action.ActionRequest;
2828
import org.elasticsearch.action.ActionRequestValidationException;
29+
import org.elasticsearch.action.admin.cluster.repositories.get.GetRepositoriesRequest;
30+
import org.elasticsearch.action.admin.cluster.repositories.get.GetRepositoriesResponse;
2931
import org.elasticsearch.action.bulk.BulkRequest;
3032
import org.elasticsearch.action.bulk.BulkResponse;
3133
import org.elasticsearch.action.delete.DeleteRequest;
@@ -189,6 +191,7 @@ public class RestHighLevelClient implements Closeable {
189191

190192
private final IndicesClient indicesClient = new IndicesClient(this);
191193
private final ClusterClient clusterClient = new ClusterClient(this);
194+
private final SnapshotClient snapshotClient = new SnapshotClient(this);
192195

193196
/**
194197
* Creates a {@link RestHighLevelClient} given the low level {@link RestClientBuilder} that allows to build the
@@ -252,6 +255,15 @@ public final ClusterClient cluster() {
252255
return clusterClient;
253256
}
254257

258+
/**
259+
* Provides a {@link SnapshotClient} which can be used to access the Snapshot API.
260+
*
261+
* See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/modules-snapshots.html">Snapshot API on elastic.co</a>
262+
*/
263+
public final SnapshotClient snapshot() {
264+
return snapshotClient;
265+
}
266+
255267
/**
256268
* Executes a bulk request using the Bulk API
257269
*
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
/*
2+
* Licensed to Elasticsearch under one or more contributor
3+
* license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright
5+
* ownership. Elasticsearch licenses this file to you under
6+
* the Apache License, Version 2.0 (the "License"); you may
7+
* not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
package org.elasticsearch.client;
21+
22+
import org.apache.http.Header;
23+
import org.elasticsearch.action.ActionListener;
24+
import org.elasticsearch.action.admin.cluster.repositories.get.GetRepositoriesRequest;
25+
import org.elasticsearch.action.admin.cluster.repositories.get.GetRepositoriesResponse;
26+
import org.elasticsearch.action.admin.cluster.settings.ClusterUpdateSettingsRequest;
27+
import org.elasticsearch.action.admin.cluster.settings.ClusterUpdateSettingsResponse;
28+
29+
import java.io.IOException;
30+
31+
import static java.util.Collections.emptySet;
32+
33+
/**
34+
* A wrapper for the {@link RestHighLevelClient} that provides methods for accessing the Snapshot API.
35+
* <p>
36+
* See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/modules-snapshots.html">Snapshot API on elastic.co</a>
37+
*/
38+
public final class SnapshotClient {
39+
private final RestHighLevelClient restHighLevelClient;
40+
41+
SnapshotClient(RestHighLevelClient restHighLevelClient) {
42+
this.restHighLevelClient = restHighLevelClient;
43+
}
44+
45+
/**
46+
* Gets a list of snapshot repositories. If the list of repositories is empty or it contains a single element "_all", all
47+
* registered repositories are returned.
48+
* <p>
49+
* See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/modules-snapshots.html"> Snapshot and Restore
50+
* API on elastic.co</a>
51+
*/
52+
public GetRepositoriesResponse getRepositories(GetRepositoriesRequest getRepositoriesRequest, Header... headers)
53+
throws IOException {
54+
return restHighLevelClient.performRequestAndParseEntity(getRepositoriesRequest, RequestConverters::getRepositories,
55+
GetRepositoriesResponse::fromXContent, emptySet(), headers);
56+
}
57+
58+
/**
59+
* Asynchronously gets a list of snapshot repositories. If the list of repositories is empty or it contains a single element "_all", all
60+
* registered repositories are returned.
61+
* <p>
62+
* See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/modules-snapshots.html"> Snapshot and Restore
63+
* API on elastic.co</a>
64+
*/
65+
public void getRepositoriesAsync(GetRepositoriesRequest getRepositoriesRequest,
66+
ActionListener<GetRepositoriesResponse> listener, Header... headers) {
67+
restHighLevelClient.performRequestAsyncAndParseEntity(getRepositoriesRequest, RequestConverters::getRepositories,
68+
GetRepositoriesResponse::fromXContent, listener, emptySet(), headers);
69+
}
70+
}

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

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import org.apache.http.util.EntityUtils;
3030
import org.elasticsearch.action.ActionRequestValidationException;
3131
import org.elasticsearch.action.DocWriteRequest;
32+
import org.elasticsearch.action.admin.cluster.repositories.get.GetRepositoriesRequest;
3233
import org.elasticsearch.action.admin.cluster.settings.ClusterUpdateSettingsRequest;
3334
import org.elasticsearch.action.admin.indices.alias.Alias;
3435
import org.elasticsearch.action.admin.indices.alias.IndicesAliasesRequest;
@@ -1427,6 +1428,26 @@ public void testIndexPutSettings() throws IOException {
14271428
assertEquals(expectedParams, request.getParameters());
14281429
}
14291430

1431+
public void testGetRepositories() {
1432+
Map<String, String> expectedParams = new HashMap<>();
1433+
StringBuilder endpoint = new StringBuilder("/_snapshot");
1434+
1435+
GetRepositoriesRequest getRepositoriesRequest = new GetRepositoriesRequest();
1436+
setRandomMasterTimeout(getRepositoriesRequest, expectedParams);
1437+
setRandomLocal(getRepositoriesRequest, expectedParams);
1438+
1439+
if (randomBoolean()) {
1440+
String[] entries = new String[] {"a", "b", "c"};
1441+
getRepositoriesRequest.repositories(entries);
1442+
endpoint.append("/" + String.join(",", entries));
1443+
}
1444+
1445+
Request request = RequestConverters.getRepositories(getRepositoriesRequest);
1446+
assertThat(endpoint.toString(), equalTo(request.getEndpoint()));
1447+
assertThat(HttpGet.METHOD_NAME, equalTo(request.getMethod()));
1448+
assertThat(expectedParams, equalTo(request.getParameters()));
1449+
}
1450+
14301451
public void testPutTemplateRequest() throws Exception {
14311452
Map<String, String> names = new HashMap<>();
14321453
names.put("log", "log");
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
/*
2+
* Licensed to Elasticsearch under one or more contributor
3+
* license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright
5+
* ownership. Elasticsearch licenses this file to you under
6+
* the Apache License, Version 2.0 (the "License"); you may
7+
* not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
package org.elasticsearch.client;
21+
22+
import org.apache.http.entity.ContentType;
23+
import org.apache.http.entity.StringEntity;
24+
import org.elasticsearch.ElasticsearchException;
25+
import org.elasticsearch.action.admin.cluster.repositories.get.GetRepositoriesRequest;
26+
import org.elasticsearch.action.admin.cluster.repositories.get.GetRepositoriesResponse;
27+
import org.elasticsearch.rest.RestStatus;
28+
29+
import java.io.IOException;
30+
import java.util.Collections;
31+
32+
import static org.hamcrest.Matchers.equalTo;
33+
34+
public class SnapshotIT extends ESRestHighLevelClientTestCase {
35+
36+
public void testModulesGetRepositoriesUsingParams() throws IOException {
37+
String repository = "test";
38+
String repositorySettings = "{\"type\":\"fs\", \"settings\":{\"location\": \".\"}}";
39+
highLevelClient().getLowLevelClient().performRequest("put", "_snapshot/" + repository, Collections.emptyMap(),
40+
new StringEntity(repositorySettings, ContentType.APPLICATION_JSON));
41+
42+
highLevelClient().getLowLevelClient().performRequest("put", "_snapshot/" + repository + "_other", Collections.emptyMap(),
43+
new StringEntity(repositorySettings, ContentType.APPLICATION_JSON));
44+
45+
{
46+
GetRepositoriesRequest request = new GetRepositoriesRequest();
47+
request.repositories(new String[]{repository});
48+
GetRepositoriesResponse response = execute(request, highLevelClient().snapshot()::getRepositories,
49+
highLevelClient().snapshot()::getRepositoriesAsync);
50+
assertThat(1, equalTo(response.repositories().size()));
51+
}
52+
{
53+
GetRepositoriesRequest request = new GetRepositoriesRequest();
54+
GetRepositoriesResponse response = execute(request, highLevelClient().snapshot()::getRepositories,
55+
highLevelClient().snapshot()::getRepositoriesAsync);
56+
assertThat(2, equalTo(response.repositories().size()));
57+
}
58+
}
59+
60+
public void testModulesGetDefaultRepositories() throws IOException {
61+
String repositorySettings = "{\"type\":\"fs\", \"settings\":{\"location\": \".\"}}";
62+
GetRepositoriesRequest request = new GetRepositoriesRequest();
63+
64+
highLevelClient().getLowLevelClient().performRequest("put", "_snapshot/test", Collections.emptyMap(),
65+
new StringEntity(repositorySettings, ContentType.APPLICATION_JSON));
66+
67+
GetRepositoriesResponse response = execute(request, highLevelClient().snapshot()::getRepositories,
68+
highLevelClient().snapshot()::getRepositoriesAsync);
69+
assertThat(1, equalTo(response.repositories().size()));
70+
}
71+
72+
public void testModulesGetRepositoriesNonExistent() throws IOException {
73+
String repository = "doesnotexist";
74+
GetRepositoriesRequest request = new GetRepositoriesRequest(new String[]{repository});
75+
ElasticsearchException exception = expectThrows(ElasticsearchException.class, () -> execute(request,
76+
highLevelClient().snapshot()::getRepositories, highLevelClient().snapshot()::getRepositoriesAsync));
77+
78+
assertThat(exception.status(), equalTo(RestStatus.NOT_FOUND));
79+
assertThat(exception.getMessage(), equalTo(
80+
"Elasticsearch exception [type=repository_missing_exception, reason=[" + repository + "] missing]"));
81+
}
82+
}
Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
/*
2+
* Licensed to Elasticsearch under one or more contributor
3+
* license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright
5+
* ownership. Elasticsearch licenses this file to you under
6+
* the Apache License, Version 2.0 (the "License"); you may
7+
* not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
package org.elasticsearch.client.documentation;
21+
22+
import org.apache.http.entity.ContentType;
23+
import org.apache.http.entity.StringEntity;
24+
import org.elasticsearch.action.ActionListener;
25+
import org.elasticsearch.action.LatchedActionListener;
26+
import org.elasticsearch.action.admin.cluster.repositories.get.GetRepositoriesRequest;
27+
import org.elasticsearch.action.admin.cluster.repositories.get.GetRepositoriesResponse;
28+
import org.elasticsearch.client.ESRestHighLevelClientTestCase;
29+
import org.elasticsearch.client.RestHighLevelClient;
30+
import org.elasticsearch.cluster.metadata.RepositoryMetaData;
31+
import org.elasticsearch.common.unit.TimeValue;
32+
33+
import java.io.IOException;
34+
import java.util.Collections;
35+
import java.util.List;
36+
import java.util.concurrent.CountDownLatch;
37+
import java.util.concurrent.TimeUnit;
38+
39+
import static org.hamcrest.Matchers.equalTo;
40+
41+
/**
42+
* This class is used to generate the Java Cluster API documentation.
43+
* You need to wrap your code between two tags like:
44+
* // tag::example
45+
* // end::example
46+
*
47+
* Where example is your tag name.
48+
*
49+
* Then in the documentation, you can extract what is between tag and end tags with
50+
* ["source","java",subs="attributes,callouts,macros"]
51+
* --------------------------------------------------
52+
* include-tagged::{doc-tests}/SnapshotClientDocumentationIT.java[example]
53+
* --------------------------------------------------
54+
*
55+
* The column width of the code block is 84. If the code contains a line longer
56+
* than 84, the line will be cut and a horizontal scroll bar will be displayed.
57+
* (the code indentation of the tag is not included in the width)
58+
*/
59+
public class SnapshotClientDocumentationIT extends ESRestHighLevelClientTestCase {
60+
61+
private static final String testRepository = "test_repository";
62+
63+
public void testSnapshotGetRepository() throws IOException {
64+
RestHighLevelClient client = highLevelClient();
65+
66+
createTestRepositories();
67+
68+
// tag::get-repository-request
69+
GetRepositoriesRequest request = new GetRepositoriesRequest();
70+
// end::get-repository-request
71+
72+
// tag::get-repository-request-repositories
73+
String [] repositories = new String[] { testRepository };
74+
request.repositories(repositories); // <1>
75+
// end::get-repository-request-repositories
76+
// tag::get-repository-request-local
77+
request.local(true); // <1>
78+
// end::get-repository-request-local
79+
// tag::get-repository-request-masterTimeout
80+
request.masterNodeTimeout(TimeValue.timeValueMinutes(1)); // <1>
81+
request.masterNodeTimeout("1m"); // <2>
82+
// end::get-repository-request-masterTimeout
83+
84+
// tag::get-repository-execute
85+
GetRepositoriesResponse response = client.snapshot().getRepositories(request);
86+
// end::get-repository-execute
87+
88+
// tag::get-repository-response
89+
List<RepositoryMetaData> repositoryMetaDataResponse = response.repositories();
90+
// end::get-repository-response
91+
assertThat(1, equalTo(repositoryMetaDataResponse.size()));
92+
assertThat(testRepository, equalTo(repositoryMetaDataResponse.get(0).name()));
93+
}
94+
95+
public void testSnapshotGetRepositoryAsync() throws InterruptedException {
96+
RestHighLevelClient client = highLevelClient();
97+
{
98+
GetRepositoriesRequest request = new GetRepositoriesRequest();
99+
100+
// tag::get-repository-execute-listener
101+
ActionListener<GetRepositoriesResponse> listener =
102+
new ActionListener<GetRepositoriesResponse>() {
103+
@Override
104+
public void onResponse(GetRepositoriesResponse getRepositoriesResponse) {
105+
// <1>
106+
}
107+
108+
@Override
109+
public void onFailure(Exception e) {
110+
// <2>
111+
}
112+
};
113+
// end::get-repository-execute-listener
114+
115+
// Replace the empty listener by a blocking listener in test
116+
final CountDownLatch latch = new CountDownLatch(1);
117+
listener = new LatchedActionListener<>(listener, latch);
118+
119+
// tag::get-repository-execute-async
120+
client.snapshot().getRepositoriesAsync(request, listener); // <1>
121+
// end::get-repository-execute-async
122+
123+
assertTrue(latch.await(30L, TimeUnit.SECONDS));
124+
}
125+
126+
}
127+
128+
private void createTestRepositories() throws IOException {
129+
RestHighLevelClient client = highLevelClient();
130+
String repositorySettings = "{\"type\":\"fs\", \"settings\":{\"location\": \".\"}}";
131+
highLevelClient().getLowLevelClient().performRequest("put", "_snapshot/" + testRepository, Collections.emptyMap(),
132+
new StringEntity(repositorySettings, ContentType.APPLICATION_JSON));
133+
134+
}
135+
}

0 commit comments

Comments
 (0)