Skip to content

Commit

Permalink
Add GET Repository High Level REST API (#30362)
Browse files Browse the repository at this point in the history
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
  • Loading branch information
hub-cap committed May 9, 2018
1 parent 240a338 commit 83f8327
Show file tree
Hide file tree
Showing 9 changed files with 435 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import org.apache.http.entity.ContentType;
import org.apache.lucene.util.BytesRef;
import org.elasticsearch.action.DocWriteRequest;
import org.elasticsearch.action.admin.cluster.repositories.get.GetRepositoriesRequest;
import org.elasticsearch.action.admin.cluster.settings.ClusterUpdateSettingsRequest;
import org.elasticsearch.action.admin.indices.alias.IndicesAliasesRequest;
import org.elasticsearch.action.admin.indices.alias.get.GetAliasesRequest;
Expand Down Expand Up @@ -626,6 +627,17 @@ static Request indexPutSettings(UpdateSettingsRequest updateSettingsRequest) thr
return request;
}

static Request getRepositories(GetRepositoriesRequest getRepositoriesRequest) {
String[] repositories = getRepositoriesRequest.repositories() == null ? Strings.EMPTY_ARRAY : getRepositoriesRequest.repositories();
String endpoint = new EndpointBuilder().addPathPartAsIs("_snapshot").addCommaSeparatedPathParts(repositories).build();
Request request = new Request(HttpGet.METHOD_NAME, endpoint);

Params parameters = new Params(request);
parameters.withMasterTimeout(getRepositoriesRequest.masterNodeTimeout());
parameters.withLocal(getRepositoriesRequest.local());
return request;
}

static Request putTemplate(PutIndexTemplateRequest putIndexTemplateRequest) throws IOException {
String endpoint = new EndpointBuilder().addPathPartAsIs("_template").addPathPart(putIndexTemplateRequest.name()).build();
Request request = new Request(HttpPut.METHOD_NAME, endpoint);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@
import org.elasticsearch.action.ActionListener;
import org.elasticsearch.action.ActionRequest;
import org.elasticsearch.action.ActionRequestValidationException;
import org.elasticsearch.action.admin.cluster.repositories.get.GetRepositoriesRequest;
import org.elasticsearch.action.admin.cluster.repositories.get.GetRepositoriesResponse;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.delete.DeleteRequest;
Expand Down Expand Up @@ -187,6 +189,7 @@ public class RestHighLevelClient implements Closeable {

private final IndicesClient indicesClient = new IndicesClient(this);
private final ClusterClient clusterClient = new ClusterClient(this);
private final SnapshotClient snapshotClient = new SnapshotClient(this);

/**
* Creates a {@link RestHighLevelClient} given the low level {@link RestClientBuilder} that allows to build the
Expand Down Expand Up @@ -250,6 +253,15 @@ public final ClusterClient cluster() {
return clusterClient;
}

/**
* Provides a {@link SnapshotClient} which can be used to access the Snapshot API.
*
* See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/modules-snapshots.html">Snapshot API on elastic.co</a>
*/
public final SnapshotClient snapshot() {
return snapshotClient;
}

/**
* Executes a bulk request using the Bulk API
*
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/*
* Licensed to Elasticsearch under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

package org.elasticsearch.client;

import org.apache.http.Header;
import org.elasticsearch.action.ActionListener;
import org.elasticsearch.action.admin.cluster.repositories.get.GetRepositoriesRequest;
import org.elasticsearch.action.admin.cluster.repositories.get.GetRepositoriesResponse;
import org.elasticsearch.action.admin.cluster.settings.ClusterUpdateSettingsRequest;
import org.elasticsearch.action.admin.cluster.settings.ClusterUpdateSettingsResponse;

import java.io.IOException;

import static java.util.Collections.emptySet;

/**
* A wrapper for the {@link RestHighLevelClient} that provides methods for accessing the Snapshot API.
* <p>
* See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/modules-snapshots.html">Snapshot API on elastic.co</a>
*/
public final class SnapshotClient {
private final RestHighLevelClient restHighLevelClient;

SnapshotClient(RestHighLevelClient restHighLevelClient) {
this.restHighLevelClient = restHighLevelClient;
}

/**
* Gets a list of snapshot repositories. If the list of repositories is empty or it contains a single element "_all", all
* registered repositories are returned.
* <p>
* See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/modules-snapshots.html"> Snapshot and Restore
* API on elastic.co</a>
*/
public GetRepositoriesResponse getRepositories(GetRepositoriesRequest getRepositoriesRequest, Header... headers)
throws IOException {
return restHighLevelClient.performRequestAndParseEntity(getRepositoriesRequest, RequestConverters::getRepositories,
GetRepositoriesResponse::fromXContent, emptySet(), headers);
}

/**
* Asynchronously gets a list of snapshot repositories. If the list of repositories is empty or it contains a single element "_all", all
* registered repositories are returned.
* <p>
* See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/modules-snapshots.html"> Snapshot and Restore
* API on elastic.co</a>
*/
public void getRepositoriesAsync(GetRepositoriesRequest getRepositoriesRequest,
ActionListener<GetRepositoriesResponse> listener, Header... headers) {
restHighLevelClient.performRequestAsyncAndParseEntity(getRepositoriesRequest, RequestConverters::getRepositories,
GetRepositoriesResponse::fromXContent, listener, emptySet(), headers);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import org.apache.http.util.EntityUtils;
import org.elasticsearch.action.ActionRequestValidationException;
import org.elasticsearch.action.DocWriteRequest;
import org.elasticsearch.action.admin.cluster.repositories.get.GetRepositoriesRequest;
import org.elasticsearch.action.admin.cluster.settings.ClusterUpdateSettingsRequest;
import org.elasticsearch.action.admin.indices.alias.Alias;
import org.elasticsearch.action.admin.indices.alias.IndicesAliasesRequest;
Expand Down Expand Up @@ -1367,6 +1368,26 @@ public void testIndexPutSettings() throws IOException {
assertEquals(expectedParams, request.getParameters());
}

public void testGetRepositories() {
Map<String, String> expectedParams = new HashMap<>();
StringBuilder endpoint = new StringBuilder("/_snapshot");

GetRepositoriesRequest getRepositoriesRequest = new GetRepositoriesRequest();
setRandomMasterTimeout(getRepositoriesRequest, expectedParams);
setRandomLocal(getRepositoriesRequest, expectedParams);

if (randomBoolean()) {
String[] entries = new String[] {"a", "b", "c"};
getRepositoriesRequest.repositories(entries);
endpoint.append("/" + String.join(",", entries));
}

Request request = RequestConverters.getRepositories(getRepositoriesRequest);
assertThat(endpoint.toString(), equalTo(request.getEndpoint()));
assertThat(HttpGet.METHOD_NAME, equalTo(request.getMethod()));
assertThat(expectedParams, equalTo(request.getParameters()));
}

public void testPutTemplateRequest() throws Exception {
Map<String, String> names = new HashMap<>();
names.put("log", "log");
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
/*
* Licensed to Elasticsearch under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

package org.elasticsearch.client;

import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.elasticsearch.ElasticsearchException;
import org.elasticsearch.action.admin.cluster.repositories.get.GetRepositoriesRequest;
import org.elasticsearch.action.admin.cluster.repositories.get.GetRepositoriesResponse;
import org.elasticsearch.rest.RestStatus;

import java.io.IOException;
import java.util.Collections;

import static org.hamcrest.Matchers.equalTo;

public class SnapshotIT extends ESRestHighLevelClientTestCase {

public void testModulesGetRepositoriesUsingParams() throws IOException {
String repository = "test";
String repositorySettings = "{\"type\":\"fs\", \"settings\":{\"location\": \".\"}}";
highLevelClient().getLowLevelClient().performRequest("put", "_snapshot/" + repository, Collections.emptyMap(),
new StringEntity(repositorySettings, ContentType.APPLICATION_JSON));

highLevelClient().getLowLevelClient().performRequest("put", "_snapshot/" + repository + "_other", Collections.emptyMap(),
new StringEntity(repositorySettings, ContentType.APPLICATION_JSON));

{
GetRepositoriesRequest request = new GetRepositoriesRequest();
request.repositories(new String[]{repository});
GetRepositoriesResponse response = execute(request, highLevelClient().snapshot()::getRepositories,
highLevelClient().snapshot()::getRepositoriesAsync);
assertThat(1, equalTo(response.repositories().size()));
}
{
GetRepositoriesRequest request = new GetRepositoriesRequest();
GetRepositoriesResponse response = execute(request, highLevelClient().snapshot()::getRepositories,
highLevelClient().snapshot()::getRepositoriesAsync);
assertThat(2, equalTo(response.repositories().size()));
}
}

public void testModulesGetDefaultRepositories() throws IOException {
String repositorySettings = "{\"type\":\"fs\", \"settings\":{\"location\": \".\"}}";
GetRepositoriesRequest request = new GetRepositoriesRequest();

highLevelClient().getLowLevelClient().performRequest("put", "_snapshot/test", Collections.emptyMap(),
new StringEntity(repositorySettings, ContentType.APPLICATION_JSON));

GetRepositoriesResponse response = execute(request, highLevelClient().snapshot()::getRepositories,
highLevelClient().snapshot()::getRepositoriesAsync);
assertThat(1, equalTo(response.repositories().size()));
}

public void testModulesGetRepositoriesNonExistent() throws IOException {
String repository = "doesnotexist";
GetRepositoriesRequest request = new GetRepositoriesRequest(new String[]{repository});
ElasticsearchException exception = expectThrows(ElasticsearchException.class, () -> execute(request,
highLevelClient().snapshot()::getRepositories, highLevelClient().snapshot()::getRepositoriesAsync));

assertThat(exception.status(), equalTo(RestStatus.NOT_FOUND));
assertThat(exception.getMessage(), equalTo(
"Elasticsearch exception [type=repository_missing_exception, reason=[" + repository + "] missing]"));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
/*
* Licensed to Elasticsearch under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

package org.elasticsearch.client.documentation;

import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.elasticsearch.action.ActionListener;
import org.elasticsearch.action.LatchedActionListener;
import org.elasticsearch.action.admin.cluster.repositories.get.GetRepositoriesRequest;
import org.elasticsearch.action.admin.cluster.repositories.get.GetRepositoriesResponse;
import org.elasticsearch.client.ESRestHighLevelClientTestCase;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.cluster.metadata.RepositoryMetaData;
import org.elasticsearch.common.unit.TimeValue;

import java.io.IOException;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

import static org.hamcrest.Matchers.equalTo;

/**
* This class is used to generate the Java Cluster API documentation.
* You need to wrap your code between two tags like:
* // tag::example
* // end::example
*
* Where example is your tag name.
*
* Then in the documentation, you can extract what is between tag and end tags with
* ["source","java",subs="attributes,callouts,macros"]
* --------------------------------------------------
* include-tagged::{doc-tests}/SnapshotClientDocumentationIT.java[example]
* --------------------------------------------------
*
* The column width of the code block is 84. If the code contains a line longer
* than 84, the line will be cut and a horizontal scroll bar will be displayed.
* (the code indentation of the tag is not included in the width)
*/
public class SnapshotClientDocumentationIT extends ESRestHighLevelClientTestCase {

private static final String testRepository = "test_repository";

public void testSnapshotGetRepository() throws IOException {
RestHighLevelClient client = highLevelClient();

createTestRepositories();

// tag::get-repository-request
GetRepositoriesRequest request = new GetRepositoriesRequest();
// end::get-repository-request

// tag::get-repository-request-repositories
String [] repositories = new String[] { testRepository };
request.repositories(repositories); // <1>
// end::get-repository-request-repositories
// tag::get-repository-request-local
request.local(true); // <1>
// end::get-repository-request-local
// tag::get-repository-request-masterTimeout
request.masterNodeTimeout(TimeValue.timeValueMinutes(1)); // <1>
request.masterNodeTimeout("1m"); // <2>
// end::get-repository-request-masterTimeout

// tag::get-repository-execute
GetRepositoriesResponse response = client.snapshot().getRepositories(request);
// end::get-repository-execute

// tag::get-repository-response
List<RepositoryMetaData> repositoryMetaDataResponse = response.repositories();
// end::get-repository-response
assertThat(1, equalTo(repositoryMetaDataResponse.size()));
assertThat(testRepository, equalTo(repositoryMetaDataResponse.get(0).name()));
}

public void testSnapshotGetRepositoryAsync() throws InterruptedException {
RestHighLevelClient client = highLevelClient();
{
GetRepositoriesRequest request = new GetRepositoriesRequest();

// tag::get-repository-execute-listener
ActionListener<GetRepositoriesResponse> listener =
new ActionListener<GetRepositoriesResponse>() {
@Override
public void onResponse(GetRepositoriesResponse getRepositoriesResponse) {
// <1>
}

@Override
public void onFailure(Exception e) {
// <2>
}
};
// end::get-repository-execute-listener

// Replace the empty listener by a blocking listener in test
final CountDownLatch latch = new CountDownLatch(1);
listener = new LatchedActionListener<>(listener, latch);

// tag::get-repository-execute-async
client.snapshot().getRepositoriesAsync(request, listener); // <1>
// end::get-repository-execute-async

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

}

private void createTestRepositories() throws IOException {
RestHighLevelClient client = highLevelClient();
String repositorySettings = "{\"type\":\"fs\", \"settings\":{\"location\": \".\"}}";
highLevelClient().getLowLevelClient().performRequest("put", "_snapshot/" + testRepository, Collections.emptyMap(),
new StringEntity(repositorySettings, ContentType.APPLICATION_JSON));

}
}
Loading

0 comments on commit 83f8327

Please sign in to comment.