Skip to content

Commit

Permalink
Add high level rest client support for SetIndexLifecyclePolicy
Browse files Browse the repository at this point in the history
This adds HLRC support for the ILM operation of setting an index's lifecycle
policy.

It also includes extracting and renaming a number of classes (like the request
and response objects) as well as the addition of a new `IndexLifecycleClient`
for the HLRC. This is a prerequisite to making the `index.lifecycle.name`
setting internal only, because we require a dedicated REST endpoint to change
the policy, and our tests currently set this setting with the REST client
multiple places. A subsequent PR will change the setting to be internal and move
those uses over to this new API.

This misses some links to the documentation because I don't think ILM has any
documentation available yet.

Relates to elastic#29827 and elastic#29823
  • Loading branch information
dakrone committed Jul 27, 2018
1 parent 783e427 commit 2a075d4
Show file tree
Hide file tree
Showing 16 changed files with 622 additions and 314 deletions.
@@ -0,0 +1,65 @@
/*
* 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.elasticsearch.action.ActionListener;
import org.elasticsearch.protocol.xpack.indexlifecycle.SetIndexLifecyclePolicyRequest;
import org.elasticsearch.protocol.xpack.indexlifecycle.SetIndexLifecyclePolicyResponse;

import java.io.IOException;

import static java.util.Collections.emptySet;

public class IndexLifecycleClient {
private final RestHighLevelClient restHighLevelClient;

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

/**
* Set the index lifecycle policy for an index
* See <a href="https://fix-me-when-we-have-docs.com">
* the docs</a> for more.
* @param request the request
* @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
* @return the response
* @throws IOException in case there is a problem sending the request or parsing back the response
*/
public SetIndexLifecyclePolicyResponse setIndexLifecyclePolicy(SetIndexLifecyclePolicyRequest request,
RequestOptions options) throws IOException {
return restHighLevelClient.performRequestAndParseEntity(request, RequestConverters::setIndexLifecyclePolicy, options,
SetIndexLifecyclePolicyResponse::fromXContent, emptySet());
}

/**
* Asynchronously set the index lifecycle policy for an index
* See <a href="https://fix-me-when-we-have-docs.com">
* the docs</a> for more.
* @param request the request
* @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
* @param listener the listener to be notified upon request completion
*/
public void setIndexLifecyclePolicyAsync(SetIndexLifecyclePolicyRequest request, RequestOptions options,
ActionListener<SetIndexLifecyclePolicyResponse> listener) {
restHighLevelClient.performRequestAsyncAndParseEntity(request, RequestConverters::setIndexLifecyclePolicy, options,
SetIndexLifecyclePolicyResponse::fromXContent, listener, emptySet());
}
}
Expand Up @@ -39,12 +39,12 @@
import org.elasticsearch.action.admin.cluster.settings.ClusterGetSettingsRequest;
import org.elasticsearch.action.admin.cluster.settings.ClusterUpdateSettingsRequest;
import org.elasticsearch.action.admin.cluster.snapshots.create.CreateSnapshotRequest;
import org.elasticsearch.action.admin.cluster.snapshots.delete.DeleteSnapshotRequest;
import org.elasticsearch.action.admin.cluster.snapshots.get.GetSnapshotsRequest;
import org.elasticsearch.action.admin.cluster.snapshots.restore.RestoreSnapshotRequest;
import org.elasticsearch.action.admin.cluster.snapshots.status.SnapshotsStatusRequest;
import org.elasticsearch.action.admin.cluster.storedscripts.DeleteStoredScriptRequest;
import org.elasticsearch.action.admin.cluster.storedscripts.GetStoredScriptRequest;
import org.elasticsearch.action.admin.cluster.snapshots.delete.DeleteSnapshotRequest;
import org.elasticsearch.action.admin.cluster.snapshots.status.SnapshotsStatusRequest;
import org.elasticsearch.action.admin.indices.alias.IndicesAliasesRequest;
import org.elasticsearch.action.admin.indices.alias.get.GetAliasesRequest;
import org.elasticsearch.action.admin.indices.analyze.AnalyzeRequest;
Expand Down Expand Up @@ -78,8 +78,8 @@
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.ingest.DeletePipelineRequest;
import org.elasticsearch.action.ingest.GetPipelineRequest;
import org.elasticsearch.action.ingest.SimulatePipelineRequest;
import org.elasticsearch.action.ingest.PutPipelineRequest;
import org.elasticsearch.action.ingest.SimulatePipelineRequest;
import org.elasticsearch.action.search.ClearScrollRequest;
import org.elasticsearch.action.search.MultiSearchRequest;
import org.elasticsearch.action.search.SearchRequest;
Expand Down Expand Up @@ -107,9 +107,10 @@
import org.elasticsearch.index.VersionType;
import org.elasticsearch.index.rankeval.RankEvalRequest;
import org.elasticsearch.protocol.xpack.XPackInfoRequest;
import org.elasticsearch.protocol.xpack.watcher.PutWatchRequest;
import org.elasticsearch.protocol.xpack.XPackUsageRequest;
import org.elasticsearch.protocol.xpack.indexlifecycle.SetIndexLifecyclePolicyRequest;
import org.elasticsearch.protocol.xpack.license.PutLicenseRequest;
import org.elasticsearch.protocol.xpack.watcher.PutWatchRequest;
import org.elasticsearch.rest.action.search.RestSearchAction;
import org.elasticsearch.script.mustache.MultiSearchTemplateRequest;
import org.elasticsearch.script.mustache.SearchTemplateRequest;
Expand Down Expand Up @@ -1140,6 +1141,19 @@ static Request xpackUsage(XPackUsageRequest usageRequest) {
return request;
}

static Request setIndexLifecyclePolicy(SetIndexLifecyclePolicyRequest setPolicyRequest) {
Request request = new Request(HttpPut.METHOD_NAME,
new EndpointBuilder()
.addCommaSeparatedPathParts(setPolicyRequest.indices())
.addPathPartAsIs("_lifecycle")
.addPathPart(setPolicyRequest.policy())
.build());
Params params = new Params(request);
params.withIndicesOptions(setPolicyRequest.indicesOptions());
params.withMasterTimeout(setPolicyRequest.masterNodeTimeout());
return request;
}

static Request putLicense(PutLicenseRequest putLicenseRequest) {
Request request = new Request(HttpPut.METHOD_NAME, "/_xpack/license");
Params parameters = new Params(request);
Expand Down
Expand Up @@ -43,11 +43,13 @@ public final class XPackClient {
private final RestHighLevelClient restHighLevelClient;
private final WatcherClient watcherClient;
private final LicenseClient licenseClient;
private final IndexLifecycleClient indexLifecycleClient;

XPackClient(RestHighLevelClient restHighLevelClient) {
this.restHighLevelClient = restHighLevelClient;
this.watcherClient = new WatcherClient(restHighLevelClient);
this.licenseClient = new LicenseClient(restHighLevelClient);
this.indexLifecycleClient = new IndexLifecycleClient(restHighLevelClient);
}

public WatcherClient watcher() {
Expand Down Expand Up @@ -113,4 +115,15 @@ public void usageAsync(XPackUsageRequest request, RequestOptions options, Action
public LicenseClient license() {
return licenseClient;
}

/**
* A wrapper for the {@link RestHighLevelClient} that provides methods for
* accessing the Elastic Index Lifecycle APIs.
* <p>
* See the <a href="http://FILL-ME-IN-WE-HAVE-NO-DOCS-YET.com">
* X-Pack APIs on elastic.co</a> for more information.
*/
public IndexLifecycleClient indexLifecycle() {
return this.indexLifecycleClient;
}
}
@@ -0,0 +1,103 @@
/*
* 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.HttpEntity;
import org.apache.http.entity.ContentType;
import org.apache.http.nio.entity.NStringEntity;
import org.elasticsearch.action.admin.indices.settings.get.GetSettingsRequest;
import org.elasticsearch.action.admin.indices.settings.get.GetSettingsResponse;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.protocol.xpack.indexlifecycle.SetIndexLifecyclePolicyRequest;
import org.elasticsearch.protocol.xpack.indexlifecycle.SetIndexLifecyclePolicyResponse;

import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.is;

public class IndexLifecycleIT extends ESRestHighLevelClientTestCase {

public void testSetIndexLifecyclePolicy() throws Exception {
String policy = randomAlphaOfLength(10);

// TODO: convert this to using the high level client once there are APIs for it
String jsonString = "{\n" +
" \"policy\": {\n" +
" \"type\": \"timeseries\",\n" +
" \"phases\": {\n" +
" \"hot\": {\n" +
" \"after\": \"60s\",\n" +
" \"actions\": {\n" +
" \"rollover\": {\n" +
" \"max_age\": \"500s\"\n" +
" } \n" +
" }\n" +
" },\n" +
" \"warm\": {\n" +
" \"after\": \"1000s\",\n" +
" \"actions\": {\n" +
" \"allocate\": {\n" +
" \"require\": { \"_name\": \"node-1\" },\n" +
" \"include\": {},\n" +
" \"exclude\": {}\n" +
" },\n" +
" \"shrink\": {\n" +
" \"number_of_shards\": 1\n" +
" },\n" +
" \"forcemerge\": {\n" +
" \"max_num_segments\": 1000\n" +
" }\n" +
" }\n" +
" },\n" +
" \"cold\": {\n" +
" \"after\": \"2000s\",\n" +
" \"actions\": {\n" +
" \"replicas\": {\n" +
" \"number_of_replicas\": 0\n" +
" }\n" +
" }\n" +
" },\n" +
" \"delete\": {\n" +
" \"after\": \"3000s\",\n" +
" \"actions\": {\n" +
" \"delete\": {}\n" +
" }\n" +
" }\n" +
" }\n" +
" }\n" +
"}";
HttpEntity entity = new NStringEntity(jsonString, ContentType.APPLICATION_JSON);
Request request = new Request("PUT", "/_xpack/index_lifecycle/" + policy);
request.setEntity(entity);
client().performRequest(request);

createIndex("foo", Settings.builder().put("index.lifecycle.name", "bar").build());
createIndex("baz", Settings.builder().put("index.lifecycle.name", "eggplant").build());
SetIndexLifecyclePolicyRequest req = new SetIndexLifecyclePolicyRequest(policy, "foo", "baz");
SetIndexLifecyclePolicyResponse response = execute(req, highLevelClient().xpack().indexLifecycle()::setIndexLifecyclePolicy,
highLevelClient().xpack().indexLifecycle()::setIndexLifecyclePolicyAsync);
assertThat(response.hasFailures(), is(false));
assertThat(response.getFailedIndexes().isEmpty(), is(true));

GetSettingsRequest getSettingsRequest = new GetSettingsRequest().indices("foo", "baz");
GetSettingsResponse settingsResponse = highLevelClient().indices().getSettings(getSettingsRequest, RequestOptions.DEFAULT);
assertThat(settingsResponse.getSetting("foo", "index.lifecycle.name"), equalTo(policy));
assertThat(settingsResponse.getSetting("baz", "index.lifecycle.name"), equalTo(policy));
}
}
Expand Up @@ -126,6 +126,7 @@
import org.elasticsearch.index.rankeval.RatedRequest;
import org.elasticsearch.index.rankeval.RestRankEvalAction;
import org.elasticsearch.protocol.xpack.XPackInfoRequest;
import org.elasticsearch.protocol.xpack.indexlifecycle.SetIndexLifecyclePolicyRequest;
import org.elasticsearch.protocol.xpack.watcher.PutWatchRequest;
import org.elasticsearch.repositories.fs.FsRepository;
import org.elasticsearch.rest.action.search.RestSearchAction;
Expand Down Expand Up @@ -2580,6 +2581,25 @@ public void testXPackPutWatch() throws Exception {
assertThat(bos.toString("UTF-8"), is(body));
}

public void testSetIndexLifecyclePolicy() throws Exception {
SetIndexLifecyclePolicyRequest req = new SetIndexLifecyclePolicyRequest();
String policyName = randomAlphaOfLength(10);
String[] indices = randomIndicesNames(0, 10);
req.policy(policyName);
req.indices(indices);
Map<String, String> expectedParams = new HashMap<>();
setRandomMasterTimeout(req, expectedParams);
setRandomIndicesOptions(req::indicesOptions, req::indicesOptions, expectedParams);

Request request = RequestConverters.setIndexLifecyclePolicy(req);
assertThat(request.getMethod(), equalTo(HttpPut.METHOD_NAME));
String idxString = Strings.arrayToCommaDelimitedString(indices);
assertThat(request.getEndpoint(),
equalTo("/" + (idxString.isEmpty() ? "" : (idxString + "/")) +
"_lifecycle/" + policyName));
assertThat(request.getParameters(), equalTo(expectedParams));
}

/**
* Randomize the {@link FetchSourceContext} request parameters.
*/
Expand Down
Expand Up @@ -60,7 +60,7 @@
import org.elasticsearch.xpack.core.indexlifecycle.action.PutLifecycleAction;
import org.elasticsearch.xpack.core.indexlifecycle.action.RemovePolicyForIndexAction;
import org.elasticsearch.xpack.core.indexlifecycle.action.RetryAction;
import org.elasticsearch.xpack.core.indexlifecycle.action.SetPolicyForIndexAction;
import org.elasticsearch.xpack.core.indexlifecycle.action.SetIndexLifecyclePolicyAction;
import org.elasticsearch.xpack.core.logstash.LogstashFeatureSetUsage;
import org.elasticsearch.xpack.core.beats.BeatsFeatureSetUsage;
import org.elasticsearch.xpack.core.ml.MachineLearningFeatureSetUsage;
Expand Down Expand Up @@ -338,7 +338,7 @@ public List<Action<? extends ActionResponse>> getClientActions() {
GetLifecycleAction.INSTANCE,
PutLifecycleAction.INSTANCE,
ExplainLifecycleAction.INSTANCE,
SetPolicyForIndexAction.INSTANCE,
SetIndexLifecyclePolicyAction.INSTANCE,
RemovePolicyForIndexAction.INSTANCE,
MoveToStepAction.INSTANCE,
RetryAction.INSTANCE
Expand Down
@@ -0,0 +1,25 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

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

import org.elasticsearch.action.Action;
import org.elasticsearch.protocol.xpack.indexlifecycle.SetIndexLifecyclePolicyResponse;

public class SetIndexLifecyclePolicyAction extends Action<SetIndexLifecyclePolicyResponse> {

public static final SetIndexLifecyclePolicyAction INSTANCE = new SetIndexLifecyclePolicyAction();
public static final String NAME = "indices:admin/xpack/index_lifecycle/set_index_policy";

protected SetIndexLifecyclePolicyAction() {
super(NAME);
}

@Override
public SetIndexLifecyclePolicyResponse newResponse() {
return new SetIndexLifecyclePolicyResponse();
}
}

0 comments on commit 2a075d4

Please sign in to comment.